如何在出现闪烁的窗体上设置控件的受保护的DoubleBuffered属性?
这是Dummy解决方案的通用版本。
我们可以使用反射来获取受保护的DoubleBuffered属性,然后可以将其设置为true。
注意:如果用户在终端服务会话(例如,远程桌面)中运行,则应向开发人员缴税,并且不使用双缓冲。如果此人在远程桌面中运行,则此帮助程序方法将不会启用双缓冲。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
//Taxes: Remote Desktop Connection and painting
//http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
if (System.Windows.Forms.SystemInformation.TerminalServerSession)
return;
System.Reflection.PropertyInfo aProp =
typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(c, true, null);
} |
检查这个线程
重复该答案的核心,您可以在窗口上打开WS_EX_COMPOSITED样式标志,以使窗体及其所有控件都得到双缓冲。从XP开始,样式标记可用。它并不能使绘制速度更快,但是整个窗口是在屏幕外缓冲区中绘制的,并且一拳打在屏幕上。使它在用户的眼睛上立即可见,而没有可见的绘画瑕疵。它并非完全没有问题,某些视觉样式渲染器可能会在其上出现故障,尤其是TabControl的标签过多时。 YMMV。
将此代码粘贴到您的表单类中:
1 2 3 4 5 6 7
| protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
} |
这种技术与Winform的双缓冲支持之间的最大区别是Winform的版本一次只能在一个控件上运行。您仍然会看到每个单独的控件绘画本身。看起来也像是闪烁效果,尤其是在未绘制的控件矩形与窗口背景形成鲜明对比的情况下。
1 2 3 4
| System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control)
.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(ListView1, true, null); |
Ian拥有有关在终端服务器上使用此功能的更多信息。
1 2 3 4 5 6 7 8
| public void EnableDoubleBuffering()
{
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
} |
一种方法是扩展要加倍缓冲的特定控件,并在控件的ctor中设置DoubleBuffered属性。
例如:
1 2 3 4
| class Foo : Panel
{
public Foo() { DoubleBuffered = true; }
} |
扩展方法为控件打开或关闭双缓冲
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static class ControlExtentions
{
/// <summary>
/// Turn on or off control double buffering (Dirty hack!)
/// </summary>
/// <param name="control">Control to operate</param>
/// <param name="setting">true to turn on double buffering</param>
public static void MakeDoubleBuffered(this Control control, bool setting)
{
Type controlType = control.GetType();
PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(control, setting, null);
}
} |
用法(例如,如何使DataGridView DoubleBuffered):
1 2 3
| DataGridView _grid = new DataGridView();
// ...
_grid.MakeDoubleBuffered(true); |
nobugz在他的链接中获得了该方法的荣誉,我只是在重新发布。将此替代添加到表单中:
1 2 3 4 5 6 7 8 9
| protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
} |
这对我来说效果最好,在Windows 7上,当我调整控件较重的窗体的尺寸时,会出现大的黑色块。现在,控件将反弹!但是更好。
这导致我在第三方控制下持续两天的悲伤,直到我找到它为止。
1 2 3 4 5 6 7 8 9
| protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
} |
最近,在调整包含其他几个控件的控件的大小/重画时,我遇到了很多漏洞。
我尝试了WS_EX_COMPOSITED和WM_SETREDRAW,但是直到我使用了它,一切都没有起作用:
1 2 3 4
| private void myPanel_SizeChanged(object sender, EventArgs e)
{
Application.DoEvents();
} |
只是想传递下去。
在尝试双缓冲之前,请查看SuspendLayout()/ ResumeLayout()是否解决了您的问题。
vb.net这个很好的解决方案的版本。...:
1 2 3 4 5 6 7
| Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H2000000
Return cp
End Get
End Property |
您也可以将控件继承到自己的类中,并在其中设置属性。如果您倾向于在所有控件上进行很多相同的设置,则此方法也很好。
我发现只需在表单上设置DoubleBuffered设置即可自动设置此处列出的所有属性。