When a .NET project requires some kind of custom printed output, the .NET framework provides the PrintDocument and related classes to facilitate the process. Whilst these classes make a very good job of abstracting your code away from printer specifics, writing all the necessary code to render a complicated form can be very time consuming, and the resulting code can be difficult to reuse or adapt to future requirements.
For example, consider the typical TaxForm data entry application below (this is included as a sample application with PrintForm). What is required here is a printout that matches the on-screen display as closely as possible, but anyone who has developed such an application will tell you how long the process of developing the necessary graphics code takes.
Our PrintForm technology arose from the questions 'Why can't we just print the Form?' and '.NET knows how to render it onto the screen, so surely it can render it to the printer as well?'
Well, as usual with these things, 'Just printing the Form' turned out to be a little more complex.
The simplest way of printing a Form is to use the underlying Windows API take a bitmap (BitBlt) 'snapshot' of the window. This is unsatisfactory for many reasons, however - the resulting image doesn't scale well to the higher resolutions of most modern printers, resulting in a 'blocky' printout, it doesn't cope with scrollable Forms and you have no control over what is displayed at print time - you literally get a bitmapped image of the Form as you see it on screen at the screen resolution.
By contrast, PrintForm renders each control individually, using the graphics calls the control uses to render itself onto the screen. This means that printouts are resolution independent, and the entire contents of a scrollable region can be rendered, whether or not the controls are in view. It also allows us to selectively omit some controls from the printout - for example you may not want the OK and Cancel buttons to appear on the printout. By the same mechanism we can specify an alternative background color for individual controls at print time, so a Form which is gray at runtime can be printed out with a more appropriate white background etc.
The results of this approach can be seen below. Printing was added to the TaxForm application by simply adding a PrintForm component to the Form, and setting the PrintForm.BodyContainer property to point at the entire Form. This makes PrintForm render the entire contents of the Form into the MarginBounds area of the printed page:
(Note: in this example there are several Forms in the application, each of which has been rendered on a separate page).
As you can see, designing the printed output is as simple as designing a Windows Form.
PrintForm is derived from the .NET framework PrintDocument class. This means you can use it in any place where you might use a PrintDocument component.
For example, if you were implementing custom printing in your application without the use of PrintForm you would add a PrintDocument and a PrintPreviewDialog component to your Form, and set the PrintPreviewDialog.Document property to the PrintDocument. You would then handle the PrintDocument.PrintPage event and do all your graphics calls there to layout the page. (See the Microsoft documentation on this at https://samples.gotdotnet.com/quickstart/winforms/doc/WinFormsPrinting.aspx).
Custom printing with PrintForm is a very similar process - you add PrintForm and PrintPreviewDialog components to your Form, and set the PrintPreviewDialog.Document property to the PrintForm. Then, instead of writing the PrintPage code yourself, you set PrintForm's BodyContainer property to whichever control you want to print on the page and PrintForm handles all the drawing.
In addition to the BodyContainer, PrintForm also has HeaderContainer and FooterContainer properties. The controls referenced by these two properties are rendered in the positions shown below. The bottom of the HeaderContainer control is aligned with the top of the Margin rectangle, and the top of the FooterContainer control is aligned with the bottom.
PrintForm provides a number of properties to control how the output is rendered, including scaling, centering, visibility and background color. When the outermost container control (e.g. Form) has a non-client border area this can optionally be printed as well.
* The CenterStyle options result in the following placement of the output:
It may not always be appropriate to use PrintForm as a PrintDocument, for example:
For these reasons PrintForm provides a utility method PrintControl. Using this you can render any control into a given rectangle at a given scale. Using this you can:
A number of samples are provided with PrintForm which illustrate each of these procedures.
The life cycle of printing using a PrintDocument class is explained in detail in the .NET documentation, but briefly when Print is called on any PrintDocument or PrintDocument derived class, the sequence is:
OnBeginPrint (base raises BeginPrint event) is called at start of print job.
For each page:
OnQueryPageSettings (base raises QueryPageSettings event) is called.
OnPrintPage (base raises PrintPage event) is called, looping continues while HasMorePages is set True.
OnEndPrint (base raises QueryPageSettings event) is called.
Print job ends.
So if we have many Forms in an application and each one has a PrintDocument (or a PrintForm) how do we make them all part of the same print job? For this PrintForm provides the PrintChainManager class and the IChainedDocument interface.
PrintChainManager is itself derived from PrintDocument and will daisy chain together a sequence of objects which implement the IChainedDocument interface into a single print job. The TaxForm sample at the start of this document demonstrates this approach, allowing an application consisting of a number of separate Forms to be presented as an integrated application with the ability to print the sequence of Forms as a single document.
This short overview has covered the how and why of PrintForm. If you'd like to give it a try you can download a free trial copy from https://www.winformreports.co.uk
This article © 2019 TMG Development Ltd. All Rights Reserved.