Microsoft KB Archive/890894

= How to print the active Windows form in Visual Basic .NET =

Article ID: 890894

Article Last Modified on 5/31/2007

-

APPLIES TO


 * Microsoft Visual Studio .NET 2003 Professional Edition
 * Microsoft Visual Studio .NET 2003 Enterprise Architect
 * Microsoft Visual Studio .NET 2003 Enterprise Developer
 * Microsoft Visual Studio .NET 2003 Academic Edition

-





INTRODUCTION
This article describes how to print the active Windows form in Microsoft Visual Basic .NET by using Windows Graphics Device Interface (GDI) functions.



MORE INFORMATION
To print the active Windows form in Visual Basic .NET, you must do the following:
 * 1) Create a PrintDocument object to send output to the printer.
 * 2) Create a class that contains the Windows GDI structures and the DllImport statements that are required to call the Windows GDI functions.
 * 3) Associate the PrintDocument.PrintPage event with an event handler that is named OnPrintPage. To do this, use the AddHandler statement.
 * 4) In the OnPrintPage event handler, print the current Windows device context as a graphics image to the PrintDocument object when the PrintDocument.Print method is called.

To do this, follow these steps:  In Microsoft Visual Studio .NET 2003, create a new Visual Basic Windows Application. Add two or tree Windows Forms controls to Form1.vb. For example, add a TextBox control, a CheckBox control, and a Button control to the form. Click the Button1 control, and change the Text property to Print in the Properties window. In Solution Explorer, right-click Form1.vb, and then click View Code.  Add the following Imports statements to the top of the Form1.vb source code: Imports System.Drawing.Printing Imports System.Drawing.Graphics Imports System.Drawing.Imaging Imports System.Runtime.InteropServices Note This step adds the required references to call the printing, graphic, imaging and InteropServices functions and methods.   Add the following Win32APICall class to Form1.vb after the Form1 class: Public Class Win32APICall

Public Const DIB_RGB_COLORS = 0 Public Const BI_RGB = 0 Public Const WHITENESS = 16711778

 _ Public Shared Function PrintWindow(ByVal hWnd As IntPtr, ByVal hDC As IntPtr, ByVal dwFlags As Integer) As UInt32 End Function

<StructLayout(LayoutKind.Sequential, pack:=8, CharSet:=CharSet.Auto)> _ Structure BITMAPINFOHEADER Dim biSize As Int32 Dim biWidth As Int32 Dim biHeight As Int32 Dim biPlanes As Int16 Dim biBitCount As Int16 Dim biCompression As Int32 Dim biSizeImage As Int32 Dim biXPelsPerMeter As Int32 Dim biYPelsPerMeter As Int32 Dim biClrUsed As Int32 Dim biClrImportant As Int32 End Structure

