The correct method for drawing a bitmap image into a window

364 views Asked by At

I have a function which takes a rectangular region of a bitmap image, rescales it to different dimensions, and draws it at some offset inside of a window within my dialog-box application:

void DrawImage(HANDLE hImageBitmap,
               CDC* pDstDC,const CRect& dstRect,
               CDC* pSrcDC,const CRect& srcRect)
{
    pSrcDC->SelectObject(hImageBitmap);
    pDstDC->SetStretchBltMode(HALFTONE);
    pDstDC->StretchBlt
    (
        dstRect.left,dstRect.top,dstRect.Width(),dstRect.Height(),pSrcDC,
        srcRect.left,srcRect.top,srcRect.Width(),srcRect.Height(),SRCCOPY
    );
}

I create and maintain the window using a CWnd m_cImageWindow member variable.

I perform the drawing from the dialog-box's OnPaint handler as follows:

CDC* pDC = m_cImageWindow.GetDC();
CDC  cDC;
cDC.CreateCompatibleDC(pDC);

CRect srcRect = ...;
CRect dstRect = ...;
DrawImage(m_hImageBitmap,pDC,dstRect,&cDC,srcRect);

cDC.DeleteDC();
m_cImageWindow.ReleaseDC(pDC);

I have two problems:

  1. I see flickering whenever I change the drawing parameters. The standard way to solve this, from what I have read here and there, is by using a temporary DC for double-buffering. But as far as I understand, this is exactly what I am already doing.

  2. If some of the destination region falls outside the window, it is painted over other controls within the dialog box. I am able to partially solve this by calling MoveWindow or SetWindowPos for each one of these controls. But I can still see the image flickering behind them. I have tried calling SetWindowPos in various different ways, hoping in vain that it would dictate a strict Z-order of the controls.

Thank you.

2

There are 2 answers

2
Adrian McCarthy On BEST ANSWER
  1. The painting of the image into the child window should be done in the WM_PAINT handler for that child window, not for the dialog. Your child window may need remember information provided by the parent dialog so that it can paint independently. By painting the window from the dialog's WM_PAINT handler, you're possibly painting more often than necessary (and possibly aren't causing a validation to occur in the image window).

  2. The dialog should probably have the WS_CLIPCHILDREN window style and your image window should probably have WS_CLIPSIBLINGS. This will prevent the dialog controls from drawing over each other, and it can reduce flicker by allowing for more minimal updates.

  3. If the image will always completely cover the entire image window, then you want to make sure there's no background erasing happening for the image window, as that can cause a flash of the background color which looks like painting. There are several ways to do this, but the easiest is probably to provide a WM_ERASEBKGND handler that just returns TRUE.

0
thomiel On

I found OnEraseBkgnd to be the right place to minimize flickering of drawn bitmaps.