Windows Forms 2.0 Programming (Microsoft .NET Development Series)

All print controller implementations rely on the print document's print events to gather the drawing commands into the Graphics object, either to spool to the printer or to show on the screen:

void printDocument_PrintPage(object sender, PrintPageEventArgs e) { // Draw to the e.Graphics object that wraps the print target Graphics g = e.Graphics; using( Font font = new Font("Lucida Console", 72) ) { g.DrawString("Hello,\nPrinter", font, Brushes.Black, 0, 0); } }

Notice that this sample PrintPage event handler creates a font only for printing. For a single page, this code is fine, because it creates the font and then reclaims the font resources when the printing is complete. However, if we're printing more than one page, it's wasteful to create the font anew on each page. On the other hand, creating a font for printing and then caching it in a field seems wasteful if the font is never used again after the print job. What we need is to be notified when a print job is started and ended so that we can have tight control over print-related resources. For this, we use the print document's BeginPrint and EndPrint events:

Font printerfont = null; void printDocument_BeginPrint(object sender, PrintEventArgs e) { // Create font for printing printerfont = new Font("Lucida Console", 72); } void printDocument_EndPrint(object sender, PrintEventArgs e) { // Reclaim font printerfont.Dispose(); printerfont = null; }

Notice that the BeginPrint and EndPrint event handlers are passed an instance of the PrintEventArgs class:

namespace System.Drawing.Printing { class PrintEventArgs : CancelEventArgs { // Properties public bool Cancel { get; set; } public PrintAction PrintAction { get; } // New } }

PrintEventArgs derives from CancelEventArgs to allow you to cancel a print operation if certain conditions aren't metfor example, a lack of data to print:

void printDocument_BeginPrint(object sender, PrintEventArgs e) { ... // Don't print if data not available to print if( myDataObject == null ) e.Cancel = true; }

PrintEventArgs.PrintAction provides information about the type of printing that is taking place, and is one of the values of the PrintAction enumeration:

namespace System.Drawing.Printing { enum PrintAction { PrintToFile = 0, PrintToPreview = 1, PrintToPrinter = 2 } }

This value is ultimately determined by the print controller that's being used; if PreviewPrintController is processing a print document, PrintAction has a value of PrintToPreview. Thus, PrintAction allows you to determine the type of print before printing takes place, information that PrintPage can use if it needs to tailor the output it generates on a per-target basis. The following code checks for a print preview, which receives special attention later in this chapter:

bool preview; ... void printDocument_BeginPrint(object sender, PrintEventArgs e) { ... // Print preview? preview = (e.PrintAction == PrintAction.PrintToPreview); }

Like BeginPrint, EndPrint is passed a PrintEventArgs object. Unlike BeginPrint and EndPrint, the PrintPage event comes with an instance of the PrintPageEventArgs class:

namespace System.Drawing.Printing { class PrintPageEventArgs : EventArgs { // Constructors public PrintPageEventArgs( Graphics graphics, Rectangle marginBounds, Rectangle pageBounds, PageSettings pageSettings); // Properties public bool Cancel { get; set; } public Graphics Graphics { get; } public bool HasMorePages { get; set; } public Rectangle MarginBounds { get; } public Rectangle PageBounds { get; } public PageSettings PageSettings { get; } } }

As you've seen, the Cancel property is used to cancel a print job, and the Graphics property is used for drawing. HasMorePages defaults to false. If there are more pages to print, you set HasMorePages to true during the PrintPage handler for all pages except the last page of a multipage document:

int totalPages = 13; int page; int maxPage; void printDocument_PrintPage(object sender,PrintPageEventArgs e) { //Draw to the e.Graphics object that wraps the print target Graphics g = e.Graphics; using(Font font = new Font("Lucida Console", 72) ) { g.DrawString("Hello,\nPrinter\nPage: " + page.ToString(), ...); } // Check whether there are more pages to print ++page; e.HasMorePages = ( page <= maxPage ); } void printPreviewDialogButton_Click(object sender, EventArgs e) { // Calculate print preview range page = 1; maxPage = totalPages; // Print this.printPreviewDialog.Document = this.printDocument; this.printPreviewDialog.ShowDialog(); }

This example has 13 pages, and as many as 6 can be shown in the print preview dialog at once (as shown in Figure 8.7).

Figure 8.7. Printing Multiple Pages

Категории