Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Capture Desktop image and Print to Printer

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Tom Hanlin
    replied
    COMDLG32.INC is quite definitely included in the Win32API.zip
    archive. It may also be found in your PB/DLL WINAPI folder.

    Please remember that the Source Code forum is for source code,
    not discussions. Topic closed.

    ------------------
    Tom Hanlin
    PowerBASIC Staff

    Leave a comment:


  • Werner Lentz
    replied
    Hi, I couldn't find the "COMDLG32.INC" file either. It is not included in the "WIN32API.ZIP" file from the files-section.
    Can somebody help?
    Thanks,

    Werner

    ------------------

    Leave a comment:


  • Gajanan Raje
    replied
    I use Don Dickinson's code above to print bmp files and it works
    great. Thanks Don.

    When a printer dialog opens it comes with "Portrait" orientation as
    default. How can the default orientation be made to be "Landscape"
    in the printer dialog ?

    Thanks.

    Gajanan

    ------------------

    Leave a comment:


  • Eric Pearson
    replied
    Dan --

    COMDLG32.INC is contained in the WIN32API.ZIP file, which can be found here...

    ftp://ftp.powerbasic.com/pub/support

    As for whether or not it works with PB/CC, it should work perfectly.

    -- Eric

    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>



    [This message has been edited by Eric Pearson (edited February 08, 2000).]

    Leave a comment:


  • Daniel Raymer
    replied
    Hi - does the Don Dickinson code compile under PB/CC? I get "COMDLG32.INC" not found when I try to compile it. Also, could you post an example of how to use it, please?

    Leave a comment:


  • Dave Navarro
    replied
    I think Don Dickinson wrote this code:
    Code:
    $COMPILE EXE
    $DIM ALL
    $INCLUDE "WIN32API.INC"
    $INCLUDE "COMDLG32.INC"
     
    '==================================================================
    '   1. PRELIMINARY STEP   -     **** IMPORTANT ****
    '   You need to go into your win32api.inc file and change the declaration
    '   for the BITMAPINFO structure's bmi Colors member to 256. If you don't
    '   you'll gpf on all bitmaps that aren't monochrome.
    '
    '   TYPE BITMAPINFO
    '      bmiHeader AS BITMAPINFOHEADER
    '      bmiColors(256) AS RGBQUAD
    '   END TYPE
    '==================================================================
     
    '==================================================================
    FUNCTION BltImage(zFile AS ASCIIZ, BYVAL iPrinting AS INTEGER, _
      BYVAL x AS DOUBLE, BYVAL y AS DOUBLE, BYVAL wid AS DOUBLE, _
      BYVAL hgt AS DOUBLE, BYVAL dcOut AS LONG) EXPORT AS INTEGER
     
       '  The function will take the name of a .BMP file (sImageFile)
       '  and a value (iPrinting) to tell us whether or not we're printing.
       '  If printing we'll need to use the DIB calls.
       '  Also passed are the left and top coordinates (x and y) and
       '  width and height of the bitmap to display (wid and hgt).
       '  The function will fit the image inside the rectangle defined
       '  by x, y, wid, and hgt. All measurements are in inches.
       '  Finally, the DC of the surface to blt to is passed (hDC)
       '
     
       '  Variable declarations
      DIM ppiX AS LONG           ' pixels per inch in X direction
      DIM ppiY AS LONG           ' pixels per inch in Y direction
      DIM x1 AS LONG             ' This will contain the X position in Pixels
      DIM y1 AS LONG             ' This will contain the Y position in Pixels
      DIM w1 AS LONG             ' This will contain the width in Pixels
      DIM h1 AS LONG             ' This will contain the height in Pixels
     
      DIM hDesktop AS LONG       ' A handle to the desktop window (for reference)
      DIM hBitmap AS LONG        ' A handle to the bitmap while it's in memory
      DIM dcWindow AS LONG       ' We need to obtain a temporary DC
      DIM dcBitmap AS LONG       ' Another temporary DC compatible with the
                                 ' dcWindow that will be used to reference
                                 ' the bitmap hBitmap.
      DIM hOldBM AS LONG         ' Another temporary handle.
     
      DIM bmSize AS LONG         ' How big is our DIB going to have to be
      DIM ptrMem AS LONG         ' Pointer to the gMemory string.
      DIM gMemory AS STRING      ' Space to put the DIB Bits
      DIM rBitmap AS BITMAP      ' Structure describing the dependent bitmap
      DIM bmInfo AS BITMAPINFO   ' Structure describing the independent bitmap
     
      '- STEP 1 - ensure that we have properly altered the BITMAPINFO structure
      IF SIZEOF(bmInfo) < 40 + 256 * 4 THEN
        MsgBox "The BITMAPINFO structure doesn't have enough space in the " + _
          "bmiColors array. Please define it with at least 256 array members."
        FUNCTION = %False
      ELSE
        '- STEP 2 - Do unit conversions from inches to output units
        ppiX = GetDeviceCaps(dcOut, %LOGPIXELSX)
        ppiY = GetDeviceCaps(dcOut, %LOGPIXELSY)
        x1 = ppiX * x
        y1 = ppiY * y
        w1 = ppiX * wid
        h1 = ppiY * hgt
     
        '- STEP 3               Load the BMP
        '  Load the bitmap into memory. This function requires Win95 or WinNT v4.
        '  Instead of doing this, you could also pass the handle to the bitmap.
        '  This call requires the width and height of the bitmap be passed as
        '  well as the name of the file.
     
        hBitmap = LoadImage(0, zFile, %IMAGE_BITMAP, 0, 0, %LR_LOADFROMFILE)
        IF hBitmap = 0 THEN
          MsgBox "Can't load bitmap"
          FUNCTION = %FALSE
        ELSE
          '- STEP 4            Get a temp DC for bmp manipulation
          '  For printing the bitmap, we will need a temporary dc
          '  compatible with the display. For blting to the screen,
          '  we need a temporary dc to hold the bitmap that will
          '  be blted to the screen. We'll just create one compaible
          '  with the desktop window.
     
          hDesktop = GetDesktopWindow()
          dcWindow = GetDC(hDesktop)
          dcBitmap = CreateCompatibleDC(dcWindow)
          ReleaseDC hDesktop, dcWindow
     
          IF iPrinting = %False THEN
            '- STEP 5-A       Not printing, so blt the image.
            '  If we're not printing, then copying the bitmap is a simple
            '  matter of calling bitblt. We need to first get the height and
            '  width of the bitmap so it can be proportionally fit into the
            '  defined rectangle.
     
            GetObject hBitmap, len(rBitmap), rBitmap
     
            '- Proportionally fit the bitmap inside of the defined rectangle
            IF (rBitmap.bmWidth / rBitmap.bmHeight) > (w1 / h1) THEN
              h1 = w1 * rBitmap.bmHeight / rBitmap.bmWidth
            ELSE
              w1 = h1 * rBitmap.bmWidth / rBitmap.bmHeight
            END IF
     
            hOldBM = SelectObject(dcBitmap, hBitmap)
            BitBlt dcOut, x1, y1, w1, h1, dcBitmap, 0, 0, %SRCCOPY
            SelectObject dcBitmap, hOldBM
            FUNCTION = %True
          ELSE
            '- STEP 4-B       Create a DIB
            '  If we're blting to a printer, then we need to create
            '  a DIB from the device dependent bitmap (hBitmap).
            '  This area of the routine is the most involved. For those
            '  not familiar with a DIB, I will quickly explain ...
     
            '     A device dependent bitmap is a window object that
            '     can be manipulated with API calls. A DIB is merely
            '     a memory area containing pixel information and a
            '     structure describing it. You can't use SelectObject
            '     on a dib because it isn't a Windows Object. To convert
            '     a device dependent bitmap into a DIB requires 2 things.
            '        1. Fill out a structure containing the description of
            '           the DIB's Bits
            '        2. Get the actual bits in the correct format into an
            '           area of memory.
            '     Once these things are done, the API has a few calls
            '     to manipulate the dibs based on it's structure and a
            '     pointer to it's bits.
     
            GetObject hBitmap, len(rBitmap), rBitmap
            bmInfo.bmiHeader.biSize = len(bmInfo.bmiHeader)
            bmInfo.bmiHeader.biWidth = rBitmap.bmWidth
            bmInfo.bmiHeader.biHeight = rBitmap.bmHeight
            bmInfo.bmiHeader.biPlanes = 1
            bmInfo.bmiHeader.biBitCount = rBitmap.bmBitsPixel
            bmInfo.bmiHeader.biCompression = %BI_RGB
     
            '- Calculate space needed for the dib bits
            bmSize = bmInfo.bmiHeader.biWidth
            bmSize = (bmSize + 1) * (bmInfo.bmiHeader.biBitCount / 8)
            bmSize = ((bmSize + 3) / 4) * 4
            bmSize = bmSize * bmInfo.bmiHeader.biHeight
     
            '- Allocate the memory
            ON ERROR RESUME NEXT
            gMemory = STRING$(bmSize, CHR$(0))
            ON ERROR GOTO 0
            IF ERR THEN
              '- Couldn't get the memory
              FUNCTION = %FALSE
            ELSE
              '- Proportionally fit the bitmap inside of the defined rectangle
              IF (rBitmap.bmWidth / rBitmap.bmHeight) > (w1 / h1) THEN
                h1 = w1 * rBitmap.bmHeight / rBitmap.bmWidth
              ELSE
                w1 = h1 * rBitmap.bmWidth / rBitmap.bmHeight
              END IF
     
              '- STEP 6               Copy Bits
              '  This step takes the hBitmap object and copies it's
              '  bits over to our memory in a DIB format.
     
              ptrMem = STRPTR(gMemory)
              GetDIBits dcBitmap, hBitmap, 0, bmInfo.bmiHeader.biHeight, _
                BYVAL ptrMem, bmInfo, %DIB_RGB_COLORS
     
              '- STEP 7               Blt the bits to the printer
              '  FINALLY, the moment of truth. We have our structure
              '  and memory full of DIB Bits, so we can call StretchDIBits
              '  to blt the bits onto the printer's DC
     
              StretchDIBits dcOut, x1, y1, w1, h1, 0, 0, bmInfo.bmiHeader.biWidth, _
                bmInfo.bmiHeader.biHeight, BYVAL ptrMem, bmInfo, _
                %DIB_RGB_COLORS, %SRCCOPY
     
              FUNCTION = %True
            END IF      '_ err, else
     
            '- STEP 8               Clean up after myself
            '  To ensure we don't have any memory leaks, we need
            '  to clean up after ourselves.
     
            DeleteObject hBitmap
            DeleteDC dcBitmap
            gMemory = ""
          END IF	'_ if printing% = 0, else
        END IF	'_ if hBitmap = 0, else
      END IF	'_ if bad structure, else
     
    END FUNCTION
     
    '===================================================================
    FUNCTION WinMain(BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _
      lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
     
      DIM zCommand AS ASCIIZ * 255
      DIM i AS LONG
      DIM dcPrint AS LONG
      DIM iCopies AS LONG, iFrom AS LONG, iTo AS LONG
      DIM iMin AS LONG, iMax AS LONG, iOptions AS LONG
      DIM rDocInfo AS DOCINFO
      DIM zString AS ASCIIZ * 256
     
      '- The command line should contain the name of the bmp file
      zCommand = @lpCmdLine
      IF INSTR(zCommand, ".") < 1 THEN
        zCommand = TRIM$(zCommand) + ".bmp"
      END IF
     
      IF DIR$(zCommand) = "" THEN
        MsgBox "Usage: printbmp bitmap.bmp" + CHR$(13) + _
          "Pass the bitmap name on the command line."
      ELSE
        '- Prompt the user for a printer
        iOptions = %PD_COLLATE + %PD_HIDEPRINTTOFILE + %PD_RETURNDC + _
          %PD_NOSELECTION + %PD_PAGENUMS
     
        iFrom = 1: iTo = 1: iMin = 1: iMax = 1: iCopies = 1
        PrinterDialog %NULL, iOptions, dcPrint, iCopies, iFrom, iTo, iMin, iMax
        IF dcPrint THEN
          SetCursor LoadCursor(%NULL, BYVAL %IDC_WAIT)
          '- Init the document
          zString = "Bitmap Printed: " + zCommand
          rDocInfo.lpszDocName = VARPTR(zString)
          rDocInfo.lpszOutput = %NULL
          StartDoc dcPrint, rDocInfo
          FOR i = 1 TO iCopies
            StartPage dcPrint
            TextOut dcPrint, 200, 200, zString, LEN(zString)
     
            '- Here's the big call to do the printing. For test purposes
            '  I print it in at 1" over, 1" down, 3" wide, and 2" high
            '  rectangle.
            BltImage zCommand, %True, 1, 1, 3, 2, dcPrint
            EndPage dcPrint
          NEXT i
     
          '- Clean up
          EndDoc dcPrint
          DeleteDC dcPrint
          SetCursor LoadCursor(%NULL, BYVAL %IDC_ARROW)
        END IF	'_ if dcPrint
      END IF	'_ if bitmap file exist
     
    END FUNCTION

    -------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Fred Oxenby
    replied
    Second Edition


    -------------
    Fred
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Don Dickinson
    replied
    Hey Dave,
    What is Windows 98 SE - specifically what's SE? Someone asked me that yesterday and I didn't have an answer.
    tia,
    Don

    Leave a comment:


  • Dave Navarro
    replied
    It works in Windows 98 SE too.

    Thanks for the heads up! I'll work on it this weekend and upload a fix.

    --Dave


    -------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Don Dickinson
    replied
    According to the sdk
    ... BitBlt returns an error if the source and destination device contexts represent different devices ...
    You have a screen dc being blt'd to one comptible with the printer. That's probably why bitblt is failing. Printing bitmaps is best done with DIBs as described in Petzold and the article in Basically Speaking (www.infoms.com/bsp.htm). The bitmap for the screen is device dependent so you'll likely have inconsistent results trying to print it. It's interesting that the NT machines all seem to work.
    Best Regards,
    Don

    Leave a comment:


  • Dave Navarro
    replied
    It's definitely a Windows 95/98 problem, but I'm still not sure how to fix it yet. I tried it on an older Windows 98 machine and it failed.

    --Dave

    -------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Jim Padgett
    replied
    I did not have a problem with it.
    I am on NT 4.0 SP3 printing to a networked Lexmark 1625 printer.

    Leave a comment:


  • Dave Navarro
    replied
    Alright, I'm gonna need help with this. Ken Lundberg also emailed me with the same problem.

    It works perfectly for me on my Windows NT 4.0 (SP3) machine and Windows 98 laptop. Both are connected to a network and printing to an HP DeskJet 697C and an HP LaserJet 6.

    Both machines are running at 16-bit (65536 colors). The WinNT machine is running at 1024x768 resolution and the laptop is running at 800x600 resolution.

    My *guess* is that it's a palette problem, but I'm not sure.

    --Dave

    -------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Dave Navarro
    started a topic Capture Desktop image and Print to Printer

    Capture Desktop image and Print to Printer

    The following code will work in both PB/DLL and PB/CC:
    Code:
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMDLG32.INC"
     
    FUNCTION PbMain() AS LONG
     
      LOCAL pd     AS PRINTDLGAPI
      LOCAL di     AS DOCINFO
      LOCAL dn     AS ASCIIZ * 64
     
      LOCAL hWnd   AS LONG
      LOCAL hDC    AS LONG
      LOCAL hBmp   AS LONG
      LOCAL hBmpDC AS LONG
      LOCAL r      AS RECT
     
      LOCAL x      AS LONG
      LOCAL y      AS LONG
     
      pd.lStructSize = SIZEOF(pd)
      pd.Flags       = %PD_NOSELECTION OR %PD_NOPAGENUMS OR %PD_USEDEVMODECOPIES OR %PD_RETURNDC
      pd.hWndOwner   = %HWND_DESKTOP
      IF ISFALSE PrintDlg(pd) THEN
        EXIT FUNCTION
      END IF
     
      hWnd     = GetDeskTopWindow
      GetWindowRect hWnd, r
      hDC      = GetDC(hWnd)
      hBmpDC   = CreateCompatibleDC(pd.hDC)
      hBmp     = CreateCompatibleBitmap(pd.hDC, r.nRight, r.nBottom)
      SelectObject hBmpDC, hBmp
      BitBlt hBmpDC, 0, 0, r.nRight, r.nBottom, hDC, 0, 0, %SRCCOPY
     
      dn = "Printer Test"
      di.cbSize = SIZEOF(di)
      di.lpszDocName = VARPTR(dn)
     
      IF StartDoc(pd.hDC, di) > 0 THEN
        IF StartPage(pd.hDC) <= 0 THEN
          EXIT FUNCTION
        END IF
     
        ' scale the bitmap to the width of the page
        x = GetDeviceCaps(pd.hDC, %HORZRES)
        y = CLNG((x / r.nRight) * r.nBottom)
        SelectObject pd.hDC, hBmp
        StretchBlt pd.hDC, 0, 0, x, y, hBmpDC, 0, 0, r.nRight, r.nBottom, %SRCCOPY
     
        IF EndPage(pd.hDC) <= 0 THEN
          EXIT FUNCTION
        END IF
        EndDoc pd.hDC
      END IF
     
      DeleteDC hDC
      DeleteDC hBmpDC
      DeleteDC pd.hDC
     
    END FUNCTION

    -------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
Working...
X