Lesson 1: Implementing Print Functionality

Lesson 1: Implementing Print Functionality

Printing data and documents is a common task in any business setting. The .NET Framework provides the PrintDocument component to facilitate printing and a host of other classes to support and configure your printer settings. In this lesson, you will learn how to create and configure a PrintDocument object, and how to use it to print text, text files, and graphics.

After this lesson, you will be able to

  • Describe how to create and configure a PrintDocument object

  • Explain how to print text

  • Describe how to print graphics

  • Describe how to use the PrintPreview control and the Print Preview dialog box

  • Explain how to configure page settings with the PageSetupDialog control

  • Describe how to implement printer selection with the PrintDialog control

Estimated lesson time: 45 minutes

Printing will undoubtedly play a major part in your business applications. Although electronic file and document storage is increasingly popular, printed material will not be replaced in the near future. Thus, you must be able to implement print capability in your applications. The .NET Framework provides classes and components that allow you to quickly and easily implement print support for your programs.

The PrintDocument Component

A printed document is represented by the PrintDocument component in the .NET Framework. Although it is not a control with a visual component, the PrintDocument component can be found on the Windows Forms tab of the Toolbox, from where it can be added to your application in the designer.

The PrintDocument object encapsulates all of the information necessary to print a page. It exposes a PrinterSettings property that contains information about the capabilities and settings of the printers; a DefaultPageSettings property that encapsulates the configuration for printing each printed page; and a PrintController property that describes how each page is guided through the printing process. Through these properties, it is possible to attain an exacting level of control over the print process.

Creating a PrintDocument Object

You can create a PrintDocument object either in the designer at design time or in code at run time. You can drag an instance of the PrintDocument object directly from the Toolbox to the designer. The new instance appears in the component tray and is automatically configured to work with the system s default printer.

You can also create an instance in code, as follows:

Visual Basic .NET

' Assumes Imports System.Drawing.Printing Dim myPrintDocument As New PrintDocument()

Visual C#

// Assumes using System.Drawing.Printing; PrintDocument myPrintDocument = new PrintDocument();

An instance created in code is also automatically configured to work with the default system printer.

How Printing Works

In the .NET Framework printing model, printed content is provided directly by the application logic. A print job is initiated by the PrintDocument.Print method. This starts the print job and then raises one or more PrintPage events. If there is no client method to handle this event, printing does not take place. By providing a method to handle this event, you can specify the content to be printed.

If the print job contains multiple pages, one PrintPage event is raised for each page in the job. This, in turn, causes the method handling the PrintPage event to execute multiple times. Thus, that method must implement some functionality to track the print job and ensure that successive pages of a multipage document are printed. Otherwise, the first page of the document will print multiple times.

The PrintPage Event

The PrintPage event is the main event involved in printing documents. To actually send content to the printer, you must handle this event and provide code to render the content in the PrintPage event handler. All of the objects and information needed to send content to the printer is wrapped in the PrintPageEventArgs object, which is received by this event handler. The PrintPageEventArgs object contains the properties listed in Table 8.1.

Table 8-1. Properties of the PrintPageEventArgs Object

Property

Description

Cancel

Indicates whether or not a print job should be canceled

Graphics

The Graphics object used to render content to the printed page

HasMorePages

Gets or sets a value indicating whether additional pages should be printed

MarginBounds

Gets the Rectangle object that represents the portion of the page within the margins

PageBounds

Gets the Rectangle object that represents the total page area

PageSettings

Gets or sets the PageSettings object for the current page

Content is rendered to the printed page by the Graphics object provided in the PrintPageEventArgs object. The printed page in this case behaves just like a form, control or any other drawing surface that can be represented by a Graphics object. To render content, you use the same methods used to render content to a form. The following code example, where the content inscribes an ellipse inside the bounds of the margin, demonstrates a simple method to print a page:

Visual Basic .NET

' This method must handle the PrintPage event in order to be executed Public Sub PrintEllipse(ByVal sender As System.Object, ByVal e As _ System.Drawing.Printing.PrintPageEventArgs) e.Graphics.DrawEllipse(Pens.Black, e.MarginBounds) End Sub

