Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preprocess PrintDocument to calculate the total number of pages before printing?

Tags:

.net

printing

In an answer to this question...

Printing page x of y in .Net

The accepted answer included this statement...

You don't have to print it twice, you just have to simulate printing the first time.

So, how can you pass through the document one time first without any output going to the printer or screen?

like image 828
Bill Avatar asked Aug 19 '11 02:08

Bill


1 Answers

You will need to create a printer device context and render your pages using that device context as a reference DC while keeping track of the number of pages you have rendered. This will have to be done outside the scope of the .NET Printing infrastructure.

  1. Obtain Reference Printer DC
  2. Create Bitmap based on Reference Printer DC
  3. Create Graphics object to draw on bitmap
  4. Render Page to bitmap using Graphics Object (Count Pages Here)
  5. More Data to Print? Goto 4

Here's a shot at step 1, assumes you're working in winforms...

 Private Function GetHighResolutionGraphics() As Graphics

        Try

            Dim HighestResolution As Printing.PrinterResolution = Nothing
            Dim HighestResolutionPrinter As String = ""
            Dim XResolution As Integer = Integer.MinValue

            Using dlg As New PrintDialog

                For Each Printer As String In Printing.PrinterSettings.InstalledPrinters
                    dlg.PrinterSettings.PrinterName = Printer
                    For Each Resolution As Printing.PrinterResolution In dlg.PrinterSettings.PrinterResolutions
                        Using gr As Graphics = dlg.PrinterSettings.CreateMeasurementGraphics()
                            If gr.DpiX > XResolution Then
                                HighestResolution = Resolution
                                HighestResolutionPrinter = Printer
                                XResolution = gr.DpiX
                            End If
                        End Using
                    Next
                Next

                dlg.PrinterSettings.PrinterName = HighestResolutionPrinter
                dlg.PrinterSettings.DefaultPageSettings.PrinterResolution = HighestResolution

                Return dlg.PrinterSettings.CreateMeasurementGraphics()

            End Using

        Catch ex As Exception
            ' handle or ignore .NET AccessViolation for certain network printers that are turned off, etc...
        End Try

        Return Me.CreateGraphics()

    End Function

Step 2 is "simply" using the returned Reference Graphics Object with your already implemented PagePrint event code to render the pages to an appropriate bitmap while keeping track of the number of pages you're rendering. Don't forget to refactor your PagePrint Event to a separate routine that accepts a Graphics object so it can be used for Printing, Previewing and Page Numbering. Don't forget to dispose of the Graphics object and the Bitmap

using gfxReference as Graphics = GetHighResolutionGraphics()
  using bmpPage as new Bitmap(gfxReference.DpiX * 8.5, gfxReference.DpiY * 11)
    using gfxRender as Graphics = Graphics.FromImage(bmpPage)
      gfxRender.Clear(Color.White)
      // Existing PagePrint event logic goes here (uses gfxRender)
      // Track Number of pages printed
    end using
  end using
end using
like image 191
Pyramid Avatar answered Oct 15 '22 13:10

Pyramid