PrintForm .NET Frequently Asked Questions

 Basic Questions. How do I ... ?

  1. Add PrintForm to the Visual Studio Toolbox?
  2. Print a Form with one line of code?
  3. PrintPreview a Form with one line of code?
  4. Change the Background color of the Form on the printout?
  5. Prevent Form controls from showing up on the printout?
  6. Center the printed Form in the page?
  7. Zoom the Form to fill the printed page?
  8. Add headers and footers to my printout?
  9. Set margin sizes on my printout?

 Advanced Questions. How do I ... ?

  1. Turn printing of the borders of my Form / control on or off?
  2. Print different controls from a single Form (e.g. Tab pages) on each page of the printout?
  3. Print different Forms on each page of the printout?
  4. Print a Form which is larger than the paper size over multiple pages?
  5. Print a control inside a UserControl with a different BackColor?
  6. Set UseLegacyPrinting, BackColorWhilePrinting, VisibleWhilePrinting settings on controls that are inside a UserControl?
  7. Print more than one Form / container control (tab, panel etc) on the same page?
  8. Print the Page image to a file?
  9. Print multiple Page images to a TIFF file?
  10. Print a Form or control scaled to custom size?
  11. Print without showing the 'Printing Page n' dialog?
  12. Print a hidden Form / control?
  13. Handle rendering of a legacy control myself?
 
Top of PageBasic Questions. How do I ... ?

 

Q: Add PrintForm to the Visual Studio Toolbox?                                                                                

A: After you have installed the PrintForm component you will need to add it to your toolbox so that you can then drop it onto your Form. The following procedure describes how to do this:

  1. Open the Visual Studio .NET editor.
  2. Right click on the 'General' tab of the Toolbox, and select 'Customize Toolbox...' ('Add/Remove Items...' in Visual Studio 2019). You may alternatively add it to the Windows Forms tab, or create a new tab.
  3. Select the .NET Framework Components tab of the Customize Toolbox Dialog and scroll down until you find 'PrintForm'; check this and click OK.

You should now be able to drag a PrintForm component from the General Tab of the Toolbox onto your Form's Component tray.

 

Q: Print a Form with one line of code?                                                                              

A: Perform the following steps:

  1. Drag a PrintForm component onto your Form from the Visual Studio Toolbox
  2. Set the PrintForm.BodyContainer property to reference your Form
  3. Add a button and button click handler. In the handler call PrintForm.Print()
 

Q: PrintPreview a Form with one line of code?                                                                              

A: Perform the following steps:

  1. Drag a PrintForm component onto your Form from the Visual Studio Toolbox
  2. Set the PrintForm.BodyContainer property to reference your Form
  3. Drag a PrintPreviewDialog component onto your Form from the Visual Studio Toolbox
  4. Set the PrintPreviewDialog.Document property to reference the PrintForm component
  5. Add a button and button click handler. In the handler call PrintPreviewDialog.ShowDialog()
 

Q: Change the Background color of the Form on the printout?                                                                              

A: PrintForm extends each control on your Form, and the Form itself, with a new property: BackColorWhilePrinting. You can set this for each control on the Form, but since as a general rule child controls inherit their parent's BackColor it is usually enough to set the Form's BackColorWhilePrinting property (e.g. to White) and all the child controls on the Form will pick this up automatically.

 

Q: Prevent Form controls from showing up on the printout?                                                                              

A: PrintForm extends each control on your Form with a new property: VisibleWhilePrinting. You can set this for each control on the Form to prevent it from being rendered in the printout, for example you may not want the OK and Cancel buttons to appear on the printout.

 

Q: Center the printed Form in the page?                                                                              

A: The PrintForm.CenterStyle property allows you to center the printed output in the horizontal or vertical dimension, or both. When the Form or control you are printing is smaller than the Margins of the printed page, PrintForm uses the CentreStyle setting to center the output, alternatively to print the output at the top left of the Margin rectangle set CenterStyle = CenterStyle.None.