Visual C#

// This method must handle the PrintPage event in order to be executed public void PrintEllipse(object sender, System.Drawing.Printing.PrintPageEventArgs e) { e.Graphics.DrawEllipse(Pens.Black, e.MarginBounds); }

The MarginBounds and PageBounds properties represent areas of the page surface. You can specify printing to occur inside the margin bounds of the page by calculating printing coordinates based on the MarginBounds rectangle. Printing that is to take place outside the margin bounds, such as headers or footers, can be specified by calculating the printing coordinates based on the PageBounds rectangle. As with painting to the screen, print coordinates are in pixels by default.

You can specify that a print job has multiple pages by using the HasMorePages property. By default, this property is set to false. When your program logic determines that multiple pages are required to print a job, you should set this property to true. When the last page is printed, the property should be reset to false.

NOTE
The method handling the PrintPage event must keep track of the number of pages in the job. Failure to do so can cause unexpected results while printing. For example, if you fail to set the HasMorePages property to false after the last page is printed, the application will continue to raise PrintPage events.

You can also cancel a print job without finishing the current page by setting the Cancel property to true.

You can create an event handler for the PrintPage event by double-clicking the PrintDocument instance in the designer to create a default event handler or by declaring the event handler in code as described in Chapter 3.

Printing Content

Initiating a print job is as easy as calling the PrintDocument.Print method. In this section, you will learn how to create the code that determines what content is sent to the printer.

Printing Graphics

Printing graphics is as easy as rendering them to the screen. You use the Graphics object supplied by PrintPageEventArgs to render graphics to the screen. Simple shapes can be printed, or complex shapes can be created and printed, using the GraphicsPath object. The following code example shows how to print a complex shape with a GraphicsPath object:

Visual Basic .NET

' This method must handle the PrintPage event Public Sub PrintGraphics(ByVal Sender As System.Object, _ ByVal e As System.Drawing.Printing.PrintPageEventArgs) Dim myPath As New System.Drawing.Drawing2D.GraphicsPath() myPath.AddPolygon(New Point() {New Point(1, 1), _ New Point(12, 55), New Point(34, 8), New Point(52, 53), _ New Point(99, 5)}) myPath.AddRectangle(New Rectangle(33, 43, 20, 20)) e.Graphics.DrawPath(Pens.Black, myPath) End Sub

Visual C#

// This method must handle the PrintPage event public void PrintGraphics(object sender, System.Drawing.Printing.PrintPageEventArgs e) { System.Drawing.Drawing2D.GraphicsPath myPath = new System.Drawing.Drawing2D.GraphicsPath(); myPath.AddPolygon(new Point[] {new Point(1, 1), new Point(12, 55), new Point(34, 8), new Point(52, 53), new Point(99, 5)}); myPath.AddRectangle(new Rectangle(33, 43, 20, 20)); e.Graphics.DrawPath(Pens.Black, myPath); }

To print a graphics job that has multiple pages, you must manually divide the job among pages and implement the appropriate logic. For example, the following method uses two pages to draw an ellipse that is twice as long as the page length:

Visual Basic .NET

Dim FirstPagePrinted As Boolean = False ' This method must handle the PrintPage event Public Sub PrintBigEllipse(ByVal Sender As System.Object, ByVal _ e As System.Drawing.Printing.PrintPageEventArgs) If FirstPagePrinted = False Then FirstPagePrinted = True e.HasMorePages = True e.Graphics.DrawEllipse(Pens.Black, New Rectangle(0, 0, _ e.PageBounds.Width, e.PageBounds.Height * 2)) Else e.HasMorePages = False FirstPagePrinted = False e.Graphics.DrawEllipse(Pens.Black, New Rectangle(0, _ -(e.PageBounds.Height), e.PageBounds.Width, _ e.PageBounds.Height * 2)) End If End Sub

Visual C#

