I can envision a couple of problems
1) You are reading from a file and printing directly from within the print function
If you open the file in the print function,
e.hasmorepages = true will cause the file to be opened a second time when the print function is subsequently called again, thus the first set of data that has already been written will be written again.
2) Printing multiple pages from dynamic data, which is essentially what you have when you read your data from a stream can be difficult to master because of several things:
All the data is written every time, it just does not show up on the page because it is out of the margin.
Each time the print function is called, the page number is incremented internally i.e. you don't manage this with code, thus your code must know exactly what has already been printed in any of the subsequent print calls.
3) By setting
e.hasmorepages = true and not verifying that there is actually more data to be printed, the code will continue to print over and over again, even if there is no data to be printed, thus you will print into infinity or until your system crashes due to resource overload.
Try this:
Define a private variable with a module wide scope. This will hold the number of lines that have already been printed successfully. In the
BeginPrint event, initialize this variable to 0, meaning you have not printed anything just yet.
In the
PrintPage event, increment that variable by 1 each time you successfully print a line on the page. You will have to check to ensure that the item you are printing will actually fit on the page by using
MeasureString with the coordinates of where it is to be printed.
When you read from the stream, if the line will not fit on the page, close the streamreader, you could otherwise end up with multiple file handles open and cause potential problems down the road, especially if the file is very big.
If the private variable is 0 when the
PrintPage event is fired, you will know that this is the first time the event has been fired, thus simply open the streamreader and start using
DrawString to put the lines on the page, however, if the private variable is anything else, then you will need to loop through your stream until the number of lines have been processed that match the number that have already been printed. i.e. pick up from the same location where you left off before.
What you might consider doing is creating a function that will increment the stream for you and just call that at the beginning of the
PrintPage event.
Something like:
SeekToStringInFile (ByVal strFilename As String, ByVal intLocation As Integer) As Stream
Of course, since you are reading the whole file en-masse you could make the file contents variable a private global, set it in the
BeginPrint event and then trim the already printed portions out of the string, until it is eventually an empty value.
In the end, after your page has printed, you will need to determine if there are more pages that are required to be printed. If there are, set
e.hasmorepages to
true, otherwise set it to
False.
I've put some of the things together in the following example, you will need to incorporate it in your program. I have not tested the code, so it may not be 100% correct.
Class MyPrintingClass
Private pathofFile As String
Private FileContents As String
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
'Make sure the FileContents are empty, just in case the last print event
'was cancelled or a glitch caused the var to not be completely empty.
FileContents = ""
End Sub
Private Sub PrintDocument_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
'Define our string format for proper printing
Dim strFmt As New StringFormat
strFmt.Alignment = StringAlignment.Near
strFmt.LineAlignment = StringAlignment.Near
strFmt.Trimming = StringTrimming.None
strFmt.FormatFlags = StringFormatFlags.LineLimit
Dim charsFitted As Integer
Dim linesFilled As Integer
'Our Font
Dim myFont As New Font("Lucida Console", 8)
'Read the file, if it hasn't been already
If FileContents.Length = 0 Then
Dim pathFile As New System.IO.StreamReader(pathofFile)
FileContents = pathFile.ReadToEnd
pathFile.Close()
End If
'Measure the contents according to the page
e.Graphics.MeasureString(FileContents, myFont, _
New Drawing.SizeF(e.MarginBounds.Width, e.MarginBounds.Height), _
strFmt, charsFitted, linesFilled)
'Print the contents
e.Graphics.DrawString(FileContents, myFont, Brushes.Black, 100, 3)
'Trim the printed portion out of the variable
FileContents = Right(FileContents, FileContents.Length - charsFitted)
'Call the print function again if there is more to be printed
If FileContents.Length > 0 Then
e.HasMorePages = True
Else
e.HasMorePages = False
End If
End Sub
End Class