通过双缓冲区减少闪烁:SetStyle 与覆盖 CreateParam
Posted
技术标签:
【中文标题】通过双缓冲区减少闪烁:SetStyle 与覆盖 CreateParam【英文标题】:To reduce flicker by double buffer: SetStyle vs. overriding CreateParam 【发布时间】:2014-11-10 10:38:58 【问题描述】:谁能解释一下两者的区别和关系
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;
它们是减少闪烁所必需的,但何时以及如何正确使用它们?可以单独使用,还是必须成对使用,这是什么原因?
谢谢!
学分:
第一个代码sn-p引用自MSDN page;第二个代码sn-p在How to fix the flickering in User controls上找到,原作者是@HansPassant。
【问题讨论】:
first - ControlStyles.AllPaintingInWmPaint 应该与 ControlStyles.UserPaint 一起使用,已经说过带有这些选项的 setstyle 相当于 this.DoubleBuffered = true;。现在不同的是 setstyle 应用于控件级别(例如:带有控件的表单,这将仅应用于表单),而 CreateParams 将应用于表单中的所有控件,包括表单。 csharptutorial.in/15/csharp-how-to-avoid-flickering-in-csharp - 从我从这个链接得到的关于范围的信息。 【参考方案1】:感谢@terrybozzlo 的解释和@Caramiriel 澄清问题的精彩页面。
我想总结一下我在这里得到的一切。
为什么会出现闪烁
当您的表单或容器控件(例如 Panel
)包含太多控件时(以及默认情况下打开 WS_CLIPCHILDREN
时),通常会发生闪烁。根据@HansPassant:
它绘制 BackgroundImage,在子控件窗口所在的位置留下孔。然后每个子控件都会收到一条消息来绘制自己,他们将用他们的窗口内容填充这个洞。当你有很多控件时,这些漏洞对用户来说是可见的一段时间。它们通常是白色的,与背景图像在黑暗时形成鲜明对比。或者,如果表单设置了 Opacity 或 TransparencyKey 属性,它们可能是黑色的,与几乎任何东西形成鲜明对比。
如何在控制级别避免它们
您应该将控件的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
在控件层做工作,CreateParam
在表单层做工作,实现表单内所有控件的双缓冲。
学分:
@terrybozzlo、@Caramiriel、@HansPassant
【讨论】:
...在子控制窗口所在的位置留下孔。不会。当您设置 WS_CLIPCHILDREN 时会发生这种情况,否则它会绘制到包括子控件在内的整个区域。 SETSTYLE 不会消除闪烁,也不能仅用于整个表单的特定控件。 CreateParams 在开始时有效,但是当您调整大小时,您会失去该属性并且控件再次开始闪烁。你知道解决这个问题的方法吗? 正如@TannerOrnelas 所说,当您调整表单大小时,控件再次开始闪烁。有没有人有办法解决吗?我已经尝试了很多事情,比如这篇文章***.com/questions/3286373/… 中的事情,但我无法得到真正的解决方案。我非常感谢任何帮助。 @Ignacio 正如这个答案所述,您需要创建自己的从 Panel 派生的类,或者只是创建一个用户控件。 Panel 控件按原样没有 DoubleBuffer 选项,因此使用CreateParams
方法将不起作用,因为面板不会继承 DoubleBuffered 属性。在您的派生类或 UserControl 构造函数中,添加以下 SetStyle(ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
在此面板上绘制。
谢谢!创建一个 UserControl 并在构造函数中使用 SetStyle
对我有用。在我的新 UserControl 上绘制形状时不再闪烁。以上是关于通过双缓冲区减少闪烁:SetStyle 与覆盖 CreateParam的主要内容,如果未能解决你的问题,请参考以下文章