Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid flicker while handling WM_ERASEBKGND in Windows dialog

I have a dialog that resizes. It also has a custom background which I paint in response to a WM_ERASEBKGND call (currently a simple call to FillSolidRect).

When the dialog is resized, there is tremendous flickering going on. To try and reduce the flickering I enumerate all child windows and add them to the clipping region. That seems to help a little -- now the flickering is mostly evident in all of the child controls as they repaint.

How can I make the dialog flicker-free while resizing? I suspect double-buffering must play a part, but I'm not sure how to do that with a dialog with child controls (without making all child controls owner-draw or something like that).

I should note that I'm using C++ (not .NET), and MFC, although pure Win32-based solutions are welcomed :)

NOTE: One thing I tried but which didn't work (not sure why) was:

CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.FillSolidRect(rect, backgroundColor);

pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
like image 259
DougN Avatar asked Oct 02 '08 21:10

DougN


5 Answers

Assuming that "FillSolidRect" is the erase of your background then return TRUE from the WM_ERASEBKGND.

To do the double buffering that you are almost doing in your code fragment, you will need to use CreateCompatibleBitmap and select that into your memDC.

like image 53
David L Morris Avatar answered Nov 10 '22 14:11

David L Morris


Try adding the following line to your OnInitDialog function:

    ModifyStyle(0, WS_CLIPCHILDREN, 0);
like image 30
Adam Pierce Avatar answered Nov 10 '22 13:11

Adam Pierce


Do nothing in the WM_ERASEBKGND handling and do the erase as part of your main WM_PAINT. You can either paint smarter so that you only redraw the invalid areas, or more easily, double-buffer the drawing.

By not doing anything in the erase background, you have all your drawing code in one location which should make it easier for others to follow and maintain.

like image 39
Jeff Yates Avatar answered Nov 10 '22 13:11

Jeff Yates


If you are targeting WinXP or higher, you can also use the WS_EX_COMPOSITED style to enable double-buffering by default for top-level windows with this style. Bear in mind this has its own set of limitations -- specifically, no more drawing out of OnPaint cycles using GetDC, etc.

like image 28
adzm Avatar answered Nov 10 '22 14:11

adzm


you can set parameter of your call to InvalidateRect method as false. This will prevent you to send WM_ERASEBKGND when the window will redraw.

like image 4
Imrank Avatar answered Nov 10 '22 12:11

Imrank