在这种情况下如何使用双缓冲?

Posted

技术标签:

【中文标题】在这种情况下如何使用双缓冲?【英文标题】:How to use double buffer in this case? 【发布时间】:2009-09-27 11:04:28 【问题描述】:

假设我有三个控件A,B,C。它们都继承自CDialog, A 是一个主对话框,A 包含 B,B 包含 C。 而且每次我用鼠标拖动C,B和C都会一起移动。

这是一张图片:http://img507.imageshack.us/img507/7039/31709956.jpg

我们知道这会导致 B 和 C 重新绘制自己。并且可能会导致闪烁。

我的问题是是否有一种方法可以对这两个对话框 B 和 C 进行双重缓冲?

我知道在 XP 和 vista 中,有一个属性 WS_EX_COMPOSITED 会有所帮助,但我不想使用它。

可能有人建议我使用 memDC,但我的问题是如何将 B 的 ondraw 和 C 的 ondraw 函数中的动作合并到缓冲区中?

希望有人知道我说了什么。

提前致谢!

【问题讨论】:

当您说:对话框...您的意思是它们是单独的窗口吗? (所以 CDialog?) 是的,所有的对话框都继承自CDialog~ 【参考方案1】:

对闪烁有很大帮助的是重载erasebackground 方法。此方法用纯色填充整个背景。油漆比油漆上面的所有物品。通过删除erasebackground,绘画只会在已经存在的东西上绘画,从而消除闪烁。

【讨论】:

但我的问题是如何将 B 的 ondraw 和 C 的 ondraw 函数中的动作合并到缓冲区中?假设当我拖动C时,B和C将被重绘,顺序是B先绘制然后C,它是在它们自己的ondraw函数中完成的,我想将它们双重缓冲成位图,然后将其绘制在上面A. 但我不知道该怎么做。 我无法想象能够使用 1 个屏幕外位图重绘 2 个单独的窗口。为此,您需要对话框不是单独的窗口。 嗨...我刚看到你的测试图片。对话框真的完全由您绘制吗(所以没有控件?)在这种情况下,为什么要完全使用 CDialog 而不是自己直接在主窗口上绘制它们,从而消除所有闪烁 因为我将在子对话框 C 上添加一些事件处理程序,例如拖放 WS_EX_COMPOSITED ,该属性可以将它的所有子元素缓冲到缓冲区中,然后绘制它。但我不想用这个....【参考方案2】:

CS_PARENTDC 会有所帮助。

【讨论】:

【参考方案3】:

我自己从来没有搞过双缓冲 Windows 的绘图调用,但我曾经在 Microsoft 论坛上遇到过关于它的讨论:http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/789a4116-d3b2-488e-801a-3f7bc1e4d33a/ 也许这可能对你有帮助。

【讨论】:

【参考方案4】:

假设 B 和 C 是 A 的子级(对话框的常见情况),A 应该具有 WS_CLIPCHILDREN 样式集。如果 B 和 C 是 A 的兄弟姐妹,则设置 A 的 WS_CLIPSIBLINGS 位。

【讨论】:

【参考方案5】:

主对话框 A 使用一个 MemDC,B 和 C 使用组合 MemDC。 现在当你拖动 C 时,你应该根据当前位置组合这 2 个 MemDC 通过使用 BitBlt 函数,最后你必须在对话框的实际 DC 上执行组合 memDC 的 bitblt。

除此之外,您还必须覆盖 onerasebackground 方法,因此不会出现闪烁。

【讨论】:

以上是关于在这种情况下如何使用双缓冲?的主要内容,如果未能解决你的问题,请参考以下文章

Android中View如何刷新

利用双缓冲队列来减少锁的竞争

双缓冲(Double Buffer)原理和使用

双缓冲(Double Buffer)原理和使用

重温一下读写双缓冲问题

试图将文本函数插入QUERY - 如何在这种情况下转义字符串?