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

10

我有一个可以改变大小的对话框。它还有一个自定义背景,我通过响应WM_ERASEBKGND调用来绘制(目前是一个简单的FillSolidRect调用)。

当对话框被调整大小时,会出现大量闪烁。为了试图减少闪烁,我枚举所有子窗口并将它们添加到剪辑区域中。这似乎有所帮助——现在闪烁主要出现在所有子控件重绘时。

如何使对话框在调整大小时不闪烁?我怀疑双缓冲必须发挥作用,但我不确定如何在具有子控件的对话框中实现双缓冲(而无需使所有子控件进行所有者绘制或类似操作)。

我应该注意到,我正在使用C++(而不是.NET),以及MFC,尽管纯Win32解决方案也是可以的 :)

注意:我尝试过的一件事,但不起作用(不知道为什么),是:

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

pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
6个回答

10
假设 "FillSolidRect" 是擦除背景的操作,那么在 WM_ERASEBKGND 消息中返回 TRUE。
为了实现你代码片段中几乎实现的双缓冲技术,你需要使用 CreateCompatibleBitmap 并将其选择到你的内存设备上下文(memDC)中。

6
尝试在您的OnInitDialog函数中添加以下行:
    ModifyStyle(0, WS_CLIPCHILDREN, 0);

5

如果你的目标是WinXP或更高版本,你也可以使用WS_EX_COMPOSITED样式来启用默认情况下顶级窗口的双缓冲。请注意,这样做有其自己的一套限制 - 具体而言,不能再使用GetDC等方法在OnPaint周期之外进行绘图。


5

在WM_ERASEBKGND处理中不要进行任何操作,而是将擦除作为主要的WM_PAINT的一部分。您可以更加智能地绘制图像,以便只重新绘制无效区域,或者更容易地使用双缓冲区技术进行绘制。

通过不在擦除背景中进行任何操作,您的所有绘制代码都位于一个位置,这应该使其他人更容易跟踪和维护。


4
您可以将InvalidateRect方法的参数设置为false。这样,当窗口重新绘制时,您就可以防止发送WM_ERASEBKGND消息。

您的链接似乎已经损坏。 - Ayxan Haqverdili

3

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

只要您确保CLIPCHILDREN,子控件就会自行处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接