Mooseworks Software, LLC
Controls That Work

Printing with Windows CE PCL Drivers


One question that comes up often is "How do I print from Windows CE?" There are a variety of answers to this question, usually depending on platform and printer hardware. The method we present here is through use of the PCL (Printer Control Language from Hewlett Packard) driver. The PCL driver is widely available in Windows CE devices. This code was tested on a 5" x 7" Windows CE 4.2 panel with a USB host port. Since the CE version was 4.2, the sample is done in Visual Studio 2003. The code should work in Visual Studio 2005 as well, however. 

Download the Source Code

The sample application simple prints a screen capture. It has an option for automatically fitting the image to the page. Most of the work is done using API calls, so there are extensive DllImport functions.

 The first step is to capture the screen image. We use the GetCapture API function to get the window handle, and then copy it to a bitmap. The code is shown below.

     'Capture the window handle
    Dim hOldWnd As IntPtr = GetCapture()
    ctl.Capture = True
    Dim hWnd As IntPtr = GetCapture()
    ctl.Capture = False
    SetCapture(hOldWnd)

    'Get DC for entire screen (be sure to destroy later!)
    Dim hdcInput As IntPtr = GetWindowDC(hWnd)
    If (hdcInput.Equals(IntPtr.Zero)) Then
      Return False
    End If

    Dim screenWidth As Integer
    Dim screenHeight As Integer

    If (Not TypeOf (ctl) Is Form) Then
      'Create bitmap for whole screen
      screenWidth = GetSystemMetrics(SM_CXSCREEN)
      screenHeight = GetSystemMetrics(SM_CYSCREEN)
    Else
      'Just size it for the control
      screenWidth = ctl.Width
      screenHeight = ctl.Height
    End If

    Dim hBitmap As IntPtr = CreateCompatibleBitmap(hdcInput, screenWidth, screenHeight)
    If (hdcInput.Equals(IntPtr.Zero)) Then
      Return False
    End If

    Dim hdcOutput As IntPtr = CreateCompatibleDC(hdcInput)
    If (hdcInput.Equals(IntPtr.Zero)) Then
      DeleteDC(hdcInput)
      Return False
    End If

    Dim hbmOld As IntPtr = SelectObject(hdcOutput, hBitmap)

    'Copy the image into the bitmap....
    If (Not BitBlt(hdcOutput, 0, 0, screenWidth, screenHeight, hdcInput, 0, 0, SRCCOPY)) Then
      SelectObject(hdcOutput, hbmOld)
      DeleteDC(hdcOutput)
      DeleteDC(hdcInput)
      Return False
    End If

After some clean up, we load the device context (DC) for the printer using the PCL driver. In this case, we are using the PCL Inkjet device, and LPT1, which is actually the USB host port.

    Dim hPrinterDC As IntPtr = CreateDC("pcl.dll", "PCL Inkjet", "LPT1", IntPtr.Zero)

We then get the printer page size in case we're auto sizing.

      Dim pageSizeX As Integer = GetDeviceCaps(hPrinterDC, HORZRES)     ' page width in pixels
      Dim pageSizeY As Integer = GetDeviceCaps(hPrinterDC, VERTRES)     ' page height in pixels

We put our screen bitmap into a memory DC for transfer to the printer DC.

      'Select bitmap into the generic DC.
      Dim hGenericMemoryDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)
      Dim hOldObj As IntPtr = SelectObject(hGenericMemoryDC, hBitmap)

Then we start the print document. The di parameter is a DOCINFO struct that contains the document name and file name. Once the document is started we draw to the printers DC just like we would draw to any other DC. We use the StretchBlt API function to copy the image to the printer DC. StretchBlt allows us to resize the image. BitBlt could be used if resizing is not desired.

      If (StartDoc(hPrinterDC, di) > 0) Then
        'Tell printer to start page.
        StartPage(hPrinterDC) 

        Dim bmpInfo As BITMAP_STRUC = New BITMAP_STRUC
        GetObject(hBitmap, System.Runtime.InteropServices.Marshal.SizeOf(bmpInfo), bmpInfo)

        'Copy generic DC to the printer (destination) DC.
        Dim scale As Integer = pageSizeX / bmpInfo.bmWidth
        If (scale = 0) Then
          scale = 4
        End If
        If (Not autoscale) Then
          scale = 1
        End If
        StretchBlt(hPrinterDC, 0, 0, bmpInfo.bmWidth * scale, bmpInfo.bmHeight * scale, _
         hGenericMemoryDC, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY)

        'Call end of page and end of document.
        EndPage(hPrinterDC)
        EndDoc(hPrinterDC)
      End If

And thats it. This print out will use the printers default setup, likely monochrome and portrait. To print in a non-default mode requires use of the ChangeDisplaySettingsEx API function and the DeviceMode structure.

Download the Source Code

Products
 Graph
 Trend Graph
 Visual Dashboard
 Instrumentation
 User Entry
 Email
Download Demos
 Graph
 Trend Graph
 Visual Dashboard
 Instrumentation
 User Entry
 Email
Support
 Contact
Testimonials
 Testimonials
 Awards
Articles
 VS2005 Control Design
 Windows CE Printing
 Links
About Us
 Home
 Contact
 News
 Legend