Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
120
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

700 Chapter 15 PRINTING WITH VB.NET

Printing simple reports (tabular data) is another common printing task. You can draw an outline of the printout on paper and then implement it with VB code. The data will most likely come from a database, so you don’t really need to create an application with an elaborate interface. Printing graphics is straightforward—but not typical in business applications. All the graphics commands you use to generate a graphic on the screen can be applied to the printer as well. The most complicated case is the printing of formatted text.

The examples of this section will address many of your day-to-day needs, and I’m including examples that will serve as your starting point for some of the most typical printing needs, from printing tabular data to bitmaps.

VB6 VB.NET

VB6 included some mechanisms to simplify the generation of simple printouts. These mechanisms are no longer available. On the plus side, VB.NET provides a unified approach for generating all types of printouts. Generating a preview, for example, is no longer a separate process. Whether you print on a printer or in the preview pane, the process is identical.

The Printing Objects

We’ll start our exploration of Visual Basic’s printing capabilities with an overview of the printing process, which is the same no matter what you print. Printing with VB.NET is equivalent to drawing on a Form or PictureBox object. VB.NET introduced several controls for generating output for the printer, and here’s a quick overview of these objects (you’ll find more information on these objects and examples in the following sections). You don’t need to use all these objects in your project. Only the PrintDocument object is required, and you will have to master the members of this control.

PrintDocument

This object represents your printer, and you must add a PrintDocument control to any project that generates printer output. In effect, everything you draw on the PrintDocument object is sent to the printer. The PrintDocument object represents the printing surface, and it exposes a Graphics object. You can program against the Graphics object using all the methods discussed in Chapter 14. 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. To print headers and footers, you supply the text to be printed, the coordinates on the page where the string will be printed, and the font in which the string will be rendered. 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.

To send something to the printer, you must first add an instance of the PrintDocument control to the project. This control is invisible at runtime, and its icon will appear on the Components tray at design time. When you’re ready to print, call the PrintDocument object’s Print method. This method isn’t going to produce any output, but it will raise the PrintPage event. This is where you must insert the code that generates output for the printer. The PrintPage event passes the e argument, which exposes the Graphics property of the current Printer object, among other members.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

THE PRINTING OBJECTS 701

This is same object we used in the previous chapter to generate all kinds of graphics. The printer has its own Graphics object, which represents the page you print on. All the methods that generate graphics can be applied to the printer’s Graphics object to print graphics on the page. The following statement initiates the printing:

PrintDocument1.Print

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, and add an instance of the PrintDocument object to the project. Enter the previous 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. 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. When you’ve finished, you set the e.HasMorePages property to False, and no more PrintPage events will be fired. Figure 15.1 outlines the printing process.

Figure 15.1

 

 

 

 

 

 

Event Handlers

 

 

All printing takes

 

 

 

 

 

 

 

 

place in the Print-

 

PrintDocument.Print

 

 

 

 

BeginPrint

 

 

 

Page event handler of

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Insert initialization code here

 

 

 

 

 

 

 

 

the PrintDocument

 

 

 

 

 

 

 

 

 

 

 

 

object.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PrintPage

 

 

 

 

 

 

 

 

 

 

Insert code to print next page

 

 

 

 

 

 

 

 

 

 

 

HasMorePages = True

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

HasMorePages = False

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

EndPrint

 

 

 

 

 

 

 

 

 

 

Insert clean-up code here

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Initialize the printing process…

 

 

 

and program these events to handle the printing.

 

 

 

 

 

 

 

 

 

 

 

 

 

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

Listing 15.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

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

702 Chapter 15 PRINTING WITH VB.NET

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.NET”, 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 Else

e.HasMorePages = False 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’m assuming you’re using an letter-size page, so I’ve hardcoded 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 its orientation, too.

You can draw anywhere you like on the page. The PrintDocument object accumulates all the graphics commands and sends them to the printer when the PrintPage event handler terminates. So, the order in which you place the various elements on the page doesn’t matter. You can also draw overlapping shapes, like placing text over a bitmap or drawing arrows over a chart.

The code of Listing 15.1 prints three pages, with the same text and different page numbers. While 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. Note that the pageNum variable was declared as static, so that it will retain its value between calls.

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 and 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.

PrintDialog

The PrintDialog control displays the standard Print dialog box, shown in Figure 15.2, which allows users to select a printer and set its properties. If you don’t display this dialog box, the output will be sent automatically to the default printer and will use the default settings of the printer. The Print

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

THE PRINTING OBJECTS 703

dialog box was discussed in Chapter 7, and you already know how to retrieve the selected printer, as well as the settings specified by the user, in the dialog box. In this chapter, you’ll see how to use these settings in the code that generates output for the printer.

Figure 15.2

The Print dialog box

Among other settings, the Print dialog box allows you to specify the range of pages to be printed. Before allowing users to select a range of pages, be sure that you have a way to skip any number of pages. If the user specifies pages 10 through 19, your code must calculate the section of the document that would normally be printed on the first nine pages, skip it, and start printing after that. If the printout is a report with a fixed number of rows per page, skipping pages is trivial. If the printout contains formatted text, you must repeat all the calculations to generate the first nine pages and ignore them (skip the statements that actually print the graphics). Starting a printout at a page other than the first one can be a challenge.

When you select a printer from this dialog box, it automatically becomes the active printer and any printout generated after the selection of the printer will be sent to this printer; you don’t have to insert any code to switch printers.

The actual printer to which you will send the output of your application is almost transparent to the printing code. The same commands will generate the same output on any printer. If you’re using a color printer, you may insert additional code to generate colored output. If you’re using a plotter, you’ll also want to print all the components of the same color together, to minimize the time spent by the plotter in changing pens. For the most common printers—that is, ink-jet and PostScript printers—you don’t have to modify a single statement. The same code will work with all printers.

It is also possible to set the printer from within your code with a statement like the following:

PrintDocument1.PrinterSettings.PrinterName = printer

where printer is the name of one of the installed printers. For more information on selecting a printer form within your code, see the section “Printer and Page Properties,” later in this chapter. There are situations where you want to set a printer from within your code and not give users a chance to change it. An application that prints invoices and reports, for example, must use a different printer for each type of printout.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com