bool FirstPagePrinted = false; // This method must handle the PrintPage event public void PrintBigEllipse(object sender, System.Drawing.Printing.PrintPageEventArgs e) { if (FirstPagePrinted == false) { FirstPagePrinted = true; e.HasMorePages = true; e.Graphics.DrawEllipse(Pens.Black, new Rectangle(0, 0, e.PageBounds.Width, e.PageBounds.Height * 2)); } else { e.HasMorePages = false; FirstPagePrinted = false; e.Graphics.DrawEllipse(Pens.Black, new Rectangle(0, -(e.PageBounds.Height), e.PageBounds.Width, e.PageBounds.Height * 2)); } }

This example uses the FirstPagePrinted variable to keep track of whether the first page or the second page is printing. Note that this variable is declared outside the method. If this variable were declared inside the method, it would reinitialize every time the method executed, and thus always return false. As the program prints each page, it redraws the image each time, changing the position of the ellipse s rectangle so as to orient the ellipse correctly across both pages.

Printing Text

Text is printed in the same way it is rendered to the screen. The Graphics.DrawString method is used to output text to the printer. As with rendering text to the screen, to print you must specify a font for rendering the text, text to render, a Brush object, and coordinates at which to print. For example:

Visual Basic .NET

Dim myfont As New Font("Batang", 36, FontStyle.Regular, _ GraphicsUnit.Pixel) Dim Hello As String = "Hello World!" e.Graphics.DrawString(Hello, myfont, Brushes.Black, 30, 30)

Visual C#

Font myfont = new Font("Batang", 36, FontStyle.Regular, GraphicsUnit.Pixel); string Hello = "Hello World!"; e.Graphics.DrawString(Hello, myfont, Brushes.Black, 30, 30);

NOTE
When printing text, you must take steps in your code to ensure that you do not attempt to print outside the bounds of the page. If you do attempt to print outside the bounds of the page, any content that falls outside the page bounds will not be printed.

Printing Multiple Lines

When printing multiple lines of text, such as an array of strings or lines read from a text file, you must include logic to calculate the line spacing. You can calculate the number of lines per page by dividing the height of the margin bounds by the height of the font. Similarly, you can calculate the position of each line by multiplying the line number by the height of the font. The following code example demonstrates how to print an array of strings called myStrings:

Visual Basic .NET

' This variable keeps track of the current position in the array. ' It must be declared outside the method that handles the ' PrintPage event in order to keep from being reinitialized with ' each page Dim ArrayCounter As Integer = 0 ' This method handles a PrintDocument.PrintPage event. It assumes ' an array of strings called myStrings() has been declared and ' populated elsewhere in the application. It also assumes a font ' for printing has been initialized and called myFont Private Sub PrintStrings(sender As Object, e As _ PrintPageEventArgs) ' Declares the variables that will be used to keep track of ' spacing and paging Dim LeftMargin As Single = e.MarginBounds.Left Dim TopMargin As Single = e.MarginBounds.Top Dim MyLines As Single = 0 Dim YPosition As Single = 0 Dim Counter As Integer = 0 Dim CurrentLine As String ' Calculate the number of lines per page. MyLines = e.MarginBounds.Height / _ myFont.GetHeight(e.Graphics) ' Prints each line of the file, but stops at the end of a page While Counter < MyLines And ArrayCounter <= _ myStrings.GetUpperBound(0) CurrentLine = myStrings(ArrayCounter) YPosition = TopMargin + Counter * _ myFont.GetHeight(e.Graphics) e.Graphics.DrawString(CurrentLine, myFont, Brushes.Black, _ LeftMargin, YPosition, New StringFormat()) Counter += 1 ArrayCounter += 1 End While ' If more lines exist, print another page. If Not (ArrayCounter = myStrings.GetUpperBound(0)) Then e.HasMorePages = True Else e.HasMorePages = False End If End Sub

Visual C#

