How to print the active Windows form in Visual Basic .NET (890894)



The information in this article applies to:

  • Microsoft Visual Studio .NET (2003), Professional Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Developer Edition
  • 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:
  1. In Microsoft Visual Studio .NET 2003, create a new Visual Basic Windows Application.
  2. 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.
  3. Click the Button1 control, and change the Text property to Print in the Properties window.
  4. In Solution Explorer, right-click Form1.vb, and then click View Code.
  5. 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.
  6. 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
    
        <DllImport("user32.dll", EntryPoint:="PrintWindow", _
        SetLastError:=True, CharSet:=CharSet.Unicode, _
        ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
        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("gdi32.dll", EntryPoint:="CreateDIBSection", _
        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("gdi32.dll", EntryPoint:="PatBlt", _
        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("gdi32.dll", EntryPoint:="SelectObject", _
        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("GDI32.dll", EntryPoint:="CreateCompatibleDC", SetLastError:=True, CharSet:=CharSet.Unicode, _
        ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
        Public Shared Function CreateCompatibleDC(ByVal hRefDC As IntPtr) As IntPtr
        End Function
    
        <DllImport("GDI32.dll", EntryPoint:="DeleteDC", SetLastError:=True, CharSet:=CharSet.Unicode, _
        ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
        Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
        End Function
    
        <DllImport("GDI32.dll", EntryPoint:="DeleteObject", SetLastError:=True, CharSet:=CharSet.Unicode, _
        ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
        Public Shared Function DeleteObject(ByVal hObj As IntPtr) As Boolean
        End Function
    
        <DllImport("User32.dll", EntryPoint:="ReleaseDC", 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("User32.dll", EntryPoint:="GetDC", 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.
  7. 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.
  8. 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.
  9. Press CTRL-F5 to run the solution, and then click Print to print the current Windows form.

Modification Type:MajorLast Reviewed:8/30/2005
Keywords:kbGDI kbWindowsForms kbhowto kbinfo KB890894 kbAudDeveloper