HOWTO: Print Form or Client Area to Size on PostScript or PCL Printer
ID: Q85978
|
The information in this article applies to:
-
Microsoft Visual Basic Standard and Professional Editions for Windows, versions 2.0, 3.0
-
Microsoft Visual Basic programming system for Windows, version 1.0
SUMMARY
This article demonstrates two Visual Basic procedures: PrintWindow and
PrintClient. Both procedures allow you to print a control or form at a
specified size and location (a printed page, another form, or a picture
control).
The PrintWindow procedure allows you to print the entire control including
the border, caption, and menus.
The PrintClient procedure prints everything contained in the form or
control excluding the border, caption, and menus. When passed a form, the
PrintClient procedure works just like Visual Basic's PrintForm method.
Both procedures (PrintWindow and PrintClient) print all child controls
contained in the form or control. And both use the StretchDIBits Window API
function as well as other Windows API functions to print a form or control.
These functions will print to both Postscript and PCL (printer control
language) or HP-type LaserJet printers.
MORE INFORMATION
This information is included with the Help file provided with Microsoft
Visual Basic version 3.0.
Step-by-Step Example
The following steps show you how to create a program that prints a form
on the printer.
- Start Visual Basic or from the File menu, choose New Project (ALT, F, N) if Visual Basic is already running. Form1 is created by default.
- Add two command buttons (Command1 and Command2) to Form1.
- Load the WINLOGO.BMP file (or some other large bitmap) into the Picture property of Form1. WINLOGO.BMP should be in the \WINDOWS directory.
- From the File menu, choose New Module (ALT, F, M). Module1 is created by default.
- Add the following code to Module1:
'*********************************************************************
'* Project
'* PrintAll.MAK
'*
'* Contents
'* PrintALL.FRM (Form1)
'* PrintALL.BAS
'* Structure
'* Form1 can contain any number of controls.
'* The minimum number to demonstrate both client area
'* printing and entire form printing is two command buttons.
'* For illustration, assign a large bitmap to the picture
'* property of Form1.
'*
'* Description:
'* This example successfully prints on both PostScript and
'* PCL (Printer Control Language: the non-PostScript type)
'* printers. The printer output is of the same resolution as
'* you would expect from the PrintForm method or from
'* printing the form from the VB environment. Both the
'* PrintClient and PrintWindow procedures are generic in
'* that they can be used to print any visible window. To
'* incorporate the code into your project, add PrintAll.BAS
'* in the project and paste the code in the PrintAll.GLB
'* program into a code module. The code in the
'* Command1_Click and Command2_Click events demonstrates how
'* to call the two procedures PrintWindow and PrintClient. To
'* print any active window, use the Appactivate and the
'* GetFocus functions to get the handle to the window to pass
'* to the procedures.
'*
'*********************************************************************
'*********************************************************************
'* Module
'* PrintAll.BAS
'*
'* Description:
'* Contains all the necessary Windows API function and Type
'* structure declarations
'*********************************************************************
DefInt A-Z
Type BITMAPINFOHEADER_Type
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Type BITMAPINFO_Type
BitmapInfoHeader As BITMAPINFOHEADER_Type
bmiColors As String * 1024
End Type
Type RectType
Left As Integer
Top As Integer
Right As Integer
Bottom As Integer
End Type
Type PointType
x As Integer
y As Integer
End Type
' DC related API
Declare Function CreateCompatibleDC Lib "gdi" (ByVal hDC)
Declare Function GetWindowDC Lib "user" (ByVal hWnd)
Declare Function GetDC Lib "user" (ByVal hWnd)
Declare Function ReleaseDC Lib "user" (ByVal hWnd, ByVal hDC)
Declare Function DeleteDC Lib "gdi" (ByVal hDC)
' Graphics related API
' Enter the following Declare statement as one, single line:
Declare Function BitBlt Lib "gdi" (ByVal hDC, ByVal x, ByVal y,
ByVal w, ByVal h, ByVal hDC, ByVal x, ByVal y, ByVal o As Long)
' Enter the following Declare statement as one, single line:
Declare Function GetDIBits Lib "gdi" (ByVal hDC, ByVal hBitmap,
ByVal nStartScan, ByVal nNumScans, ByVal lpBits As Long,
BitmapInfo As BITMAPINFO_Type, ByVal wUsage)
' Enter the following Declare statement as one, single line:
Declare Function StretchDIBits Lib "gdi" (ByVal hDC, ByVal DestX,
ByVal DestY, ByVal wDestWidth, ByVal wDestHeight, ByVal SrcX,
ByVal SrcY, ByVal wSrcWidth, ByVal wSrcHeight, ByVal lpBits&,
BitsInfo As BITMAPINFO_Type, ByVal wUsage, ByVal dwRop&)
' General attribute related API
Declare Function GetDeviceCaps Lib "gdi" (ByVal hDC, ByVal nIndex)
Declare Function GetWindowRect Lib "user" (ByVal hWnd, lpRect As RectType)
Declare Function GetClientRect Lib "user" (ByVal hWnd, lpRect As RectType)
' Memory allocation related API
Declare Function GlobalAlloc Lib "kernel" (ByVal wFlags, ByVal lMem&)
Declare Function GlobalLock Lib "kernel" (ByVal hMem) As Long
Declare Function GlobalUnlock Lib "kernel" (ByVal hMem)
Declare Function GlobalFree Lib "kernel" (ByVal hMem)
' Graphics object related API
' Enter the following Declare statement as one, single line:
Declare Function CreateCompatibleBitmap Lib "gdi" (ByVal hDC, ByVal nWidth,
ByVal nHeight)
Declare Function DeleteObject Lib "gdi" (ByVal hObject)
Declare Function SelectObject Lib "gdi" (ByVal hDC, ByVal hObject)
Declare Function ClientToScreen Lib "user" (ByVal hWnd%, p As PointType)
' Include the following constant declarations if using Visual Basic
' version 1.0
' Const False = 0
' Const True = Not False
Const HORZRES = 8
Const VERTRES = 10
Const SRCCOPY = &HCC0020
Const NEWFRAME = 1
Const BITSPIXEL = 12
Const PLANES = 14
Const BI_RGB = 0
Const BI_RLE8 = 1
Const BI_RLE4 = 2
Const DIB_PAL_COLORS = 1
Const DIB_RGB_COLORS = 0
Const GMEM_MOVEABLE = 2
- Add the following function (PrintWindow) to Module1:
'*********************************************************************
'* Title
'* PrintWindow()
'*
'* Description
'*
'* Copies the entire window (form or control) to another
'* window (form or control) or device such as a printer. This
'* routine is capable of printing complete form images on any
'* printer that has Windows drivers loaded including Postscript.
'*
'* The API functions GetDIBits and StretchDIBits are used to copy
'* the client area image to the destination window or device.
'*
'* Parameters:
'* hDC_Dest Handle to the DC of the destination device or
'* window.
'* DestX X position of where the image will be
'* displayed on the destination device.
'* DestY Y position of where the image will be
'* displayed on the destination device.
'* DestDevWidth Pixel width of the destination device.
'* DestDevHeight Pixel height of the destination device.
'* hWnd_SrcWindow Window handle of the source window to be
'* displayed on the destination device.
'*********************************************************************
' Enter the following statement as one, single line:
Function PrintWindow (ByVal hDC_Dest, ByVal DestX, ByVal DestY,
ByVal DestDevWidth, ByVal DestDevHeight, ByVal hWnd_SrcWindow)
Dim Rect As RectType
Dim BitmapInfo As BITMAPINFO_Type
cr$ = Chr$(13)
' Get the DC for the entire window including the non-client area.
hDC_Window = GetWindowDC(hWnd_SrcWindow)
hDC_Mem = CreateCompatibleDC(hDC_Window)
' Get the pixel dimensions of the screen. This is necessary so
' that we can determine the relative size of the window compared to
' the screen
ScreenWidth = GetDeviceCaps(hDC_Window, HORZRES)
ScreenHeight = GetDeviceCaps(hDC_Window, VERTRES)
' Get the pixel dimensions of the window to be printed.
r = GetWindowRect(hWnd_SrcWindow, Rect)
Window_Width = Abs(Rect.Right - Rect.Left)
Window_Height = Abs(Rect.Bottom - Rect.Top)
' Create a bitmap compatible with the window DC. Enter the following
' statement as one, single line:
hBmp_Window = CreateCompatibleBitmap(hDC_Window, Window_Width,
Window_Height)
' Select the bitmap to hold the window image into the memory DC.
hPrevBmp = SelectObject(hDC_Mem, hBmp_Window)
' Copy the image of the window to the memory DC. Enter the following
' statement as one, single line:
r1 = BitBlt(hDC_Mem, 0, 0, Window_Width, Window_Height, hDC_Window,
0, 0, SRCCOPY)
BitsPerPixel = GetDeviceCaps(hDC_Mem, BITSPIXEL)
ColorPlanes = GetDeviceCaps(hDC_Mem, PLANES)
BitmapInfo.BitmapInfoHeader.biSize = 40
BitmapInfo.BitmapInfoHeader.biWidth = Window_Width
BitmapInfo.BitmapInfoHeader.biHeight = Window_Height
BitmapInfo.BitmapInfoHeader.biPlanes = 1
BitmapInfo.BitmapInfoHeader.biBitCount = BitsPerPixel * ColorPlanes
BitmapInfo.BitmapInfoHeader.biCompression = BI_RGB
BitmapInfo.BitmapInfoHeader.biSizeImage = 0
BitmapInfo.BitmapInfoHeader.biXPelsPerMeter = 0
BitmapInfo.BitmapInfoHeader.biYPelsPerMeter = 0
BitmapInfo.BitmapInfoHeader.biClrUsed = 0
BitmapInfo.BitmapInfoHeader.biClrImportant = 0
' Calculate the ratios based on the source and destination
' devices. This will help to cause the size of the window image
' to be approximately the same proportion on another device
' such as a printer.
WidthRatio! = Window_Width / ScreenWidth
HeightAspectRatio! = Window_Height / Window_Width
PrintWidth = WidthRatio! * DestDevWidth
PrintHeight = HeightAspectRatio! * PrintWidth
' Calculate the number of bytes needed to store the image assuming
' 8 bits/pixel.
BytesNeeded& = (CLng(Window_Width + 3) \ 4) * 4 * Window_Height
' Allocate a buffer to hold the bitmap bits.
hMem = GlobalAlloc(GMEM_MOVEABLE, BytesNeeded&)
' Enter the following If statement as one, single line:
If hDC_Window <> 0 And hBmp_Window <> 0 And hDC_Dest <> 0 And
hMem <> 0 Then
lpBits& = GlobalLock(hMem)
' Get the bits that make up the image and copy them to the
' destination device.
' Enter the following r2 statement as one, single line:
r2 = GetDIBits(hDC_Mem, hBmp_Window, 0, Window_Height, lpBits&,
BitmapInfo, DIB_RGB_COLORS)
' Enter the following r3 statement as one, single line:
r3 = StretchDIBits(hDC_Dest, DestX, DestY, PrintWidth, PrintHeight,
0, 0, Window_Width, Window_Height, lpBits&, BitmapInfo,
DIB_RGB_COLORS, SRCCOPY)
End If
' Reselect in the previous bitmap and delete the bitmap we created
r = SelectObject(hDC_Mem, hPrevBmp)
r = DeleteObject(hBmp_Window)
' Release or delete DC's and memory.
r = GlobalUnlock(hMem)
r = GlobalFree(hMem)
r = DeleteDC(hDC_Mem)
r = ReleaseDC(hWnd_SrcWindow, hDC_Window)
' Return true if the window was successfully printed.
If r2 <> 0 And r3 <> 0 Then
PrintWindow = True
Else
PrintWindow = False
End If
End Function
- Add the following function, PrintClient to Module1:
'*********************************************************************
'* Title
'* PrintClient()
'*
'* Description
'*
'* Copies the client area of a window visible on the desktop to
'* another window or device such as a printer. This routine is
'* capable of printing client area images on any printer that has
'* Windows drivers loaded including PostScript.
'*
'* The API functions GetDiBits and StretchBits are used to copy
'* the client area image to the destination device.
'*
'* Parameters:
'* hDC_Dest Handle to the DC of the destination device or
'* window.
'* DestX X position of where the image will be
'* displayed on the destination device.
'* DestY Y position of where the image will be
'* displayed on the destination device.
'* DestDevWidth Pixel width of the destination device.
'* DestDevHeight Pixel height of the destination device.
'* hWnd_SrcWindow Window handle of the source window to be
'* displayed on the destination device.
'*********************************************************************
' Enter the following Function statement as one, single line:
Function PrintClient (ByVal hDC_Dest, ByVal DestX, ByVal DestY,
ByVal DestDevWidth, ByVal DestDevHeight, ByVal hWnd_SrcWindow)
Dim Rect As RectType, RectClient As RectType
Dim BitmapInfo As BITMAPINFO_Type
'*
Dim pWindow As PointType, pClient As PointType, pDiff As PointType
'*
cr$ = Chr$(13)
' Get the DC for the entire window including the non-client area.
hDC_Window = GetWindowDC(hWnd_SrcWindow)
hDC_Mem = CreateCompatibleDC(hDC_Window)
' Get the pixel dimensions of the screen.
ScreenWidth = GetDeviceCaps(hDC_Window, HORZRES)
ScreenHeight = GetDeviceCaps(hDC_Window, VERTRES)
' Get the pixel dimensions of the window to be printed.
r = GetWindowRect(hWnd_SrcWindow, Rect)
Window_Width = Abs(Rect.Right - Rect.Left)
Window_Height = Abs(Rect.Bottom - Rect.Top)
' Create a bitmap compatible with the window DC.
' Enter the following statement as one, single line:
hBmp_Window = CreateCompatibleBitmap(hDC_Window, Window_Width,
Window_Height)
' Select the bitmap to hold the window image into the memory DC.
hPrevBmp = SelectObject(hDC_Mem, hBmp_Window)
' Copy the image of the window to the memory DC.
' Enter the following statement as one, single line:
r1 = BitBlt(hDC_Mem, 0, 0, Window_Width, Window_Height,
hDC_Window, 0, 0, SRCCOPY)
' Get the dimensions of the client area.
r = GetClientRect(hWnd_SrcWindow, RectClient)
Client_Width = Abs(RectClient.Right - RectClient.Left)
Client_Height = Abs(RectClient.Bottom - RectClient.Top)
' Calculate the pixel difference (x and y) between the upper-left
' corner of the non-client area and the upper-left corner of the
' client area.
pClient.x = RectClient.Left
pClient.y = RectClient.Top
r = ClientToScreen(hWnd_SrcWindow, pClient)
xDiff = Abs(pClient.x - Rect.Left)
yDiff = Abs(pClient.y - Rect.Top)
' Create a DC and bitmap to represent the client area of the window.
hDC_MemClient = CreateCompatibleDC(hDC_Window)
' Enter the following statement as one, single line:
hBmp_Client = CreateCompatibleBitmap(hDC_Window, Client_Width,
Client_Height)
hBmpClientPrev = SelectObject(hDC_MemClient, hBmp_Client)
' Bitblt client area of window to memory bitmap representing the client
' area.
' Enter the following statement as one, single line:
r = BitBlt(hDC_MemClient, 0, 0, Client_Width, Client_Height,
hDC_Mem, xDiff, yDiff, SRCCOPY)
BitsPerPixel = GetDeviceCaps(hDC_MemClient, BITSPIXEL)
ColorPlanes = GetDeviceCaps(hDC_MemClient, PLANES)
BitmapInfo.BitmapInfoHeader.biSize = 40
BitmapInfo.BitmapInfoHeader.biWidth = Client_Width
BitmapInfo.BitmapInfoHeader.biHeight = Client_Height
BitmapInfo.BitmapInfoHeader.biPlanes = 1
BitmapInfo.BitmapInfoHeader.biBitCount = BitsPerPixel * ColorPlanes
BitmapInfo.BitmapInfoHeader.biCompression = BI_RGB
BitmapInfo.BitmapInfoHeader.biSizeImage = 0
BitmapInfo.BitmapInfoHeader.biXPelsPerMeter = 0
BitmapInfo.BitmapInfoHeader.biYPelsPerMeter = 0
BitmapInfo.BitmapInfoHeader.biClrUsed = 0
BitmapInfo.BitmapInfoHeader.biClrImportant = 0
' Calculate the ratios based on the source and destination
' devices. This will help to cause the size of the window image to
' be approximately the same proportion on another device such as
' a printer.
WidthRatio! = Client_Width / ScreenWidth
HeightAspectRatio! = Client_Height / Client_Width
PrintWidth = WidthRatio! * DestDevWidth
PrintHeight = HeightAspectRatio! * PrintWidth
' Calculate the number of bytes needed to store the image assuming
' 8 bits/pixel.
BytesNeeded& = (CLng(Window_Width + 3) \ 4) * 4 * Window_Height
' Allocate a buffer to hold the bitmap bits.
hMem = GlobalAlloc(GMEM_MOVEABLE, BytesNeeded&)
If hDC_Window <> 0 And hBmp_Window <> 0 And hDC_Dest <> 0 And
hMem <> 0 Then
lpBits& = GlobalLock(hMem)
' Get the bits that make up the image and copy them to the
' destination device.
' Enter the following r2 statement as one, single line:
r2 = GetDIBits(hDC_MemClient, hBmp_Client, 0, Client_Height,
lpBits&, BitmapInfo, DIB_RGB_COLORS)
' Enter the following r3 statement as one, single line:
r3 = StretchDIBits(hDC_Dest, DestX, DestY, PrintWidth, PrintHeight,
0, 0, Client_Width, Client_Height, lpBits&, BitmapInfo,
DIB_RGB_COLORS, SRCCOPY)
End If
' Select in the previous bitmap and delete the one we created
' that's associated with the Client area
r = SelectObject(hDC_MemClient, hBmpClientPrev)
r = DeleteObject(hBmp_Client)
' delete the client DC we created
r = DeleteDC(hDC_MemClient)
' Select the previous bitmap and delete the one we created
' that's associated with the memory DC
r = SelectObject(hDC_Mem, hPrevBmp)
r = DeleteObject(hBmp_Window)
' delete the memory DC we created
r = DeleteDC(hDC_Mem)
' release the Window DC
r = ReleaseDC(hWnd_SrcWindow, hDC_Window)
' and free the memory we allocated
r = GlobalUnlock(hMem)
r = GlobalFree(hMem)
' Return true if the window was successfully printed.
If r2 <> 0 And r3 <> 0 Then
PrintClient = True
Else
PrintClient = False
End If
End Function
- Add DefInt A-Z to the General Declarations level of Form1.
- Add the following code to the Command1_Click event:
Sub Command1_Click ()
' The ScaleMode must be set to pixels for the PrintWindow
' routine to print correctly.
Printer.ScaleMode = 3
' Change MousePointer to an hourglass.
Screen.MousePointer = 11
' Initialize the printer.
Printer.Print ""
' Copy the image of the form to the printer.
' To print Command1 instead, you can substitute Command1.hWnd for
' Form1.hWnd as the last argument.
' Enter the following statement as one, single line:
r = PrintClient(Printer.hDC, 100, 100, Printer.ScaleWidth,
Printer.ScaleHeight, Form1.hWnd)
' Display an error if the return value from PrintWindow is zero.
If Not r Then
MsgBox "Unable to print the form"
Else
Printer.EndDoc
End If
Screen.MousePointer = 0
End Sub
- Add the following code to the Command2_Click event:
Sub Command2_Click ()
' The ScaleMode must be set to pixels for the PrintWindow
' routine to print correctly.
Printer.ScaleMode = 3
' Change MousePointer to an hourglass.
Screen.MousePointer = 11
' Initialize the printer.
Printer.Print ""
' Copy the image of the form to the printer.
' To print Command1 instead, you can substitute Command1.hWnd for
' Form1.hWnd as the last argument.
' Enter the following statement as one, single line:
r = PrintWindow(Printer.hDC, 100, 100, Printer.ScaleWidth,
Printer.ScaleHeight, Form1.hWnd)
' Display an error if the return value from PrintWindow is zero.
If Not r Then
MsgBox "Unable to print the form"
Else
Printer.EndDoc
End If
Screen.MousePointer = 0
End Sub
- Run the program.
Choose the Command1 button to print only the client area of Form1. Choose
the Command2 button to print the entire area of the form.
NOTE: You can print any of the forms or controls in a project by using this method. Control the size and placement of the forms by changing the second, third, fourth, and fifth parameters of the call to StretchDIBits.
In the example shown above, the form or control is sized in proportion to
the size of the screen.
Additional query words:
2.00 3.00
Keywords :
Version : WINDOWS:1.0,2.0,3.0
Platform : WINDOWS
Issue type : kbhowto
|