<DllImport(&quot;gdi32.dll&quot;, EntryPoint:=&quot;CreateDIBSection&quot;, _   SetLastError:=True, CharSet:=CharSet.Unicode, _    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function CreateDIBSection(ByVal hdc As IntPtr, ByRef pbmi As BITMAPINFOHEADER, _   ByVal iUsage As Int32, ByVal ppvBits As IntPtr, ByVal hSection As IntPtr, _    ByVal dwOffset As Int32) As IntPtr End Function

<DllImport(&quot;gdi32.dll&quot;, EntryPoint:=&quot;PatBlt&quot;, _   SetLastError:=True, CharSet:=CharSet.Unicode, _    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function PatBlt(ByVal hDC As IntPtr, ByVal nXLeft As Int32, _       ByVal nYLeft As Int32, ByVal nWidth As Int32, ByVal nHeight As Int32, _        ByVal dwRop As Int32) As Boolean End Function

<DllImport(&quot;gdi32.dll&quot;, EntryPoint:=&quot;SelectObject&quot;, _   SetLastError:=True, CharSet:=CharSet.Unicode, _    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObj As IntPtr) As IntPtr End Function

<DllImport(&quot;GDI32.dll&quot;, EntryPoint:=&quot;CreateCompatibleDC&quot;, SetLastError:=True, CharSet:=CharSet.Unicode, _   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function CreateCompatibleDC(ByVal hRefDC As IntPtr) As IntPtr End Function

<DllImport(&quot;GDI32.dll&quot;, EntryPoint:=&quot;DeleteDC&quot;, SetLastError:=True, CharSet:=CharSet.Unicode, _   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean End Function

<DllImport(&quot;GDI32.dll&quot;, EntryPoint:=&quot;DeleteObject&quot;, SetLastError:=True, CharSet:=CharSet.Unicode, _   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function DeleteObject(ByVal hObj As IntPtr) As Boolean End Function

<DllImport(&quot;User32.dll&quot;, EntryPoint:=&quot;ReleaseDC&quot;, SetLastError:=True, CharSet:=CharSet.Unicode, _   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean End Function

<DllImport(&quot;User32.dll&quot;, EntryPoint:=&quot;GetDC&quot;, SetLastError:=True, CharSet:=CharSet.Unicode, _   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function GetDC(ByVal hWnd As IntPtr) As IntPtr End Function

End Class Note This step adds the variables, the structures, and the DllImport statements that are required to call unmanaged Windows GDI API functions. </li>  Add the following OnPrintPage event handler procedure to the Form1.vb source code in the Form1 class: Private Sub OnPrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Dim hwndForm As IntPtr hwndForm = Me.Handle

Dim hdcDIBSection As IntPtr Dim hdcRef As IntPtr Dim hbmDIBSection As IntPtr Dim hbmDIBSectionOld As IntPtr Dim BMPheader As Win32APICall.BITMAPINFOHEADER

hdcRef = Win32APICall.GetDC(IntPtr.Zero) hdcDIBSection = Win32APICall.CreateCompatibleDC(hdcRef) Win32APICall.ReleaseDC(IntPtr.Zero, hdcRef)

BMPheader.biBitCount = 24 BMPheader.biClrImportant = 0 BMPheader.biClrUsed = 0 BMPheader.biCompression = Win32APICall.BI_RGB BMPheader.biSize = 40 BMPheader.biHeight = Me.Height BMPheader.biPlanes = 1 BMPheader.biSizeImage = 0 BMPheader.biWidth = Me.Width BMPheader.biXPelsPerMeter = 0 BMPheader.biYPelsPerMeter = 0

hbmDIBSection = Win32APICall.CreateDIBSection(hdcDIBSection, BMPheader, Win32APICall.DIB_RGB_COLORS, _       IntPtr.Zero, IntPtr.Zero, 0)

hbmDIBSectionOld = Win32APICall.SelectObject(hdcDIBSection, hbmDIBSection) Win32APICall.PatBlt(hdcDIBSection, 0, 0, Me.Width, Me.Height, Win32APICall.WHITENESS) Win32APICall.PrintWindow(hwndForm, hdcDIBSection, 0) Win32APICall.SelectObject(hdcDIBSection, hbmDIBSectionOld)

Dim imageFrm As Bitmap imageFrm = Image.FromHbitmap(hbmDIBSection) e.Graphics.DrawImage(imageFrm, 0, 0)

Win32APICall.DeleteDC(hdcDIBSection) Win32APICall.DeleteObject(hbmDIBSection) End Sub

End Class Note This event handler will run when the PrintDocument.Print method is executed. </li>  Add the following code to the Click event for the Print button that you created in step 2 in the Form1 class: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim prd As PrintDocument prd = New PrintDocument

AddHandler prd.PrintPage, AddressOf OnPrintPage

prd.Print End Sub Note This step adds the code that runs when you click the Print button. The code first declares a PrintDocument object. Then, the code adds an event handler by using the AddHandler statement. This event handler runs when the PrintDocument.Print method is called. </li> Press CTRL-F5 to run the solution, and then click Print to print the current Windows form.</li></ol>

<div class="references_section">