// This variable keeps track of the current position in the // array. It must be declared outside the method that handles the // PrintPage event in order to keep from being reinitialized with // each page int ArrayCounter = 0; // This method handles a PrintDocument.PrintPage event. It // assumes an array of strings called myStrings() has been // declared and populated elsewhere in the application. It also // assumes a font for printing has been initialized and called // myFont private void PrintStrings(object sender, PrintPageEventArgs e) { // Declares the variables that will be used to keep track of // spacing and paging float LeftMargin = e.MarginBounds.Left; float TopMargin = e.MarginBounds.Top; float MyLines = 0; float YPosition = 0; int Counter = 0; string CurrentLine; // Calculate the number of lines per page. MyLines = e.MarginBounds.Height / myFont.GetHeight(e.Graphics); // Prints each line of the file, but stops at the end of a // page while (Counter < MyLines && ArrayCounter <= myStrings.GetUpperBound(0)) { CurrentLine = myStrings[ArrayCounter]; YPosition = TopMargin + Counter * myFont.GetHeight(e.Graphics); e.Graphics.DrawString(CurrentLine, myFont, Brushes.Black, LeftMargin, YPosition, new StringFormat()); Counter ++; ArrayCounter ++; } // If more lines exist, print another page. if (!(ArrayCounter == myStrings.GetUpperBound(0))) e.HasMorePages = true; else e.HasMorePages = false; }

Using Color

If your printer supports color printing, you will want to use a different set of printing options than when you are printing to a black-and-white printer. For example, some colors that are easily discernable on the screen appear much different when printed. If you are designing your application to work with color printers, you should provide alternative logic to accommodate black-and-white printers.

You can determine if the current printer supports printing color by retrieving the PrinterSettings.SupportsColor property. If the printer supports color, the DefaultPageSettings.Color property will be set to true, and the printer will print in color by default. If you want to force black-and-white printing, even if you have a color page and a color printer, set the DefaultPageSettings.Color property to false. The following code example demonstrates how to provide alternative printing logic based on the PrinterSettings.SupportsColor property.

Visual Basic .NET

' This example assumes Imports System.Drawing, ' System.Drawing.Drawing2D, and System.Drawing.Printing Dim BrushOne As Brush Dim BrushTwo As Brush If PrintDocument1.PrinterSettings.SupportsColor = True Then ' Provides brushes in color for color printing BrushOne = Brushes.Red BrushTwo = Brushes.Blue Else ' Provides HatchedBrushes for black-and-white printing BrushOne = New HatchBrush(HatchStyle.DarkVertical, Color.Black) BrushTwo = New HatchBrush(HatchStyle.DashedHorizontal, _ Color.Black) End If

Visual C#

// This example assumes Imports System.Drawing, // System.Drawing.Drawing2D, and System.Drawing.Printing Brush BrushOne; Brush BrushTwo; if (printDocument1.PrinterSettings.SupportsColor == true) { // Provides brushes in color for color printing BrushOne = Brushes.Red; BrushTwo = Brushes.Blue; } else { // Provides HatchedBrushes for black-and-white printing BrushOne = new HatchBrush(HatchStyle.DarkVertical, Color.Black); BrushTwo = new HatchBrush(HatchStyle.DashedHorizontal, Color.Black); }

To enable printing in your application

  1. From the Toolbox, drag an instance of PrintDocument to the designer. The PrintDocument component appears in the component tray and is automatically configured with the default printer. You can also create a new PrintDocument in code.

  2. Create a method to handle the PrintDocument.PrintPage event.

  3. Add application logic to the PrintPage event handler to render the content to the printed screen. Use the PrintPageEventArgs.Graphics object to render the content to the printer.

  4. If working with multipage documents, add logic to your application to keep track of paging.

Using PrintPreviewControl

The .NET Framework provides a PrintPreviewControl control to allow you to graphically preview print content before it is sent to the printer. The PrintPreviewControl control can be found on the Windows Forms tab of the Toolbox, and you can add an instance of it by dragging it onto your form.

In order to preview a page, the PrintPreviewControl control must be associated with a PrintDocument instance. This association is created by setting the Print PreviewControl.Document property as follows:

Visual Basic .NET

