In a recent one of my regular articles for MSDN Germany, I came up with a PrintForm replacement (remember Visual Basic .NET, or rather Windows Forms, does not offer this method and it was very, very limited in Visual Basic anyway - barely usable, to be honest).
Although it's not a big deal after all, I've polished that code up a bit to include an option to either print only the client area of a form (as VB's PrintForm does) or the entire form (including its title bar and its borders). The latter works nicely only for regularly shaped forms - anyway, I thought I'd share it with you.
I tried to keep this one nice and easy. If you'd like to improve it a bit, you might want to add the PrintDocument object via code instead of adding it as a control. And of course, you could make it more general by passing the form as a parameter instead of needing to put that code into the form module itself.
As a sidenote, I reserve the right to update any code in my blog at any time and of course, usage is at your only risk.
' I used http://www.vbcity.com/encoder/default.asp?lang=vb to colorize this code.
' Feel free to use any published results of my work in your applications.
' Refrain from stealing my work by republishing its results without my consent.
Imports System.Drawing
' ...
Private Const SRCCOPY As Integer = &HCC0020
Private Declare Function BitBlt _
Lib "gdi32.dll" ( _
ByVal hdcDest As IntPtr, _
ByVal x As Int32, _
ByVal y As Int32, _
ByVal Width As Int32, _
ByVal Height As Int32, _
ByVal hdcSrc As IntPtr, _
ByVal xSrc As Int32, _
ByVal ySrc As Int32, _
ByVal dwRop As Int32 _
) As Boolean
Private formImage As Bitmap
Public Sub PrintForm(Optional ByVal fullWindow As Boolean = False)
' Copyright © 2004 by Mathias Schiffer. Leave this notice in place.
' Copies a screenshot of the form this code is being run in
' to the active printer. Place this code in a form module.
' Set fullWindow to True for including borders and titlebar.
' Remember to use an Imports reference to System.Drawing.
' Also, add a PrintDocument1 control to the form for printing.
' The disadvantage of this code is that it does only capture
' those parts of the form that are actually visible (screenshot),
' i.e. it must not be hidden and may not even be obscured.
' VB's PrintForm method does not require that, so this is not a
' perfect replacement. Keep that in mind.
With Me ' This can easily be replaced with a Form parameter
' Create a Graphics object for the form
Dim formGraphics As Graphics = .CreateGraphics
' Create a compatible bitmap and get its Graphics object
If fullWindow Then
formImage = New Bitmap(.Width, .Height, formGraphics)
Else
formImage = New Bitmap(.ClientRectangle.Width, _
.ClientRectangle.Height, _
formGraphics)
End If
Dim memGraphics As Graphics = Graphics.FromImage(formImage)
' Get the target and source device context handles (hDC)
Dim sourceDC As IntPtr = formGraphics.GetHdc
Dim targetDC As IntPtr = memGraphics.GetHdc
' Do the screenshot part of the job
If fullWindow Then
' Consider the border width and the titlebar height
Dim widthDelta As Integer = (.Width - _
.ClientRectangle.Width)
Dim heightDelta As Integer = (.Height - _
.ClientRectangle.Height)
' Copy the form including its titlebar and borders
BitBlt(targetDC, _
0, 0, _
.ClientRectangle.Width + widthDelta, _
.ClientRectangle.Height + heightDelta, _
sourceDC, _
0 - widthDelta \ 2, 0 - (heightDelta - widthDelta \ 2), _
SRCCOPY)
Else
' Copy the form's client area
BitBlt(targetDC, _
0, 0, .ClientRectangle.Width, .ClientRectangle.Height, _
sourceDC, _
.ClientRectangle.X, .ClientRectangle.Y, _
SRCCOPY)
End If
' Release DCs and dispose objects
formGraphics.ReleaseHdc(sourceDC)
formGraphics.Dispose()
memGraphics.ReleaseHdc(targetDC)
memGraphics.Dispose()
' formImage now has the form's image. Print it before disposing it.
PrintDocument1.Print() ' Invokes PrintDocument1_PrintPage (below)
' Finally dispose the image
formGraphics.Dispose()
End With
End Sub
Private Sub PrintDocument1_PrintPage( _
ByVal sender As System.Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs _
) Handles PrintDocument1.PrintPage
' Print the screen shot in formImage. Use DrawImage's
' parameters to control the position of the printer output.
e.Graphics.DrawImage(formImage, 100, 200) ' printing position x=100, y=200
End Sub