|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
PrintDocument and HasMorePages issueWhen using the VB.NET PrintDocument class, I seem to be encountering an issue where the sub pd_PrintPage handles PrintDocument.PrintPage (upon continuing if HasMorePages = true) will paint the next page on top of the original page. In a sample data case where the source is long enough to fill three pages, I end up with four calls to pd_PrintPage which render onto two printed sheets. Historical posts in this forum from 2003 and 2005 suggested several tactics: 1) Explicitly call Exit Sub after setting HasMorePages = true 2) Defining the PrintDocument object in code instead of with the visual component 3) Avoiding the Addhandler statement before calling pd.Print(): AddHandler pd.PrintPage, AddressOf Me.pd_PrintPage In my current code, I have implemented # 1 and 2. I was unable to get any output under #3. Are there any further tactics to try? I remain suspicious of the AddHandler, though I haven't been able to work around it yet -- could I have two concurrent pd_PrintPage threads, rendering to the same target? It seems unlikely, because my page counter is incremented between these calls. I thought I had this resolved yesterday with this code as-is, but as it happens, it worked successfully to print 3 distinct pages under only one case: where I had put in debugging break at the start of pd_PrintPage and stepped through all steps. Even if I put in a few breaks, but "F5" to accelerate between them, the issue continues to occur. Nevertheless, I've been trying to identify the specific step (maybe I should introduce an artifical delay? In the print event model, is there a way to force the pd_PrintPage execution to wait for, ie, synchronous feedback from the printer before continuing to render the next page if I suspect the local network to the printer is slow?) I once suspected I was sloppy about margins (and have attempted in code to be somewhat cleaner), and that I may have pixels rendering outside the printable bounds of the page, but I don't think this would cause the PrintPage re-iteration to stay on the same sheet. Also, because the app worked on debug mode with the same data and graphic element positioning, I no longer suspect this angle. Is this something to pursue? Here is the code I'm working with. There is a button click event handler, a beginPrint which initializes PrintPageCount as a page counter, and the PrintPage sub, which uses the page counter to determine which elements from an array of my own user controls (ComponentCollection) to render on the page. This also drives my HasMorePages = T/F logic. PrintALabel and PrintATextbox are overloaded methods I wrote that apply the offset parameter to the object's location, and call appropriate graphics.DrawRectangle and graphics.DrawString methods. '**************************************************************** Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try 'Assumes the default printer. 'Dim pd As System.Drawing.Printing.PrintDocument = PrintDocument1 pd = New System.Drawing.Printing.PrintDocument() Dim margins As New Printing.Margins(25, 25, 25, 25) pd.DefaultPageSettings.Margins = margins AddHandler pd.PrintPage, AddressOf Me.pd_PrintPage ' pd.DefaultPageSettings.Landscape = True pd.Print() Catch ex As Exception MessageBox.Show(ex.Message, "An error occurred while printing") End Try End Sub '*************************************************************** Private Sub pd_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles pd.BeginPrint PrintPageCount = 0 FormLocation = Me.ComponentCollection(0).Location FormLocation.Y = FormLocation.Y - PrintDocument1.DefaultPageSettings.HardMarginY '- 20 FormLocation.X = PrintDocument1.DefaultPageSettings.HardMarginX 'Me.ScrollControlIntoView(Me.ComponentCollection(0)) End Sub '*************************************************************** Private Sub pd_PrintPage(ByVal sender As Object, ByVal ev As System.Drawing.Printing.PrintPageEventArgs) Handles pd.PrintPage ' Draw a picture. Dim thisFont As New System.Drawing.Font("Microsoft Sans Serif", 8.25!, CType((System.Drawing.FontStyle.Regular), System.Drawing.FontStyle), System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Dim thisFormat As New System.Drawing.StringFormat() 'In future, calculate components per page based on size and paper setting. Dim ComponentsPerPage As Single = 11 Dim indexStart As Integer = PrintPageCount * ComponentsPerPage Dim indexEnd As Integer Dim LastPage As Boolean = False If Me.ComponentCollection.Length - PrintPageCount * ComponentsPerPage <= ComponentsPerPage Then ' last page to print indexEnd = indexStart + Me.ComponentCollection.Length - PrintPageCount * ComponentsPerPage - 1 LastPage = True Else indexEnd = (PrintPageCount + 1) * ComponentsPerPage - 1 'indexStart + End If '' Me.ScrollControlIntoView(Me.ComponentCollection(indexStart)) Dim item As SingleComponentControl Dim i As Integer ' For Each item In Me.ComponentCollection For i = indexStart To indexEnd item = Me.ComponentCollection(i) Dim rePoint As New System.Drawing.Point(FormLocation.X, item.Location.Y - PrintPageCount * ComponentsPerPage * (item.Height + 5) - FormLocation.Y) ' +5 to height is spacing between components. item.PrinterCoord = rePoint ev.Graphics.DrawRectangle(Pens.Gray, item.PrinterCoord.X, item.PrinterCoord.Y, item.Width - 80, item.Height) PrintATextbox(item.txtConsumed, item, ev, Drawing2D.HatchStyle.Percent50) PrintATextbox(item.txtOnHand, item, ev, Drawing2D.HatchStyle.Percent05) PrintATextbox(item.TxtOutstanding, item, ev, Drawing2D.HatchStyle.Percent75) Dim lblpt As New Point(5, 36) PrintALabel(item.Label1, item, ev, lblpt) Dim shiftleft As New Point(-50, 0) PrintALabel(item.Label2, item, ev, shiftleft) ' ... etc. Several more labels removed for clarity PrintALabel(item.Label11, item, ev, shiftleft) Next i ' iterate page count, footer, and test PrintPageCount = PrintPageCount + 1 'footer with current page number ev.Graphics.DrawString("Inventory/Component Report for Job " + JobNumber.ToString + " -- Page " + PrintPageCount.ToString, thisFont, Brushes.Black, 40, 950) ' ev.HasMorePages = False If Not LastPage Then ev.HasMorePages = True Exit Sub Else ev.HasMorePages = False End If End Sub '*********************************************************** Thank you to anyone for any insight into this issue. Regards, Keith Gerritsen I have a solution, but I'm not jazzed by it. I moved the page-count
initialization to the button event, and wrapped a Where around the pd.Print(): PrintPageCount = 0 Dim LastPage As Boolean = False While Not LastPage 'try print as separate docs... 'pd.Print() If Me.ComponentCollection.Length - PrintPageCount * ComponentsPerPage <= ComponentsPerPage Then ' last page to print LastPage = True Else LastPage = False End If pd.Print() PrintPageCount = PrintPageCount + 1 End While It still calls the PrintPage twice for each page, but as I don't increment PrintPageCount in this procedure any more, rendering twice on each output is of no consequence. I am managing my page counts and printing each page as a separate 1-page document now. It works, and I'm done with this, but I don't exactly like it. If I was going to implement a "cancel print" feature, it would be a pain to accomodate. Regards, Keith ki***@drexel.edu wrote: Show quoteHide quote > Hello, > > When using the VB.NET PrintDocument class, I seem to be encountering an > issue where the sub pd_PrintPage handles PrintDocument.PrintPage (upon > continuing if HasMorePages = true) will paint the next page on top of > the original page. In a sample data case where the source is long > enough to fill three pages, I end up with four calls to pd_PrintPage > which render onto two printed sheets. Historical posts in this forum > from 2003 and 2005 suggested several tactics: > > 1) Explicitly call Exit Sub after setting HasMorePages = true > 2) Defining the PrintDocument object in code instead of with the visual > component > 3) Avoiding the Addhandler statement before calling pd.Print(): > AddHandler pd.PrintPage, AddressOf Me.pd_PrintPage > > In my current code, I have implemented # 1 and 2. I was unable to get > any output under #3. Are there any further tactics to try? > > I remain suspicious of the AddHandler, though I haven't been able to > work around it yet -- could I have two concurrent pd_PrintPage threads, > rendering to the same target? It seems unlikely, because my page > counter is incremented between these calls. > > I thought I had this resolved yesterday with this code as-is, but as it > happens, it worked successfully to print 3 distinct pages under only > one case: where I had put in debugging break at the start of > pd_PrintPage and stepped through all steps. > > Even if I put in a few breaks, but "F5" to accelerate between them, the > issue continues to occur. Nevertheless, I've been trying to identify > the specific step (maybe I should introduce an artifical delay? In the > print event model, is there a way to force the pd_PrintPage execution > to wait for, ie, synchronous feedback from the printer before > continuing to render the next page if I suspect the local network to > the printer is slow?) > > I once suspected I was sloppy about margins (and have attempted in code > to be somewhat cleaner), and that I may have pixels rendering outside > the printable bounds of the page, but I don't think this would cause > the PrintPage re-iteration to stay on the same sheet. Also, because > the app worked on debug mode with the same data and graphic element > positioning, I no longer suspect this angle. Is this something to > pursue? > > Here is the code I'm working with. There is a button click event > handler, a beginPrint which initializes PrintPageCount as a page > counter, and the PrintPage sub, which uses the page counter to > determine which elements from an array of my own user controls > (ComponentCollection) to render on the page. This also drives my > HasMorePages = T/F logic. PrintALabel and PrintATextbox are overloaded > methods I wrote that apply the offset parameter to the object's > location, and call appropriate graphics.DrawRectangle and > graphics.DrawString methods. > > '**************************************************************** > Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As > System.EventArgs) Handles Button1.Click > Try > 'Assumes the default printer. > 'Dim pd As System.Drawing.Printing.PrintDocument = > PrintDocument1 > pd = New System.Drawing.Printing.PrintDocument() > > Dim margins As New Printing.Margins(25, 25, 25, 25) > pd.DefaultPageSettings.Margins = margins > > AddHandler pd.PrintPage, AddressOf Me.pd_PrintPage > ' pd.DefaultPageSettings.Landscape = True > pd.Print() > Catch ex As Exception > MessageBox.Show(ex.Message, "An error occurred while > printing") > End Try > End Sub > > '*************************************************************** > > Private Sub pd_BeginPrint(ByVal sender As Object, ByVal e As > System.Drawing.Printing.PrintEventArgs) Handles pd.BeginPrint > PrintPageCount = 0 > FormLocation = Me.ComponentCollection(0).Location > FormLocation.Y = FormLocation.Y - > PrintDocument1.DefaultPageSettings.HardMarginY '- 20 > FormLocation.X = PrintDocument1.DefaultPageSettings.HardMarginX > 'Me.ScrollControlIntoView(Me.ComponentCollection(0)) > End Sub > > '*************************************************************** > > Private Sub pd_PrintPage(ByVal sender As Object, ByVal ev As > System.Drawing.Printing.PrintPageEventArgs) Handles pd.PrintPage > ' Draw a picture. > Dim thisFont As New System.Drawing.Font("Microsoft Sans Serif", > 8.25!, CType((System.Drawing.FontStyle.Regular), > System.Drawing.FontStyle), System.Drawing.GraphicsUnit.Point, CType(0, > Byte)) > Dim thisFormat As New System.Drawing.StringFormat() > > 'In future, calculate components per page based on size and > paper setting. > Dim ComponentsPerPage As Single = 11 > > Dim indexStart As Integer = PrintPageCount * ComponentsPerPage > Dim indexEnd As Integer > Dim LastPage As Boolean = False > > If Me.ComponentCollection.Length - PrintPageCount * > ComponentsPerPage <= ComponentsPerPage Then > ' last page to print > indexEnd = indexStart + Me.ComponentCollection.Length - > PrintPageCount * ComponentsPerPage - 1 > LastPage = True > Else > indexEnd = (PrintPageCount + 1) * ComponentsPerPage - 1 > 'indexStart + > End If > '' > Me.ScrollControlIntoView(Me.ComponentCollection(indexStart)) > > Dim item As SingleComponentControl > Dim i As Integer > ' For Each item In Me.ComponentCollection > For i = indexStart To indexEnd > item = Me.ComponentCollection(i) > > Dim rePoint As New System.Drawing.Point(FormLocation.X, > item.Location.Y - PrintPageCount * ComponentsPerPage * (item.Height + > 5) - FormLocation.Y) > ' +5 to height is spacing between components. > item.PrinterCoord = rePoint > > ev.Graphics.DrawRectangle(Pens.Gray, item.PrinterCoord.X, > item.PrinterCoord.Y, item.Width - 80, item.Height) > PrintATextbox(item.txtConsumed, item, ev, > Drawing2D.HatchStyle.Percent50) > PrintATextbox(item.txtOnHand, item, ev, > Drawing2D.HatchStyle.Percent05) > PrintATextbox(item.TxtOutstanding, item, ev, > Drawing2D.HatchStyle.Percent75) > Dim lblpt As New Point(5, 36) > PrintALabel(item.Label1, item, ev, lblpt) > Dim shiftleft As New Point(-50, 0) > PrintALabel(item.Label2, item, ev, shiftleft) > ' ... etc. Several more labels removed for clarity > PrintALabel(item.Label11, item, ev, shiftleft) > Next i > > ' iterate page count, footer, and test > > PrintPageCount = PrintPageCount + 1 > > 'footer with current page number > ev.Graphics.DrawString("Inventory/Component Report for Job " + > JobNumber.ToString + " -- Page " + PrintPageCount.ToString, thisFont, > Brushes.Black, 40, 950) > ' ev.HasMorePages = False > > If Not LastPage Then > ev.HasMorePages = True > Exit Sub > Else > ev.HasMorePages = False > End If > End Sub > > '*********************************************************** > Thank you to anyone for any insight into this issue. > > Regards, > Keith Gerritsen
Problem calling a Sub in another form
WebBrowser - Excel processs till running Random Numbers Not Being Random Why is PeekChar causing a problem? Q: Copying part of a table Write commands to the COM port Question in re LIKE in VB 2005 Refresh/Blinking Problems with VB.NET Application TextFieldParser - reading tab delimited file Calling Subprocedures |
|||||||||||||||||||||||