Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile

All about PrintForm component 1.0

3.92/5 (10 votes)
30 Jun 20078 min read 1   1  
How to print a Form in VB.NET using the Printform Component. Describes the various ways with examples on how to customize the printed output according to your need.

Introduction

"The PrintForm Component is designed to bring back the ability to easily print a Windows Form."

This article begins with the basic steps to use the PrintForm component and simple Form printing, describes various options for customised printing with code examples where necessary, and addresses some problems faced with the usage.

Background

Sometime back, I was working on a project in VB.NET, which required printing reports. It was a very lengthy job as back then, no such component was available. This was a big drawback with working in VB.NET as compared to VB. But now, the release of the PrintForm component has proven a boon for both, VB.NET developers and those who are trying to upgrade their projects from VB to VB.NET, as you now no longer need to generate long sequences of GDI calls. You can simply print your Form, as desired, with minimal code. However, despite the ease and simplicity of the usage of the PrintForm component, problems and doubts about this have been posted on forums of almost all developer sites and hardly any examples given. This is what made me decide to write about this component.

How to start

First things first. You need to download and install the PrintForm component if you have not already done that. Here is a link to the download http://msdn2.microsoft.com/en-us/vbasic/aa701261.aspx
Installation is very simple, generally no problems occur during that. After installation, you will need to add it to your toolbox so that you can then drop it onto your Form:

  1. In the Visual Studio .NET editor, right click on the 'General' tab of the Toolbox, and select 'Customize Toolbox...'
    or add it to the Windows Forms tab
    or create a new tab.
  2. Select the .NET Framework Components tab of the Customize Toolbox Dialog and scroll down until you find 'PrintForm'.
  3. Check it and click OK.

    Now you can drag a PrintForm component from the General Tab of the Toolbox onto the Form's Component tray. PrintForm extends each control on your Form, and the Form itself, with new properties, which can be set according to requirements.

Printing the Form

To print the entire form, 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()

Print Previewing the Form

Often you need to print preview the form before actual printing, especially during testing, so that you can adjust the properties accordingly, and of course not to forget, to save paper (and hence trees)
It can be done as follows:

  1. Drag a PrintForm component onto the 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()
    VB.NET
    Private Sub Button1_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles Button1.Click
            ' If you don't want the print button to print the print button
            Button1.Visible = False
            ' Set the PrintAction to display a Print Preview dialog
            PrintForm1.PrintAction = Printing.PrintAction.PrintToPreview
            ' This prints a copy of the form as it appears in the PrintPreview
            PrintForm1.Print()
            ' Display the print button again on the form
            Button1.Visible = True
        End Sub 

Customizing the Form Printout

In order to change the Background color of the Form on the printout, you can set BackColorWhilePrinting of the Form. The background color of all the controls on the form will get changed. However, if you want to specify different colors for different forms, you can set this property for the individual controls.

If you don't want specific controls on the Form to get printed(for instance, command buttons), you can set VisibleWhitePrinting property for those controls on the Form.

For centering the printed form on the page, in the horizontal or vertical dimension, or both, you can use the PrintForm.CenterStyle property.

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.

To zoom the form to fill the printed page, setting the AutoFit property to one of these values controls this behavior: PageElement.None, PageElement.Body, PageElement.All.

To add headers and footers to the printout, there are 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 beneath the Margin rectangle respectively.

So, you will have to add two extra Panels to the Form inside which, you will add the controls that are to appear as header and footer. Then, set HeaderContainer to the header panel, BodyContainer to the Form and FooterContainer to the footer panel, making sure that they are not visible on the surface of the Form by setting their Location appropriately (eg. to (-1000, -1000)) or making them visible only while printing.

Margin widths are controlled by the Margins property of the PageSettings object. To set margin widths:

  1. Set the PrintDocument.DefaultPageSettings.Margins property to control the default margin size of all pages printed by the PrintDocument
    VB.NET
    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  
  2. or set e.PageSettings.Margins in the PrintDocument.QueryPageSettings event to set each printed page's Margin size individually:
    VB.NET
    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 

The borders of the outermost control you are rendering can be turned on or off using the PrintForm.PrintBorders property.

You may have to print different controls from a single Form on each page of the printout. You can do this by changing the BodyContainer property of PrintForm for each page.

You can also print different Forms on each page of the printout, by adding a PrintForm to each form, with its BodyContainer set to the entire Form. Add a main Form to the project, containing a PrintChainManager component and add a reference to each of the PrintForm controls to the PrintChainManager.Documents collection.

You can print more than one Form or container control on the same page by using the PrintForm.PrintControl() method which allows you to render any control you like at any position on the page.

To print a Form which is larger than the paper size over multiple pages, 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 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.

To print a control inside a UserControl with a different BackColor, set UseLegacyPrinting, BackColorWhilePrinting, VisibleWhilePrinting settings on controls that are inside a UserControl.

It is very often required to print a Form or control scaled to custom size.It can be done as follows:

  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()
    Or use the PrintForm.PrintControl() method and set the scale of the output in the 4th parameter.

You may, at times, want to print a hidden Form / control, for example, where the layout of the printed form is required to be different to the user interface. For this, you can simply call PrintForm.Print() without displaying the Form, once you have setup the required PrintForm properties. Basically, the form is visible, but just out of view.

Printing to a file

To print the Page image to a file, use a specialization of the .NET class PrintController, called FilePrintController. FilePrintController supplies a Graphics object obtained from a Bitmap to the standard printing mechanism. This class can be used to print to any of the file formats .NET supports even if you were not using PrintForm to render your printed output.

You could use the following code to achieve this:

VB.NET
' 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() 

Similarly, you can print multiple Page images to a TIFF file, using the above class.

To print without showing the 'Printing Page' dialog, use StandardPrintController. Set the PrintController property of PrintForm as follows, before calling Print, or doing a PrintPreview:

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

Some Problems

You may find that some of the controls on the Form aren't displayed at print. This is because some controls in .NET and some third party controls are not fully managed or are not written according to the .NET control guidelines. So, they are marked as 'Legacy' controls. Select the control and set it's UseLegacyPrinting property to true. This should solve the problem. A very few legacy controls may not respond to the methods that PrintForm uses to get them to render themselves into the printout.

VB.NET
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 clipboard
    vFile = ""
    NChart1.ImportExport.SaveBitmapImage(vFile, bUseWindowDim, nWidth,
                        nHeight, nBitsPerPixel)

    ' this is generic code for getting a bitmap from 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 

The control may offer some other mechanism for obtaining an image of it's contents. If this is the case PrintForm provides an event, the PreDraw event, that you can handle to take charge of rendering the control yourself. This has been shown in the above code snippet.

You may also need to distribute the PrintForm and printchaining assemblies with your application. There are several ways to locate the correct assemblies:

  • Build an installer project for your application and it will automatically pull in the correct versions.
  • Or set copy local to true for the printform and printchaining references in your project, this will cause VS.NET to copy them through to your bin directory and you can pick them up from there with your EXE and copy them to the same location as your EXE on the target machine.
  • Or copy them manually from their installed locations

CONCLUSION

Printing Windows forms in VB.NET using the PrintForm Component is a very simple and an effective way of implementing VB-type single-line printform() method in VB.NET. I hope my attempt proves useful to people working in this direction. I shall try to update the article with more examples and samples.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here