myPrintPreview.Document = myPrintDocument

Visual C#

myPrintPreview.Document = myPrintDocument;

When this association is made, the PrintPreviewControl control will display the content that is to be printed in the control. This is accomplished by invoking the method that handles the PrintDocument.Print event and capturing the graphics output from that method. This output is then rendered in the PrintPreviewControl control.

As program conditions change, the printed document might change as well. You can update the preview by calling the InvalidatePreview method as follows:

Visual Basic .NET

myPrintPreview.InvalidatePreview()

Visual C#

myPrintPreview.InvalidatePreview();

This causes the page displayed by the PrintPreviewControl control to be refreshed.

Another important property of the PrintPreviewControl control is the Zoom property. Zoom specifies the magnification level at which the preview is displayed. A value of 1 causes the preview to be displayed at full size. A fractional value reduces the image, and a value greater than 1 enlarges it.

PrintPreviewDialog

The PrintPreviewControl control is a valuable resource for previewing your printed documents and creating custom previews. However, for most applications, a standard suite of print preview functionality is adequate. The .NET Framework provides a standard PrintPreviewDialog control that exposes the most commonly used print preview functionality. The dialog box that the PrintPreviewDialog control creates is shown in Figure 8.1.

figure 8-1 the printpreviewdialog dialog box.

Figure 8-1. The PrintPreviewDialog dialog box.

You can preview a document by setting the Document property of the PrintPreviewDialog object to the PrintDocument object you want to preview. Once displayed, the PrintPreviewDialog control provides functionality to view multiple pages of the preview, to zoom, or to print the document. As with any form, you can display a PrintPreviewDialog dialog box by calling the Show or ShowDialog methods. The following example demonstrates how to associate a PrintPreviewDialog component with a PrintDocument component and display the PrintPreviewDialog dialog box.

Visual Basic .NET

' Assumes Imports System.Drawing.Printing Dim myDocument As New PrintDocument() Dim myDialog As New PrintPreviewDialog() myDialog.Document = myDocument myDialog.ShowDialog()

Visual C#

// Assumes using System.Drawing.Printing; PrintDocument myDocument = new PrintDocument(); PrintPreviewDialog myDialog = new PrintPreviewDialog(); myDialog.Document = myDocument; myDialog.ShowDialog();

Configuring Printing

The .NET Framework printing interface provides a vast array of configuration options. The PrintDocument.PrinterSettings property contains information about the printers available on a system. The PrintDocument.DefaultPageSettings property contains the page settings that will be used unless configured otherwise in the PrintPage event handler. The properties exposed by these two members are numerous. Fortunately, for the most part they are also self-documenting. Furthermore, when a PrintDocument object is created, the default configuration for the default printer is loaded into the PrinterSettings property, and the default page settings are loaded into the DefaultPageSettings property. Thus, it is possible to create and execute a print job without ever changing the default configuration.

If you want to allow users to set the configuration of their print jobs, Microsoft Visual Studio .NET provides two controls that seamlessly integrate the user interface with the printer configuration: the PrintDialog control and the PageSetupDialog control.

PrintDialog

The PrintDialog dialog box allows users to set the PrinterSettings property of a PrintDocument object at run time. You can add a PrintDialog dialog box to your application by dragging an instance of the PrintDialog control from the Windows Forms tab of the Toolbox to the designer. At run time, you can display the Print Dialog dialog box by calling the ShowDialog method, as follows:

Visual Basic .NET

PrintDialog1.ShowDialog()

Visual C#

PrintDialog1.ShowDialog();

The PrintDialog dialog box must be associated with a PrintDocument object. You can create this association by setting the PrintDialog.Document property to the PrintDocument you want to use.

When displayed, the PrintDialog dialog box binds to the PrinterSettings of the PrintDocument specified by the Document property and provides a graphical interface for user configuration. The PrintDialog dialog box is shown in Figure 8.2. The following example demonstrates how to associate a PrintDialog component with a PrintDocument component and display the PrintDialog dialog box.

Visual Basic .NET

