要通过双缓冲区减少闪烁:设置样式与重写CreateParam
本文关键字:样式 设置 重写 CreateParam 闪烁 双缓冲区 | 更新日期: 2023-09-27 18:22:08
有人能解释之间的区别和关系吗
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,在子控件窗口所在的位置留下洞。然后,每个子控件都会得到一条消息来绘制自己,它们会用窗口内容填充洞。当你有很多控件时,这些洞会在一段时间内对用户可见。它们通常是白色的,在黑暗时与背景图像形成强烈对比。或者,如果窗体设置了"不透明度"(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