Visual Basic.NET 2008 > Printing with Visual Basic

<< Previous Page Next Page >>

The PrintDocument Control in Visual Basic 2008

This object represents your printer, and you must add a PrintDocument control to any project that generates printouts. In effect, everything you draw on the PrintDocument object is sent to the printer. The PrintDocument object represents the printing device, and it exposes a Graphics object that represents the printing surface, just like the Graphics property of all Windows controls. You can program against the Graphics object by using all the graphics methods discussed in Chapter, "Drawing and Painting with Visual Basic 2008." If you can create drawings on a form, you can just as easily print them on your printer. To print text, for example, you must call the DrawString method. You can also print frames around the text with the DrawLine or DrawRectangle method. In general, you can use all the methods of the Graphics object to prepare the printout.

The PrintDocument control is invisible at runtime, and its icon will appear in the Components tray at design time. When you're ready to print, call the PrintDocument object's Print method. This method doesn't produce any output, but it does raise the control's BeginPrint and PrintPage events. The BeginPrint event is fired as soon as you call the Print method, and this is where you insert the printout's initialization code. The PrintPage event is fired once for every page of the printout, and this is where you must insert the code that generates output for the printer. Finally, the EndPrint event is fired when the printout ends, and this is where you insert the code to reset any global variables.

The following statement initiates the printing:


This statement is usually placed in a button's or a menu item's Click event handler. To experiment with simple printouts, create a new project, place a button on the form, add an instance of the PrintDocument object to the form, and enter the preceding statement in the button's Click event handler.

After the execution of this statement, the PrintDocument1 PrintPage event handler takes over. This event is fired for each page, so you insert the code to print the first page in this event's handler. The PrintPage event exposes the e argument, which gives you access to the Graphics property of the current Printer object. This is the same object we used in the two preceding chapters to generate all kinds of graphics. The printer has its own Graphics object, which represents the page you print on. If you need to print additional pages, you set the e.HasMorePages property to True just before you exit the event handler. This will fire another PrintPage event. The same process will repeat until you've printed everything. After you finish, you set the e.HasMorePages property to False, and no more PrintPage events will be fired. Instead, the EndPrint event will be fired and the printing process will come to an end. Figure 16.1 outlines the printing process.

All printing takes place in the PrintPage event handler of the PrintDocument object

Figure 16.1 - All printing takes place in the PrintPage event handler of the PrintDocument object

The code in Listing 16.1 shows the structure of a typical PrintPage event handler. The PrintPage event handler prints three pages with the same text but a different page number on each page.

Listing 16.1: A Simple PrintPage Event Handler

Private Sub PrintDocument1 PrintPage( _
        ByVal sender As Object, _    
        ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
        Handles PrintDocument1.PrintPage
    Static pageNum As Integer
    Dim prFont As New Font(”Verdana”, 24, GraphicsUnit.Point)
    e.Graphics.DrawString( _
        ”PAGE ” & pageNum + 1, prFont, _
        Brushes.Black, 700, 1050)
    e.Graphics.DrawRectangle(Pens.Blue, 0, 0, 300, 100)
        e.Graphics.DrawString( _
        ”Printing with VB 2008”, prFont, _
    Brushes.Black, 10, 10)
    ' Add more printing statements here
    ' Following is the logic that determines whether we're done printing
    pageNum = pageNum + 1
    If pageNum <= 3 Then
        e.HasMorePages = True
        e.HasMorePages = False
        pageNum = 0
    End If
End Sub

Notice that the page number is printed at the bottom of the page, but the corresponding statement is the first one in the subroutine. I assume that you're using a letter-size page, so I hard-coded the coordinates of the various elements in the code. Later in this chapter, you'll learn how to take into consideration not only the dimensions of the physical page, but also its orientation. The pageNum variable is declared as Static, so it retains its value between invocations of the event handler and isn't reset automatically. The last statement resets the pageNum variable in anticipation of another printout. Without this statement, the first page of the second printout (if you clicked the button again) would be page 4, and so on. Moreover, the printout would never come to an end because the pageNum variable would never become less than 3. Every time you repeat a printout, you must reset the global and static variables. This is a common task in printing with the PrintDocument control, and is a common source of many bugs.

Initialization of Static Variables

You can also declare variables such as the pageNum variable at the form's level, so that they'll retain their value between successive invocations of the PrintPage event handler. These variables can be reset in the PrintDocument's BeginPrint event handler, which is fired every time you start a new printout by calling the PrintDocument.Print method.

The code of Listing 16.1 above uses the methods of the e.Graphics object to generate the printout. After printing something and incrementing the page number, the code sets the e.HasMorePages property to True, to fire the PrintPage event again, this time to print the next page. As long as there are more pages to be printed, the program sets the e.HasMorePages property to True. After printing the last page, it sets the same argument to False to prevent further invocations of the PrintPage event. If you want to print a single page, you can ignore everything in this listing, except for the drawing methods that produce the output.

The entire printout is generated by the same subroutine, one page at a time. Because pages are not totally independent of one another, we need to keep some information in variables that are not initialized every time the PrintPage event handler is executed. The page number, for example, must be stored in a variable that will maintain its value between successive invocations of the PrintPage event handler, and it must be increased every time a new page is printed. If you're printing a text file, you must keep track of the current text line, so that each page will pick up where the previous one ended, not from the beginning of the document. You can use static variables or declare variables on the form's level, whatever suits you best. This is a recurring theme in programming the PrintPage event, and you'll see many more examples of this technique in the following sections. I can't stress enough the importance of resetting these variables at the end of a printout (or initializing them at the beginning of the printout).

<< Previous Page Next Page >>


Table of Contents

  1. Printing With Visual Basic
  2. The PrintDocument Control
  3. The PrintDialog Control
  4. The PageSetupDialog Control
  5. The PrintPreviewDialog Control
  6. Printer and Page Properties
  7. Retrieving the Printer Names & Page Geometry
  8. The SimplePrintout Example
  9. The PageSettings Example
  10. Printing Tabular Data
  11. Printing Plain Text
  12. Printing Bitmaps Copyright 2011 All Rights Reserved
  Home | Useful links | Contact us