From: Zach on
<snipped>
Hi Pete,
>
> Thank you very much. I think I can make changes to allow for your comment,
> however, I might find your "print status" suggestion a difficult one to
> realize. I might like to get back on that one, after trying myself first,
> if I may.
>
> Many thanks,
> Zach.
-------

Pete,

Thank you for drawing my attention to the missing usings. That was bad. I
don't ususlly use dialogs and had spent my energy on getting them to work.

The change from "==" to "!=" was a learning experience. Thank you.

What I do not understand is the possibility of printing a blanc page.
Doesn't line = streamToPrint.ReadLine() = null stop that form happening? If
I am missing the cause of blanc pages being printed, wouldn't a way out be
to count the lines before I go in and check the counter value?

Zach.


From: Peter Duniho on
Zach wrote:
> [...]
> What I do not understand is the possibility of printing a blanc page.
> Doesn't line = streamToPrint.ReadLine() = null stop that form happening?

If the last line of the file winds up being printed as the very last
line possible on a page, then in this statement:

while (count < linesPerPage && ((line = streamToPrint.ReadLine()) !=
null))

The second half of the condition will never execute, because count <
linesPerPage is true. Then you'll set "ev.HasMorePages" to true,
because "line" is not null. Then the next time your PrintPage event
handler is called, it will finally call ReadLine() only to find that
there is no more data. But by that time, the page is already being
printed. So you'll get a blank page.

You can't fix the problem simply by using the non-short-circuiting &
operator instead of &&, because then you'll read a line at the end of
each page that will never get printed, because the string returned by
ReadLine() will be lost when the method returns.

To fix the problem, you should change the code so that the "line"
variable is not a local, but instead is in an instance of an object
(either the form itself along with the other stuff, or preferably in a
printing-specific object for that purpose along with the other
print-related data). Then you can always attempt to read the next line,
but only drawing the string if there's room, moving on to the next page
otherwise.

> If I am missing the cause of blanc pages being printed, wouldn't a way
> out be to count the lines before I go in and check the counter value?

You can read the file twice, counting lines first, and then reading it
again. Or you can read the file into an array of strings, one string
per line, before you start to print anything. Or any number of other
alternatives. But since it's possible to solve the problem storing just
one string between pages, it seems to me that's the most efficient approach.

Pete
From: Zach on
"Peter Duniho" <NpOeStPeAdM(a)NnOwSlPiAnMk.com> wrote in message
news:A9adnctYJ8An-IjRnZ2dnUVZ_qWdnZ2d(a)posted.palinacquisition...
> Zach wrote:
>> [...]
>> What I do not understand is the possibility of printing a blanc page.
>> Doesn't line = streamToPrint.ReadLine() = null stop that form happening?
>
> If the last line of the file winds up being printed as the very last line
> possible on a page, then in this statement:
>
> while (count < linesPerPage && ((line = streamToPrint.ReadLine()) !=
> null))
>
> The second half of the condition will never execute, because count <
> linesPerPage is true. Then you'll set "ev.HasMorePages" to true, because
> "line" is not null. Then the next time your PrintPage event handler is
> called, it will finally call ReadLine() only to find that there is no more
> data. But by that time, the page is already being printed. So you'll get
> a blank page.
>
> You can't fix the problem simply by using the non-short-circuiting &
> operator instead of &&, because then you'll read a line at the end of each
> page that will never get printed, because the string returned by
> ReadLine() will be lost when the method returns.
>
> To fix the problem, you should change the code so that the "line" variable
> is not a local, but instead is in an instance of an object (either the
> form itself along with the other stuff, or preferably in a
> printing-specific object for that purpose along with the other
> print-related data). Then you can always attempt to read the next line,
> but only drawing the string if there's room, moving on to the next page
> otherwise.
>
>> If I am missing the cause of blanc pages being printed, wouldn't a way
>> out be to count the lines before I go in and check the counter value?
>
> You can read the file twice, counting lines first, and then reading it
> again. Or you can read the file into an array of strings, one string per
> line, before you start to print anything. Or any number of other
> alternatives. But since it's possible to solve the problem storing just
> one string between pages, it seems to me that's the most efficient
> approach.
>
> Pete

------------------------------------------------------------------------

Pete, I am impressed by your comprehensive answers and grateful for them. I
will study your recent post carefully. Having applied nested "usings" to the
code in question, like you suggested, has made the code much more elegant
(and less bugged). I had already applied a counter, reading the .txt twice,
but will endeavour to improve that solution along the lines you suggested.
You didn't like the catch all, but I am unaware of the mishaps that might be
caught. So I haven't known what to do about that.

Thank you again.

Regards,

Zach.

From: Zach on


"Zach" <xx(a)yy.zz> wrote in message
news:ufvON06CLHA.5808(a)TK2MSFTNGP02.phx.gbl...
> "Peter Duniho" <NpOeStPeAdM(a)NnOwSlPiAnMk.com> wrote in message
> news:A9adnctYJ8An-IjRnZ2dnUVZ_qWdnZ2d(a)posted.palinacquisition...
>> Zach wrote:
>>> [...]

Pete, how about this solution?
Zach.

for (int count = 0; count < linesPerPage; count++ )
{
if ((line = streamToPrint.ReadLine()) != null)
{
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
}
}

if (!streamToPrint.EndOfStream)
ev.HasMorePages = true;
else
ev.HasMorePages = false;

From: Peter Duniho on
Zach wrote:
> Pete, how about this solution? [...]

Unfortunately, the EndOfStream property in StreamReader may not return
"true" until you've actually tried to read past the end of the stream;
you've got basically the same bug, but the manifestation has been pushed
down into the StreamReader class instead of being exposed in your own code.

And other than the use of that property, the code you posted is
logically equivalent to what you had before, except that you needlessly
run the "count" value up to the maximum lines per page for each page.

You should fix the problem using one of the other techniques I
recommended. If the idea of maintaining the most-recently-read line
from the StreamReader seems too hard to understand, then I would expect
that reading all the lines at once so that you have the total line count
before you even start printing should be simple enough.

Pete