Flicker is a annoying problem in GUI programming, whether you’re using MFC or Win32 SDK or other GUI library like wxWidgets.
The aim of this article is not to present you how to prevent your Windows program from flickering, just show a little trick that will help you avoid flickering on parent window created without WS_CLIPCHILDREN.
By default, main window will be created with WS_CLIPCHILDREN mask, that prevents child controls on the parent window from being painted twice. As we know, flickering comes from drawing a pixel twice, so WS_CLIPCHILDREN will greatly reduce flickering.
But, WS_CLIPCHILDREN will cause another annoying problem, “child control dark block”, if you’ve never heard of it, try to create a windows program with WS_CLIPCHILDREN mask, and place 3-5 Edit and Static Text controls on main window, compile and run it, then minimize and restore it repeatedly. You’ll probably see on-screen “child control dark block” on these child controls.
Finally I found a way to avoid flickering without WS_CLIPCHILDREN. The key is ExcludeClipRect function.
Assuming that you have a main window created without WS_CLIPCHILDREN mask, and four Static controls on it, Static A is for owner drawing, the other three are for static text display. Normally, there’ll be flicker on Static A when you moving the window out of the screen. Now what we need to do is add WM_ERASEBKGND handler in main window message loop.
{
dc = (HDC)wParam;
GetWindowRect(hStatic, &rc);
pt1.x = rc.left;
pt1.y = rc.top;
pt2.x = rc.right;
pt2.y = rc.bottom;
ScreenToClient(hDlg, &pt1);
ScreenToClient(hDlg, &pt2);
ExcludeClipRect(dc, pt1.x, pt1.y, pt2.x, pt2.y);
}
the code above will exclude Static A from repaint area, so you can process Static A owner drawing in custom code (we’re subclassing Static A).
{
PAINTSTRUCT ps;
HDC dc;
RECT rc;
HBRUSH br;
switch (message)
{
case WM_PAINT:
GetClientRect(hwnd, &rc);
dc = BeginPaint(hwnd, &ps);
br = CreateSolidBrush(color);
FillRect(dc, &rc, br);
DeleteObject(br);
EndPaint(hwnd, &ps);
return 0;
case WM_ERASEBKGND:
return 1;
default:
return CallWindowProc(lpOldProc, hwnd, message, wParam, lParam);
}
return 0;
}
Now, even not using double-buffing, we can get smooth owner drawn Static without flickering. But it’s still a median way, the best solution is building gui controls from scratch, and create main window with WS_CLIPCHILDREN, child controls will have their own message procedure and owner drawing code. A good example of how to create custom control is SpinCube control from the latest Windows SDK.

Leave a Reply