Unable to implement DIB printing with GDI (MFC)
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13

Thread: Unable to implement DIB printing with GDI (MFC)

Threaded View

  1. #1
    Join Date
    Jan 2012
    Posts
    7

    Exclamation Unable to implement DIB printing with GDI (MFC)

    MFC doc/view architecture, GDI drawing/printing. I have a DIB backbuffer I need to display and print.

    After the long and painful road I came to the conclusion than I need to use DIB created with CreateDIBSection (rather than DDB created with CreateCompatibleBitmap), and I have to blit it onto printer dc with StretchDIBits (rather than StretchBlt).

    But i'm not able to get this thing to work.

    Here is what I do:

    In my initialization routine, I setup the backbuffer, like this:

    PHP Code:
        // Prepare device context:

        
    CClientDC aDC(this);
        
    OnPrepareDC(&aDC);

        
    // Setup proper backbuffer:

        
    _pMemDc = new CDC;
        
    _pMemDc->CreateCompatibleDC(&aDC);

        
    memset(&_bitmapInfo0sizeof(BITMAPINFO));

        
    _bitmapInfo.bmiHeader.biSize sizeof(BITMAPINFOHEADER);
        
    _bitmapInfo.bmiHeader.biWidth _sizeBackBuffer.cx;
        
    _bitmapInfo.bmiHeader.biHeight = -_sizeBackBuffer.cy// top-down
        
    _bitmapInfo.bmiHeader.biPlanes 1;
        
    _bitmapInfo.bmiHeader.biBitCount 24// Maybe 32?
        
    _bitmapInfo.bmiHeader.biCompression BI_RGB;

        
    HANDLE hMemBitmap CreateDIBSection(aDC.GetSafeHdc(), &_bitmapInfoDIB_RGB_COLORS, (void**)&_pBitmapRawBits00);

        
    _hOldSelBitmap = (HBITMAP)_pMemDc->SelectObject(hMemBitmap); 
    Variables with underscores are (private) member variables, declared like this:

    PHP Code:
        CDC *_pMemDc// Backbuffer memory dc
        
    HBITMAP _hOldSelBitmap;

        
    BITMAPINFO _bitmapInfo// Backbuffer DIB (header-only)
        
    unsigned char *_pBitmapRawBits// Pointer to pixel data of DIB

        
    SIZE _sizeBackBuffer// Size of backbuffer, i.e. size of that DIB 
    Now below is what I do in my OnDraw override:

    Firstly I get the area to be drawn like this (simplified code):

    PHP Code:
        CRect rectClipBoxPlayground;

        if (
    pDC->IsPrinting())
        {
            
    rectClipBoxPlayground _printingParams.pPrintInfo->m_rectDraw;
        }
        else
        {
            
    pDC->GetClipBox(&rectClipBoxPlayground);
        } 
    Then I calculate the corresponding rect coordinates in my backbuffer, which is usually (much) larger than the DC. Details of this calculation are irrelevant here, I just say that

    CRect rectClipBoxBackBuffer;

    represents the corresponding rect of backbuffer (in pixel coordinates of backbuffer).

    Then I draw onto my backbuffer, using the _pMemDc memory dc.

    And finally comes the part where I have troubles: blitting my DIB onto target dc (screen or printer). Here is what I do:

    PHP Code:
        // Copy back buffer to screen/printer dc:

        
    pDC->SetStretchBltMode(HALFTONE);
        
    SetBrushOrgEx(pDC->GetSafeHdc(), 000);

        
    // BELOW COMMENTED CODE OF StretchBlt WORKS(!) INSTEAD OF StretchDIBits.
        //
        //BOOL bSuccess = pDC->StretchBlt(rectClipBoxPlayground.left, rectClipBoxPlayground.top, 
        //    rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(), 
        //    _pMemDc, rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top, 
        //    rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), SRCCOPY);

        
    HBITMAP hMemBitmap = (HBITMAP)_pMemDc->SelectObject(_hOldSelBitmap);

        
    DWORD dwLines StretchDIBits(pDC->GetSafeHdc(), 
            
    rectClipBoxPlayground.leftrectClipBoxPlayground.toprectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(), 
            
    rectClipBoxBackBuffer.leftrectClipBoxBackBuffer.toprectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), 
            
    _pBitmapRawBits, &_bitmapInfoDIB_RGB_COLORSSRCCOPY);

        
    _pMemDc->SelectObject(hMemBitmap); 
    The problem is, the commented-out code of StretchBlt works flawlessly (except printing on some printers), but I can't use it because some printers have troubles with it. So I have to use StretchDIBits. Note that I firstly unselect the DIB from its memory dc temporarily, so that it is not associated with any dc. Then I use StretchDIBits but things just don't work! Output is messed up, like I give incorrect coordinates, areas are drawn off-set from where they should be drawn, and sometimes totally black. So I must be missing something (maybe something very trivial). Help! I tried changing signs of rectClipBoxBackBuffer.top and bitmapInfo.bmiHeader.biHeight, the results change, but nothing works like it should.

    What am I doing wrong??
    Last edited by TX_; January 28th, 2012 at 02:15 PM. Reason: Formatting

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center