Announcement

Collapse
No announcement yet.

hBmp & Printer

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

  • hBmp & Printer

    Hi, guys --
    Easy question, but ...
    There is pd As PRINTDLGAPI, received by PrintDlg(pd), and "free" true-colour hBmp.

    I have troubles with following
    Code:
         Local hBmpDC As Long
         hBmpDC = CreateCompatibleDC(pd.hDC)
         SelectObject hBmpDC, hMemBmp
         BitBlt pd.hDC, 0, 0, _
             rcfConsole.nRight - rcfConsole.nLeft, rcfConsole.nBottom - rcfConsole.nTop, _
             hBmpDC, 0, 0, %SRCCOPY
    Return values are correct, and even a printer is color.
    Print job appears, but without my picture.

    At the same time
    Code:
          Local pdHDC As Long
          pDhDC = GetWindowDC(GetDesktopWindow)
          hBmpDC = CreateCompatibleDC(pdhDC)
          SelectObject hBmpDC, hMemBmp
          BitBlt pdhDC, 0, 0, _
             rcfConsole.nRight - rcfConsole.nLeft, rcfConsole.nBottom - rcfConsole.nTop, _
             hBmpDC, 0, 0, %SRCCOPY)
          ReleaseDC GetDesktopWindow, pdHdc
    works fine on the screen.

    What am I doing wrong ?

    ------------------
    E-MAIL: [email protected]

  • #2
    BitBlt does not always work with printers unless the bitmap is monochrome. Sometimes it will work, sometimes not.
    You have to use a DIB to print reliably to windows printers. This brings up some issues of palettes, etc and gets a little complicated.
    If you search the code area for DIB you'll probably find some code.

    Best Regards,
    Don

    ------------------
    Don Dickinson
    www.greatwebdivide.com

    Comment


    • #3
      Don --
      I want to avoid direct copying from screen hDC to printer hDC (BTW, which works fine on my PC).

      I read a recommendation to do following -
      1) Create printer-compatible memory DC (hPrDC).
      2) Create printer-compatible hPrBmp.
      3) Select hPrBmp into hPrDC (clear), copy "screen" bitmap into hPrBmp (???) and then copy that bitmap to the printer DC.

      I can't understand p.3.
      Really I have no screen hBmp, I build it from window hDC.
      Code:
           ' Prepare screen bitmap (hMemBmp)
            bmi.bmiHeader.biSize = SizeOf(bmi.bmiHeader)
            bmi.bmiHeader.biWidth = (rcfConsole.nRight - rcfConsole.nLeft)
            bmi.bmiHeader.biHeight = (rcfConsole.nBottom - rcfConsole.nTop)
            bmi.bmiHeader.biPlanes = 1
            bmi.bmiHeader.biBitCount =   24
            bmi.bmiHeader.biCompression = %BI_RGB
            hMemDC = CreateCompatibleDC (hConsoleDC)
            hMemBmp = CreateDIBSection(hMemDC, bmi, %DIB_RGB_COLORS, 0, 0, 0)
      hConsoleDC is hDC of screen window.
      After filling hMemDC and some additional actions, I have "free" hBmp and is able to select it into another screen compatible hDC.

      Now I try to follow p.3 of recommendations (but w/o sample).

      How to understand (to translate to API) -
      1) copy bitmap, which you want to Print, (hMemBmp) into hPrBmp (???) and
      2) then copy that bitmap to the printer DC.


      [This message has been edited by Semen Matusovski (edited November 01, 2000).]

      Comment


      • #4
        Just a silly idea, but.. have you tried using StretchBlt instead
        of BitBlt? A tip: there's a sample under "Printing a Document" in
        win32.api.hlp that shows how print a string of text and a bitmapped
        image, by using StretchBlt. Could be useful to look at..


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

        Comment


        • #5
          Borje --
          Thanks, but alone, which I saw
          If (!StretchBlt(pd.hDC, ... errhandler("StretchBlt Failed", hwnd)

          I have no troubles on my PC, when I copy screen hDC to printer hDC.
          But theoretically users can have.

          I'm interesting, what to do if GetDeviceCaps (RC_BITBLT and RC_STRETCHBLT) shows that such operations ARE NOT AVAILABLE.

          What gues do you think about following way (I can't imitate situation)
          1) To create 24-bits DIB section, compatible with printer DC.
          To select it into Printer DC.
          2) Instead of BitBlt (stretchBlt), to copy all "pixels" directly from DIB-section, compatible with screen.
          Does this solve a problem or not ?

          [This message has been edited by Semen Matusovski (edited November 01, 2000).]

          Comment


          • #6
            Hm, if you have the bitmap created that way, maybe you can try
            StretchDIBits() instead? I once had to do this in a print preview
            function in an earlier version of my software, because StretchBlt
            failed to work properly with some grafik cards and printers.
            StretchDIBits turned out to be a little bit slower but seemed to
            work better. At least I got fewer support calls after I started
            using it instead..


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

            Comment


            • #7
              The bottom line is that you can't rely on bitblt or stretchblt to copy a bitmap to a printer. By definition, these work on device dependent bitmaps. They might work, but there is no guarantee.
              You have to use some sort of DIB operation (like StretchDIBits as suggested by Borje). Before doing this, you must create a dib. It looks like you might be going in the right direction with CreateDIBSection - that's one way to get a dib from a bitmap. I'm not familiar with the details of this approach, though.

              Best Regards,
              Don

              ------------------
              Don Dickinson
              www.greatwebdivide.com

              Comment


              • #8
                Guys --
                What I currently do ... (note PB/CC; console should be in window)
                Code:
                   #Compile Exe
                   #Register None
                   #Dim All
                   #Include "Win32Api.Inc"
                   #Include "ComDlg32.Inc"
                
                   $FileBmp = "C:\WinNt\WinNt.bmp" ' <---------- CHANGE
                
                   Global hWndConsole As Long, hConsoleDC As Long, rcfConsole As RECT
                
                
                   Function GetDefaultPrinterDC As Long
                
                      Dim PrinterName As Asciiz * %MAX_PATH
                
                      GetProfileString "WINDOWS", "DEVICE", ",,,", PrinterName, SizeOf(PrinterName)
                      PrinterName = Left$(PrinterName, Instr(PrinterName$, ",") - 1)
                      If PrinterName = "" Then Exit Function
                      Function = CreateDC(ByVal %Null, PrinterName$, ByVal %Null, ByVal %Null)
                
                   End Function
                
                   Sub GetConsoleDCRC
                      Dim pt As POINTAPI
                
                      hConsoleDC = GetWindowDC(hWndConsole)
                      GetWindowRect hWndConsole, rcfConsole
                      ClientToScreen hWndConsole, pt
                      pt.x = pt.x - rcfConsole.nLeft
                      pt.y = pt.y - rcfConsole.nTop
                      GetClientRect hWndConsole, rcfConsole
                      rcfConsole.nLeft   = rcfConsole.nLeft + pt.x
                      rcfConsole.nRight  = rcfConsole.nRight + pt.x
                      rcfConsole.nTop    = rcfConsole.nTop + pt.y
                      rcfConsole.nBottom = rcfConsole.nBottom + pt.y
                
                   End Sub
                
                   Function PrintConsoleWindow As Long
                
                      GetConsoleDCRC
                      Local hMemDC As Long, hMemBmp As Long, hMemBmpOld As Long, bmi As BITMAPINFO, bm As BITMAP
                
                      ' Prepare screen bitmap (hMemBmp)
                      bmi.bmiHeader.biSize = SizeOf(bmi.bmiHeader)
                      bmi.bmiHeader.biWidth = (rcfConsole.nRight - rcfConsole.nLeft)
                      bmi.bmiHeader.biHeight = (rcfConsole.nBottom - rcfConsole.nTop)
                      bmi.bmiHeader.biPlanes = 1
                      bmi.bmiHeader.biBitCount =   24
                      bmi.bmiHeader.biCompression = %BI_RGB
                      hMemDC = CreateCompatibleDC (hConsoleDC)
                      hMemBmp = CreateDIBSection(hMemDC, bmi, %DIB_RGB_COLORS, 0, 0, 0)
                      GlobalLock hMemBmp
                      hMemBmpOld = SelectObject (hMemDC, hMemBmp)
                      GetObject hMemBmp, SizeOf(bm), bm
                      BitBlt hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hConsoleDC, rcfConsole.nLeft, rcfConsole.nTop, %SRCCOPY
                      SelectObject hMemDC, hMemBmpOld
                      DeleteDC hMemDC
                
                      '----------
                      Local hPrDC   As Long
                      Local di     As DOCINFO
                      Local dn     As Asciiz * 64
                
                      hPrDC = GetDefaultPrinterDC
                
                      If hPrDC Then
                         Local hBmpDC As Long
                
                         Local x      As Long
                         Local y      As Long
                
                         x = GetDeviceCaps(hPrDC, %HORZRES)
                         y = CLng((x / (rcfConsole.nRight - rcfConsole.nLeft)) * (rcfConsole.nBottom - rcfConsole.nTop))
                
                         dn = "Ltr"
                         di.cbSize = SizeOf(di)
                         di.lpszDocName = VarPtr(dn)
                
                         ' scale the bitmap to the width of the page
                         hBmpDC   = CreateCompatibleDC(hPrDC)
                         SelectObject hBmpDC, hMemBmp
                
                         If StartDoc(hPrDC, di) > 0 Then
                            If StartPage(hPrDC) > 0 Then
                               StretchBlt hPrDC, 0, 0, x, y, hBmpDC, 0, 0, rcfConsole.nRight - rcfConsole.nLeft, _
                                 rcfConsole.nBottom - rcfConsole.nTop, %SRCCOPY
                               EndPage hPrDC
                            End If
                            EndDoc hPrDC
                         End If
                
                         DeleteDC hPrDC
                         DeleteDC hBmpDC
                
                      End If
                
                      DeleteObject hMemBmp
                      ReleaseDc hWndConsole, hConsoleDC
                
                    End Function
                
                
                   Function PbMain
                
                      hWndConsole = GetForegroundWindow
                
                      GetConsoleDCRC
                
                      Local hBmp As Long, hBmpDC As Long
                      hBmp = LoadImage(ByVal %NULL, $FileBmp, %IMAGE_BITMAP, _
                         rcfConsole.nRight - rcfConsole.nLeft, rcfConsole.nBottom - rcfConsole.nTop, %LR_LOADFROMFILE)
                      hBmpDC = CreateCompatibleDC(hConsoleDC)
                      SelectObject hBmpDC, hBmp
                      BitBlt hConsoleDC, rcfConsole.nLeft, rcfConsole.nTop, _
                         rcfConsole.nRight - rcfConsole.nLeft, rcfConsole.nBottom - rcfConsole.nTop, _
                         hBmpDC, 0, 0, %SRCCOPY
                      DeleteDC hBmpDC
                      ReleaseDc hWndConsole, hConsoleDC
                
                      Local i As Long
                      For i = 1 To 10
                         Locate 2 + i, 10: Print "      Line       " + Format$(i, "00") + "             "
                      Next
                
                      PrintConsoleWindow
                
                   End Function
                This works on my PC under 2000 and 98, color and black/white printing.
                But something confuses me.
                I decided that to build true color DIB section for printer DC is too expensive (too many dots).
                Alone, what I do - I select DIB section into printer-compatible DC.

                Guys, somebody have problems with this code (under any OS, with network printers and so on) ?



                ------------------
                E-MAIL: [email protected]

                Comment


                • #9
                  Semen, a couple of comments on the CreateDIBSection function.
                  I am far from an expert on Windows bitmaps, but ....

                  1. I'm not sure your dibsection is getting any bits. The documentation
                  suggests that you need to set a long variable by ref in the lplpvoid field. This
                  will contain the bitmap data of the dibsection. Then, you use a
                  stretchblt command passing the data pointer.

                  2. The declaration in the win32api file uses byval lplpvoid as long. This
                  will not work since only the temporary copy of the variable will be initialized.
                  Apparently this function creates its own memory block to contain the bit data.
                  So,you need to retrieve the pointer value from the function. BTW, this is not PB's
                  problem, apparently Microsoft orginally declared the function this way.

                  Jeff


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

                  Comment


                  • #10
                    Jeffrey,
                    The win32api declaration is correct. Semen used an indirect method to
                    get the bitmap bits. The direct method is to call CreateDIBSection as follows-
                    Code:
                      LOCAL     pbBits        AS BYTE PTR
                    
                      ' Create the destination bitmap(a 24 bpp top down dib)
                      ' ----------------------------------------------------
                      hDCDest    = CreateCompatibleDC(hDC)
                      ' Calculate bytes per scan line
                      cblPerLine = ((cxPaint * 3 + 3) \ 4) * 4
                      cblImage   = cblPerLine * cyPaint
                      tbmi.bmiHeader.biSize         = SIZEOF(tbmi.bmiHeader)
                      tbmi.bmiHeader.biWidth        = cxPaint
                      tbmi.bmiHeader.biHeight       = -cyPaint
                      tbmi.bmiHeader.biPlanes       = 1
                      tbmi.bmiHeader.biBitCount     = 24
                      tbmi.bmiHeader.biCompression  = %BI_RGB
                      tbmi.bmiHeader.biSizeImage    = cblImage
                      tbmi.bmiHeader.biClrUsed      = 0
                      tbmi.bmiHeader.biClrImportant = 0
                      hDIB = CreateDIBSection(hDCDest, tbmi, %DIB_RGB_COLORS, VARPTR(pbBits), %NULL, 0)
                    ------------------
                    Dominic Mitchell

                    [This message has been edited by Dominic Mitchell (edited November 01, 2000).]
                    Dominic Mitchell
                    Phoenix Visual Designer
                    http://www.phnxthunder.com

                    Comment

                    Working...
                    X