如何在 Windows 对话框中处理 WM_ERASEBKGND 时避免闪烁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/164751/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to avoid flicker while handling WM_ERASEBKGND in Windows dialog
提问by DougN
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).
我有一个可以调整大小的对话框。它还有一个自定义背景,我在响应 WM_ERASEBKGND 调用(当前是对 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 :)
我应该注意到我使用的是 C++(不是 .NET)和 MFC,尽管欢迎使用纯基于 Win32 的解决方案:)
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);
采纳答案by David L Morris
Assuming that "FillSolidRect" is the erase of your background then return TRUE from the WM_ERASEBKGND.
假设“FillSolidRect”是您的背景擦除,然后从 WM_ERASEBKGND 返回 TRUE。
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.
要执行您几乎在代码片段中执行的双缓冲,您需要使用 CreateCompatibleBitmap 并将其选择到您的 memDC 中。
回答by Adam Pierce
Try adding the following line to your OnInitDialog function:
尝试将以下行添加到您的 OnInitDialog 函数中:
ModifyStyle(0, WS_CLIPCHILDREN, 0);
回答by Jeff Yates
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.
在 WM_ERASEBKGND 处理中什么都不做,将擦除作为主要 WM_PAINT 的一部分进行。您可以更智能地绘制以便仅重绘无效区域,或者更轻松地对绘图进行双缓冲。
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.
通过在擦除背景中不做任何事情,您将所有绘图代码都放在一个位置,这将使其他人更容易遵循和维护。
回答by adzm
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.
如果您的目标是 WinXP 或更高版本,您还可以使用 WS_EX_COMPOSITED 样式为具有此样式的顶级窗口默认启用双缓冲。请记住,这有其自身的一组限制——特别是,不再使用 GetDC 等绘制 OnPaint 周期。
回答by Imrank
回答by Frank Krueger
Double buffering is indeed the only way to make this work.
双缓冲确实是完成这项工作的唯一方法。
Child controls will take care of themselves so long as you make sure CLIPCHILDREN
.
只要您确定,儿童控件就会照顾好自己CLIPCHILDREN
。