通过双缓冲区减少闪烁:SetStyle与重写CreateParam

任何人都可以解释它们之间的区别和关系

SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true) 

 protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED return cp; } } 

他们需要减少闪烁,但是何时以及如何正确使用它们? 它们可以单独使用,还是必须成对使用,这是什么原因?

谢谢!

积分

第一个代码片段是从MSDN页面引用的; 在如何修复用户控件中的闪烁中找到第二个代码片段,原作者是@HansPassant。

感谢@terrybozzlo的解释和@Caramiriel的精彩页面,澄清了问题。

我想总结一下我来到这里的所有内容。


为什么我们得到了闪烁

当您的表单或容器控件(如Panel )包含太多控件(以及启用WS_CLIPCHILDREN时,默认情况下是这种情况)时,通常会出现闪烁。 据@HansPassant说:

它绘制了BackgroundImage,在子控件窗口的位置留下了空洞。 然后每个子控件都会收到一条消息来绘制自己,他们将用它们的窗口内容填充这个洞。 当您有很多控件时,用户可以看到这些漏洞一段时间。 它们通常是白色的,在黑暗时与BackgroundImage形成鲜明对比。 或者如果表单具有Opacity或TransparencyKey属性设置,它们可能是黑色的,几乎与任何事物形成鲜明对比。

如何在控制级别上避免它们

您应该将Control的DoubleBuffered属性设置为true 。 为此,您需要从基本类型派生控件(如果它不是用户控件)并在构造函数中设置它。

例如,要获得Panel双缓冲,您需要执行以下操作:

 public class BufferedPanel : Panel { public BufferedPanel() { DoubleBuffered = true; } } 

或者,您可以使用:

 SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true); 

获得相同的效果 ,即它们是等价的

如何在表单级别上避免它们

上述技术将减少控制级别的闪烁,这意味着当重新绘制表单时,所有控件都不会闪烁。 但最终的解决方案是减少表单级别的闪烁:当表单重新绘制时,表单及其所有子项都是双缓冲的。

这需要覆盖CreateParams

 protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED return cp; } } 

摘要

SetStyle在控件级别执行作业,在Form级别执行CreateParam ,并为表单内的所有控件实现双缓冲。

积分:

@terrybozzlo,@ Caramiriel,@ HansPassant