One of the most common questions is "how can I print / print preview my windows form"? This is quite easily done by getting the form to "draw itself" on the printed page or using the VB Power Packs to do likewise, but this is often unsatisfactory because:
- The location of components on the form may not be where you want them on the printed page
- Text is drawn at screen resolution
- Every control is drawn (e.g., buttons, the form border etc.)
The attached component addresses the problem in a different manner.... What you do is drop a
FormPrintHelperComponent component onto your form and it extends each control on that form with a set of new properties (look in the Properties window for each control in the section named "MCL Form Print Helper").
You then set these to indicate:
- Whether or not the control should be printed
- Whether to print it as Text, Image, or Owner Drawn
- The boundary rectangle to print it in
- The vertical / horizontal alignment within that area
- Font and background/foreground colour to use etc.
The component then allows you to preview the printed page at design time, and to preview or print it at run time.
How it works
The component implements
System.ComponentModel.IExtenderProvider which means it provides properties to the other controls on the form - in the same way as the built-in ToolTip and F1 Help provider components do.
The class is decorated with
ProvideProperty attributes which tells the IDE which properties the control provides to extend the properties of the controls on the form. Underlying each of these "properties" are a matched pair of a function and sub routine to get/set the property for the control passed in, which are called if an extended property is changed in the target control's property window.
When the component is invoked to print or print preview, it iterates through all the controls on the form that have the extended property
Print set to
true. It then prints the control according to the other extended properties provided for that control such as boundary rectangle, font, foreground and background colour etc.
PrintMode extended property affects how the control is printed. There are three options:-
PrintAsText - Prints the "
Text" property of the control
PrintAsImage - Prints the "
Image" property of the control if it has one; otherwise, prints the control as a bitmap exactly as it appears on screen
PrintAsOwnerDrawn - Passes the control to the
OwnerDrawnControlprint event so the application can decide how to print the control
"Print as image" printing functionality
If the control doesn't have an
Image attribute, the control is drawn onto a bitmap, which is then printed on the form by using the control class'
Private Function GetControlImage(ByVal ctlIn As Control) As Image
Dim Imageproperty As System.Reflection.PropertyInfo
Imageproperty = ctlIn.GetType.GetProperty("Image", GetType(Image))
If Imageproperty Is Nothing Then
Dim imgNew As New Bitmap(ctlIn.Width, ctlIn.Height)
Return CType(Imageproperty.GetValue(ctlIn, Nothing), Image)
"Owner drawn" printing functionality
If you set the extended property
PrintAsOwnerDrawn, then at run time, when the print or print preview logic is invoked, an
OwnerDrawnControlPrint event will be raised to allow you to programmatically draw the control onto the page canvas.
Private Sub FormPrintHelperComponent1_OwnerDrawnControlPrint(ByVal sender As Object, _
ByVal e As MCL_Form_Print_Control.OwnerPrintControlEventArgs) _
If .ControlToPrint.Name = "DateTimePicker1" Then
e.Canvas.DrawString(">> " & .ControlToPrint.Text & _
"<<", .ControlToPrint.Font, _
First compile the attached source code and then add a reference to the control's DLL to your application, and (optionally) add it to the toolbox.
The next step is to layout your Windows form in Design mode with all the controls that you want on it. (You can add controls at a later date, and the extender will pick them up, so don't worry about having the full design in place to start with). You then drag an instance of the component from the tool bar on to your form.
Then, select the control(s) you want to print - e.g., on the form in the demo project in the source code above, the controls
CheckedListBox_Databases etc. are to be printed, but the user does not want to print the buttons
On the control properties pane for the controls to be printed, navigate down to the section "MCL Form Print Utility" and set the extended property named "Print on FormPrintHelperComponent1" to
Setting the rich text box mode to
PrintAsRichText means the content of a rich text box is printed in what-you-see-is-what-you-get mode.
Selecting where to print the component on the page
By default, the property "BoundingRectangle on FormPrinthelperComponent1" is set to the same rectangle as the control occupies on the form. You can alter this (to make the layout more suited to the size and orientation of the printed page) by altering the values in this property. To see how this change looks, you can preview the form print layout by selecting the
FormPrintHelperComponent instance, and from its smart tag menu, select the option "Preview Document".
Other extender provided properties
The component provides the following extended properties to the form on which it is sited:
DocumentName - The name of the document as it will appear in the print queue when printed. This defaults to the name of the form if not set.
PaperKind - The paper size to use to print the document (A4, A5, letter etc.).
The component provides the following extended properties to all the controls on the form on which the component is sited:
BackColour - The colour to fill the bounding rectangle of the control before printing it. If this is transparent, then the bounding rectangle will not obscure items printed before it.
BoundingRectangle - Where on the page to print the component.
ForeColour - The foreground colour to use to print the control (this has no effect if the print mode is not
VerticalAlignment - How to align the control's text relative to its bounding rectangle for printing.
Print - True if it should be printed on the page, false if not.
PrintFont - The font to use to print the control's text if the print method is
PrintMethod - How to print the control (see explanation above).
RightBorder - Pens to use to draw a border around the bounding rectangle on the printed document.
Of course, there are many cases where a single form needs to be printed over multiple logical pages - for example, if a form has many tabs on it, you might find it sensible to print one logical page per tab.
The component implements this functionality by having a property
LogicalPages which is a positive number 1 or greater that is the number of logical pages that this form should be printed over. Then, for each control, two additional extended properties are added that control which pages that control is to be printed on:
MultiPageprintMethod which is an enumerated type:
PrintOnEveryPage - Print the control on every logical page
PrintOnOddPages - Print the control on odd numbered logical pages
PrintOnEvenPages - Print the control on even numbered logical pages
PrintOnlyOnSpecifiedLogicalPages - Print the control only on the specified pages
MultiPageprintMethod is set to
PrintOnlyOnSpecifiedLogicalPages, then a second extended property,
PrintOnPages (which is a list of boolean values, one for each logical page) is used to set the page(s) to print it on.
When the data in a control (such as a multi-line textbox, a rich textbox, or a grid) is too large for the area allocated to print it on the document, you can optionally set it to flow over to a new page until it reaches the end of the data by setting the extended property
However, the new page will be the same logical page as the current one (with all the same controls on it), but will be a different physical page. The use of logical pages at the design stage allows a multi part document to be created that does not need to change at run time to accommodate extra data.
- Added a
UITypeEditor to allow you to set the colour and line width of all the border lines.
- Added an extended property
Trimming which controls how words wrap within their bounding rectangle.
- Added an extended property
PropertyToPrint to allow you to specify which property of the control you want to print.
- Added a
PrinterSettings method that invokes the printer setup dialog box to allow the settings to be changed at run time.
- Added a
PageSetup method that invokes a page setup dialog box to allow the user to change the page layout at run time.
- Added multi-page functionality.
- Added code to print a rich text box as rich text (what-you-see-is-what-you-get) by setting
- Added C# version of the component.