Having both screen and printer output generated through identical GDI+ commands means that I can make this a really short chapter, referring you back to Chapter 17, "GDI+, "for details. But it also means that there needs to be a canvasa System.Drawing.Graphics objectwhere the printer-specific GDI+ commands target their output. The System.Drawing.Printing.PrintDocument class provides you with the output canvas you need for both ordinary printing and "print preview" output. There are three ways to use the PrintDocument class.
Add a PrintDocument control to a form from the Windows Forms toolbox. This control appears by default in the Toolbox's "Printing" section. Assign its properties and respond to its events as with any other control.
Create a class-level instance of the PrintDocument class. Include the With Events clause in the definition to get event management.
Create a local instance of PrintDocument, and connect any events using AddHandler.
These are standard methods in .NET, but having a control variation makes the class that much more convenient. We'll get into the actual printing code a little later.
There are four other printer-specific controls available for Windows Forms projects.
PageSetupDialog. This control presents a standard Windows printer settings dialog that lets the user configure a specific print job, or all print jobs for the application. The control's ShowDialog method displays the form shown in Figure 19-2. The control also exposes properties related to the user's selection. Its PageSettings member exposes specific user preferences as defined on the form, while the PrinterSettings member identifies the selected printer and its properties. You can retain these members and later assign them to other printer-specific classes that include similar members.
Figure 19-2. The Page Setup dialog
PrintDialog. Figure 19-3 shows this control's dialog, the standard dialog that appears in most programs when the user selects the File Print menu command. This control also exposes a PrinterSettings member used to assign or retrieve the selected printer and related options.
Figure 19-3. The Print dialog
PrintPreviewDialog. This dialog displays a preview of your printed document to the user. It includes standard preview presentation features, including zoom level and a pages-to-see-at-once control. The included Print button sends the preview content to the default printer (without prompting for printer selection). This control directly interacts with your PrintDocument instance, which drives the actual display content. Figure 19-4 shows the Print Preview dialog, although with no page-specific content.
Figure 19-4. The Print Preview dialog
PrintPreviewControl. The PrintPreviewDialog control includes basic preview management features (such as the zoom feature) that meet the needs of most applications. Unfortunately, that control is a sealed black box, and you cannot easily add your own custom features to it, or remove features that you don't want. The PrintPreviewControl control provides an alternative interface that lets you fully customize the print preview experience. Instead of a full dialog, it implements just the page-display portion of the form. You must implement all toolbars and other features, and link their functionality with the preview control. I won't be discussing this control in this chapter. If you're interested in using this advanced control, you can read an article I wrote about print preview a few years ago. (You can find the article referenced on my web site, http://www.timaki.com, in the articles section.)
Before you print, you need to know which printer your user wants to target for the output. You may also need to know about available features of the printer, such as whether it supports color or not. An early beta release of Visual Basic 2005 included a My.Computer.Printers collection. Unfortunately, that feature did not make it into the final product, so you will have to use more indirect means to access the printers.
The System.Drawing.Printing.PrinterSettings class includes a shared InstalledPrinters string collection that lists the path to each configured printer. You can assign any of these strings to the PrinterSettings' PrinterName member, making the specific printer available within the application. The following code chunk lets the user select from the list of printers, and displays some basic information about the selected printer.
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' ----- Display the list of printers. Dim scanPrinter As String For Each scanPrinter In Drawing.Printing. _ PrinterSettings.InstalledPrinters ListBox1.Items.Add(scanPrinter) Next scanPrinter End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click ' ----- Display information about the selected printer. Dim selectedPrinter As Drawing.Printing.PrinterSettings If (ListBox1.SelectedIndex = -1) Then Return selectedPrinter = New Drawing.Printing.PrinterSettings() selectedPrinter.PrinterName = ListBox1.Text MsgBox(selectedPrinter.ToString) End Sub