Alex Rivera | Logout

Reduce flicker with GDI+ and C++

Asked 2008-10-13T15:16:16.353
21

I'm using GDI+ in a C++/MFC application and I just can't seem to avoid flickering whenever the window is resized.

I have already tried these steps:

  • returned TRUE on OnEraseBkGnd();
  • returned NULL on OnCtlColor();
  • used double buffering according to this code:

void vwView::OnDraw(CDC* pDC) 
{
   CRect rcClient;
   GetClientRect(rcClient);

   Bitmap bmp(rcClient.Width(), rcClient.Height());
   Graphics graphics(&bmp);

   graphics.DrawImage(m_image, rcClient.left, rcClient.top);

   Graphics grph(pDC->m_hDC);
   grph.DrawImage(&bmp, 0, 0);
}

Am I doing something wrong? Or is there another way to achieve this?

Edit
Report

2 Answers

44

To completely avoid flicker, you would need to complete all drawing in the interval between screen updates. Windows does not provide any easy means of accomplishing this for normal window painting (Vista provides composite drawing via the DWM, but this cannot be relied on even on systems running Vista). Therefore, the best you can do to minimize flicker is to draw everything as quickly as possible (reduce tearing by increasing your chances of completing all drawing within a refresh cycle), and avoid overdraw (drawing part of the screen and then drawing something else over the top: risks presenting user with a partially-drawn screen).

Let's discuss the techniques presented here so far:

  • Do-nothing OnEraseBkgnd(): helps to avoid over-draw by preventing the invalidated area of the window from being filled with the window's background color. Useful when you will be drawing the entire area again during WM_PAINT handling anyway, as in the case of double-buffered drawing... but see Notes on avoiding overdraw by preventing drawing after your WM_PAINT method.

  • Returning NULL for OnCtlColor(): this shouldn't actually do anything... unless you have child controls on your form. In that case, see Notes on avoiding overdraw by preventing drawing after your WM_PAINT method instead.

  • Double buffered drawing: helps to avoid tearing (and potentially overdraw as well), by reducing the actual on-screen drawing to a single BitBLT. May hurt the time needed for drawing though: hardware acceleration cannot be used (although with GDI+, the chances of any hardware-assisted drawing being used are quite slim), an off-screen bitmap must be created and fi

answered 2008-10-14T00:13:16.693
0

Are there child windows on the form? The Window manager starts by getting the parent window to erase its background by sending a WM_ERASEBKGND message, THEN it sends a wM_PAINT message - presumably this maps to your wx::OnDraw method. Then it iterates over each child control and gets those to paint themselves.

If this is your scenario... using Vistas new aero look would solve your problem as the aero desktop window manager does window compositing automatically. With the older window manager its a pita.

answered 2008-10-13T15:58:23.507

Your Answer