The following diagrams illustrate the effects of different CenterStyle options:



 

Q: Zoom the Form to fill the printed page?                                                                              

A: PrintForm can automatically scale the printed output it produces to allow a large Form to fit onto a single printed page. Setting the AutoFit property to one of the following values controls this behavior:

PageElement.None: When AutoFit is set to PageElement.None the output is scaled according to the setting of the PrintForm.ManualZoom
PageElement.Body: Zooming is applied to the BodyContainer page element only. HeaderContainer and FooterContainer contents will remain at the default scale factor of 1.0
PageElement.All: Zooming is applied to the BodyContainer, HeaderContainer and FooterContainer page elements equally, based on the scaling necessary to fit the BodyContainer contents into the MarginBounds rectangle.

 

Q: Add headers and footers to my printout?                                                                              

A: PrintForm has three properties that can be set to point at individual controls: HeaderContainer, BodyContainer and FooterContainer. The contents of the control referenced in the BodyContainer property are rendered inside the Margin rectangle on the page, the HeaderContainer and FooterContainer (if specified) are rendered directly above and directly beneath the Margin rectangle respectively.

So to produce a printout of your Form with headers and footers present, add two extra Panels to the Form. Inside these add the controls you wish to appear as your header and footer. Set HeaderContainer to the header panel, BodyContainer to the Form and FooterContainer to the footer panel. Finally, make sure they are not visible on the surface of the Form by setting their Location to (-1000, -1000).

 

Q: Set margin sizes on my printout?                                                                              

A: Margin widths are controlled by the Margins property of the PageSettings object.

There are two ways to set this: 1) set the PrintDocument.DefaultPageSettings.Margins property to control the default margin size of all pages printed by the PrintDocument, or 2) set e.PageSettings.Margins in the PrintDocument.QueryPageSettings event to set each printed page's Margin size individually:

1) Setting the default size for all pages in the form Load event via the DefaultPageSettings property:

Private Sub frmSimpleForm_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
  Dim newMargins As System.Drawing.Printing.Margins
  newMargins = New System.Drawing.Printing.Margins(50, 50, 50, 50)
  Me.PrintForm1.DefaultPageSettings.Margins = newMargins
End Sub

2) Setting each page's Margin size individually via the QueryPageSettingsEventArgs.PageSettings property in the QueryPageSettings event:

Private Sub PrintForm1_QueryPageSettings(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles PrintForm1.QueryPageSettings
  Dim newMargins As System.Drawing.Printing.Margins
  newMargins = New System.Drawing.Printing.Margins(50, 50, 50, 50)
  e.PageSettings.Margins = newMargins
End Sub
 

Top of PageAdvanced Questions. How do I ... ?

Q: Turn printing of the borders of my Form / control on or off?                                                                              

A: The borders, or non-client area, of the outermost control you are rendering can be turned on or off using the PrintForm.PrintBorders property.

For example if you are printing a Form in a report style document you may not want the Form title bar and border to be printed, in this case you would set PrintBorders = None. Alternatively you may be printing a 'screen shot' style representation of a Form where you want the title bar and border to be shown, but you don't want the borders on your header and footer controls to print - in which case you would set PrintBorders = Body. If you want borders on header, body and footer set PrintBorders = All.

 

Q: Print different controls from a single Form (e.g. Tab pages) on each page of the printout?                                      

A: This process is illustrated in the MultiPage sample. (See the associated readme file).

In summary, the following occurs in this sample:

The PrintForm QueryPageSettings event is handled, and is used to change the BodyContainer property of PrintForm for each successive page. In the PrintForm.PrintPage event handler the process is terminated when we have printed all the controls we need to print (in this case tab pages of a tab control).

 

Q: Print different Forms on each page of the printout?                                                                              

A: This process is illustrated in the TaxForm sample. (See the associated readme file).

In summary, the following occurs in this sample:

A different Form is added to the project for each page of the printout. Each form has a PrintForm added, with its BodyContainer set to the entire Form. A main Form is added to the project, containing a PrintChainManager component. A reference to each of the PrintForm controls is added to the PrintChainManager.Documents collection. When PrintChainManager prints, it chains the sequence of pages printed by each of the PrintForm controls into a single document.

Note: any object that implements the IChainedDocument interface can participate in the print job managed by the PrintChainManager. See the IChainedDocument documentation for details of how to implement this interface on your own classes. Products from TMG Development Ltd that support this interface include PrintForm and the PrintAdapters suite (PrintListView, PrintTreeView, PrintDataTable, PrintRichTextBox).

 

Q: Print a Form which is larger than the paper size over multiple pages?                                                                              

A: This process is illustrated in the PrintLargeControl sample. (See the associated readme file).

In summary, the following occurs in this sample:

The PrintForm.PrintControl method is used to render a portion of the Form into the MarginBounds rectangle on each successive page. The Form is divided into a number of 'Tiles' each with an offset from the origin (top left) of the control. To print each Tile we repeatedly print the Form, negatively offset by the specified amount, while the Graphics.Clip region is set to the page MarginBounds rectangle to exclude any portion of the Control not in the current Tile.

 

Q: Print a control inside a UserControl with a different BackColor?                                                                              

A: See the following item.

 

Q: Set UseLegacyPrinting, BackColorWhilePrinting, VisibleWhilePrinting settings on controls that are inside a UserControl?

A: The problem with controls contained within a UserControl is that the Visual Studio designer doesn't see them, and consequently you can't set any of the PrintForm extender properties for them whilst in the designer. The solution is to set them at runtime via the appropriate Set<extender-property-name> function.

This process is illustrated in the UserControlWithLegacy sample. (See the associated readme file).

 

Q: Print more than one Form / container control (tab, panel etc) on the same page?                                                                              

A: The default behavior of PrintForm is to print a single nominated control (referenced by the BodyContainer property) into the MarginBounds rectangle of the page. This architecture is designed for simplicity (see Print a Form with One Line Of Code), but in more complex scenarios you may have a tab control on a Form where you want to print all the tabs on one page. In this situation you would use the PrintForm.PrintControl() method which allows you to render any control you like at any position on the page.

This process is illustrated in the PrintMultipleHiddenForm sample. (See the associated readme file).

 

Q: Print the Page image to a file?                                                                              

A: The PrintToFile sample (See the associated readme file) shows how to print a representation of the printed page (headers and footers included) to a file. It uses a specialization of the .NET class PrintController, called FilePrintController, which is included in this project (.NET provides a StandardPrintController, PrintControllerWithStatusDialog and PreviewPrintController). FilePrintController supplies a Graphics object obtained from a Bitmap to the standard printing mechanism. You could use this class to print to any of the file formats .NET supports even if you were not using PrintForm to render your printed output.

If you just want to save an image of a given control or Form to a file you can use code similar to the following:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                                                                Handles Button1.Click
	' Save an image of the Form
	Dim target As Control = Me
	Dim r As Rectangle = New Rectangle(New Point(0, 0), target.Size)
	Dim img As New Bitmap(r.Width, r.Height)
	Dim g As Graphics = Graphics.FromImage(img)
	Me.PrintForm1.PrintControl(g, r, target, 1.0)
	g.Dispose()
	img.Save("c:\image.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
	img.Dispose()
End Sub

See the PrintToBitmap sample for further details (See the associated readme file).

 

Q: Print multiple Page images to a TIFF file?                                                                              

A: The PrintToMultiPageTiffFile sample (See the associated readme file) shows how to print multiple pages into a single multi-page .tif (TIFF) file. It uses a specialization of the .NET class PrintController, called FilePrintController, which is included in this project. FilePrintController supplies a Graphics object obtained from a Bitmap to the standard printing mechanism and appends each Bitmap to a single TIFF image.

 

Q: Print a Form or control scaled to custom size?                                                                              

A: Perform the following steps:

  1. Drag a PrintForm component onto your Form
  2. Set the PrintForm.BodyContainer property to reference your Form
  3. Set PrintForm.AutoFit = None, to prevent PrintForm from automatically scaling up the Form to fit the page.
  4. Set PrintForm.ManualZoom to the scale you want, say 0.5
  5. Set PrintForm.CenterStyle to control how the image is centered on the page.
  6. Add a button and button click handler. In the handler call PrintForm.Print()

Alternatively if you are using the PrintForm.PrintControl() method in a custom printing scenario you can set the scale of the output in the 4th parameter.

 

Q: Print without showing the 'Printing Page n' dialog?                                                                              

A: The solution here is to change the PrintController that the .NET printing mechanism uses. By default it uses a PrintControllerWithStatusDialog object, but there is also one in the .NET framework which doesn't display the status dialog, called StandardPrintController.

Set the PrintController property of PrintForm as follows, before calling Print, or doing a PrintPreview:

Me.PrintForm1.PrintController = New System.Drawing.Printing.StandardPrintController()
 

Q: Print a hidden Form / control?                                                                              

A: You will not always want to show the form you are about to print to the user, for example in a batch printing application, or where the layout of the printed form is required to be different to the user interface. In this situation you might expect to be able to simply call PrintForm.Print() without displaying the Form, once you had setup the required PrintForm properties. In fact some controls (TextBox, ListBox, Combo etc) will not appear on the printed output if you do this because they rely on Win32 controls internally which are detecting that they are not visible and are optimizing the repainting of the form by not displaying themselves.

The solution to this legacy control problem is to make sure that the form is visible, but just out of view. To this end the technique we use in this sample is to re-parent the form we wish to print to our main application's form, move it out of view and then print it.

This process is illustrated in the PrintHiddenForm sample. (See the associated readme file).

 

Q: Handle rendering of a legacy control myself?                                                                              

A: A very few legacy controls may not respond to the methods that PrintForm uses to get them to render themselves into the printout. In this situation it may be that the control offers some other mechanism for obtaining an image of it's contents (Save to file, copy to clipboard etc). If this is the case PrintForm provides an event, the PreDraw event, that you can handle to take charge of rendering the control yourself.

Here is some sample code that shows how to use a legacy control's SaveBitmapImage function to copy an image of its client area onto the clipboard, and then render that image into the printout. In this case the legacy control is a Nevron 3D Chart ActiveX control:

Private Sub PrintForm1_PreDraw(ByVal e As TMGDevelopment.PrintForm.PreDrawEventArgs) _
                                                               Handles PrintForm1.PreDraw
  ' look for the control we're interested in
  If e.Control Is Me.NChart1 Then
    ' this code is from the following Nevron sample and is specific to the Nevron ActiveX control:
    ' Nevron\3DChart\Example Files\Examples\3DChart\Visual Basic 6\ImportExport\Clipboard
    Dim vFile As Object
    Dim bUseWindowDim, bOK As Boolean
    Dim nHeight, nWidth, nBitsPerPixel As Integer
    bUseWindowDim = True
    nBitsPerPixel = 24
    nHeight = e.Bounds.Height
    nWidth = e.Bounds.Width
    ' a variant with an empty string indicates that we want to use the clipboard
    vFile = ""
    NChart1.ImportExport.SaveBitmapImage(vFile, bUseWindowDim, nWidth, nHeight, nBitsPerPixel) 

    ' this is generic code for getting a bitmap from the clipboard and drawing it:
    Dim iData As IDataObject = Clipboard.GetDataObject()
    Dim img As System.Drawing.Bitmap = iData.GetData(DataFormats.Bitmap, True)
    e.Graphics.DrawImage(img, e.Bounds)
    e.OwnerDrawn = True ' tell PrintForm we've drawn this control
  End If
End Sub