为啥 DoubleBuffered 默认禁用?
Posted
技术标签:
【中文标题】为啥 DoubleBuffered 默认禁用?【英文标题】:Why is DoubleBuffered disabled by default?为什么 DoubleBuffered 默认禁用? 【发布时间】:2010-11-27 09:03:14 【问题描述】:创建新表单后,我通常会执行以下仪式:
-
把名字改成有意义的;
输入
Caption
;
更改位置属性(DefaultPosOnly 几乎不是用户期望的);
将ShowHint
设置为true
;
将DoubleBuffered
设置为true
;
我一直想知道为什么默认值为“False”。对我来说,它只是看起来技术含量低而且很糟糕,而且在我的新机器上我没有注意到任何性能差异。
双缓冲在旧机器、VNC、远程桌面或虚拟机上是否存在问题?
你是开着还是关着?有什么建议吗?
【问题讨论】:
【参考方案1】:在执行某种远程桌面时应避免双缓冲,因为必须通过网络发送控件/表单的整个位图才能执行 BitBlt。见this blog post...
【讨论】:
+1 太棒了。您指出的那一刻是如此明显,但我从未想过会是这种情况。这会让我重新考虑我的一些程序....感谢您指出这一点!【参考方案2】:您还可以创建一个设计时专家,自动为您创建的每个表单/控件设置此值,而不是为每个现有的控件派生新控件,这会涉及更多工作。 请参阅 GExperts.org 上的源代码,了解如何实现这一点。
【讨论】:
【参考方案3】:您可能知道,双缓冲区通常涉及创建与可视组件大小相同的屏幕外内存缓冲区。在此缓冲区上执行写入/绘图,完成后,整个缓冲区被“交换”,以便现在将其绘制在可视组件上。
(注意:“交换”可能包括简单地更改指针指向的地址,或者实际上可能涉及复制一块内存,例如使用 BitBlt、memcpy 等)
因此,为启用该进程的每个组件分配了合理数量的内存来支持该进程。如果您的应用程序有许多窗口或和/或组件,则分配的内存量将不小。如果您不需要平滑的视觉更新/滚动,为什么要浪费这些内存?
当然,还有一种说法是,今天大多数计算机都有足够的内存可用,所以何必担心。但是,如果您不需要它,我仍然不认为这是默认启用双缓冲的理由。
如果手动将 DoubleBuffered 设置为 true 对您来说很痛苦,您始终可以创建自己的自定义控件/组件,该控件/组件继承自内置控件,并将 DoubleBuffered(和其他属性)设置为所需的默认值。
【讨论】:
+1 不错的答案。 Nitpick:将“快速复制”替换为“交换”或其他不会给人以实际存在缓冲区副本的印象的内容。通常缓冲区交换是简单的指针交换。 好点,我已经更新了答案。当然,在 Windows Forms.NET 中还有一个“假装”双缓冲,实际上只是一个内存副本。 当DoubleBuffered
为真时,控件对绘制消息的响应如下:创建位图,绘制位图,调用BitBlt
将位图复制到窗口,然后销毁位图。这不仅仅是简单的指针交换。
@Tob,我在答案中添加了关于指针交换和内存复制的注释。
@Rob,很抱歉你名字中的类型!【参考方案4】:
在执行桌面合成双缓冲的现代操作系统上,实际上可能会降低性能。无论如何,渲染都是在屏幕外的位图中执行的,因此使用双缓冲会导致额外的复制,而在这些系统上根本没有任何好处。因此,除非 VCL 足够聪明,可以在这种情况下忽略双缓冲(不知道是否这样做,需要检查),否则实际上最好不要无条件设置它。
编辑:
我检查过,在 Delphi 2007 和 Delphi 2009 中,TWinControl.WMPaint
方法在DwmCompositionEnabled
返回True
时不使用双缓冲。不错。
【讨论】:
以上是关于为啥 DoubleBuffered 默认禁用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥默认禁用 TypeScript 中的不安全/非严格编译器规则?
为啥 udev init 脚本默认禁用容器支持,而实际上它可以工作?
强制设置双缓冲DoubleBuffered 解决tableLayoutPanel 闪烁