如何在Windows对话框中处理WM_ERASEBKGND时避免闪烁

我有一个resize的对话框。 它也有一个自定义的背景,我为响应WM_ERASEBKGND调用而绘制(当前是对FillSolidRect的简单调用)。

当对话框resize时,会出现巨大的闪烁。 为了尝试减less闪烁,我枚举所有的子窗口,并将其添加到剪辑区域。 这似乎有一点帮助 – 现在,闪烁现象在所有的儿童控制中都是显而易见的,因为它们被重新绘制。

如何在resize的同时使对话框无闪烁? 我怀疑双缓冲必须发挥一部分,但我不知道如何做到这一点与儿童控制的对话(没有使所有的孩子控制所有者绘制或类似的东西)。

我应该注意到,我正在使用C ++(不是.NET)和MFC,但是欢迎使用纯粹的基于Win32的解决scheme:)

注:有一件事我尝试了,但没有奏效(不知道为什么)是:

CDC memDC; memDC.CreateCompatibleDC(pDC); memDC.FillSolidRect(rect, backgroundColor); pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY); 

假设“FillSolidRect”是擦除你的背景,那么从WM_ERASEBKGND返回TRUE。

为了在代码片段中完成双缓冲,您需要使用CreateCompatibleBitmap并将其选入您的memDC中。

尝试添加以下行到您的OnInitDialog函数:

  ModifyStyle(0, WS_CLIPCHILDREN, 0); 

在WM_ERASEBKGND处理中不做任何事情,并将其作为主WM_PAINT的一部分进行擦除。 您可以更加智能地绘制,以便仅重绘无效区域,或者更简单地双重缓冲绘图。

通过在擦除背景中不做任何事情,您可以将所有绘图代码放在一个位置,这样可以让其他人更容易跟踪和维护。

如果您的目标是WinXP或更高版本,则也可以使用WS_EX_COMPOSITED样式为默认的顶级窗口启用双缓冲。 请记住,这有它自己的限制 – 具体地说,不再使用GetDC绘制OnPaint循环,等等。

您可以将调用的参数设置为InvalidateRect方法为false。 这将防止您在窗口重绘时发送WM_ERASEBKGND。 这是一个很好的链接,以防止窗口闪烁。

双缓冲确实是使这项工作的唯一方法。

只要你确定CLIPCHILDREN孩子的控制就会自己照顾自己。