' Assumes Imports System.Drawing.Printing Dim myDocument As New PrintDocument() Dim myDialog As New PrintDialog() myDialog.Document = myDocument myDialog.ShowDialog()

Visual C#

// Assumes using System.Drawing.Printing; PrintDocument myDocument = new PrintDocument(); PrintDialog myDialog = new PrintDialog(); myDialog.Document = myDocument; myDialog.ShowDialog();

figure 8-2 the printdialog dialog box.

Figure 8-2. The PrintDialog dialog box.

PageSetupDialog

The PageSetupDialog dialog box is used in a manner similar to the PrintDialog dialog box. The PageSetupDialog provides a graphical interface that allows the user to configure page settings and printer settings at run time. The user can choose page orientation, paper size, and margins, and configure printer settings as well. The PageSetupDialog dialog box is shown in Figure 8.3. The following example demonstrates how to associate a PageSetupDialog component with a PrintDocument component and display the PageSetupDialog dialog box.

Visual Basic .NET

' Assumes Imports System.Drawing.Printing Dim myDocument As New PrintDocument() Dim myDialog As New PageSetupDialog() myDialog.Document = myDocument myDialog.ShowDialog()

Visual C#

// Assumes using System.Drawing.Printing; PrintDocument myDocument = new PrintDocument(); PageSetupDialog myDialog = new PageSetupDialog(); myDialog.Document = myDocument;

myDialog.ShowDialog();

Like the PrintDialog, the PageSetupDialog exposes a Document property that specifies the PrintDocument to use. Setting the Document property binds the specified PrintDocument to the PageSetupDialog, and any changes made in this dialog box are updated in the PrintDocument.PrinterSettings and DefaultPageSettings properties.

figure 8-3 the pagesetupdialog dialog box.

Figure 8-3. The PageSetupDialog dialog box.

Configuring PageSettings at Run Time

You might want to configure individual pages of a multipage document differently from the rest. For example, you might want to print one page in the landscape format and print the rest of the document in the portrait format. You can change the page settings by using the PrintPageEventArgs.PageSettings property. This property represents the settings for the page being printed. Changes made to this property are used to print the current page, but are not kept for the rest of the print job. The following code example shows how to change a page layout to landscape at run time:

Visual Basic .NET

' This line is excerpted from a PrintPage event handler. The variable ' e represents the PrintPageEventArgs. e.PageSettings.Landscape = True

Visual C#

// This line is excerpted from a PrintPage event handler. The variable // e represents the PrintPageEventArgs. e.PageSettings.Landscape = true;

Lesson Summary

  • A printed document is represented by an instance of the PrintDocument class. It exposes a PrinterSettings property that specifies the settings for the printer and a DefaultPageSettings property that specifies the default page properties.

  • You print a document by calling the PrintDocument.Print method. This method causes the PrintPage event to fire. You provide the logic for rendering your document to the printer in the PrintPage event handler.

  • The PrintPageEventArgs object contains all the information and functionality needed to render output to the printer. Printer output is rendered with the Graphics object that represents the printer, which is provided in the PrintPage EventArgs object.

  • If your document is a multipage document, you must incorporate application logic to handle paging. Set the PrintEventArgs.HasMorePages property to true to fire the PrintPage event again.

  • The PrintPreviewControl control allows you to preview your print documents before printing them. The PrintPreviewDialog dialog box incorporates the most commonly used PrintPreview features into an easy-to-use form.

  • The PrintDialog and the PageSetupDialog dialog boxes allow users to configure printer and page properties at run time. You can also configure individual page properties by changing the PrintPageEventArgs.PageSettings property during printing.



MCAD(s)MCSD Self-Paced Training Kit(c) Developing Windows-Based Applications With Microsoft Visual Basic. Net a[.  .. ]0-316
MCAD(s)MCSD Self-Paced Training Kit(c) Developing Windows-Based Applications With Microsoft Visual Basic. Net a[. .. ]0-316
ISBN: 735619263
EAN: N/A
Year: 2003
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net