如何在表单上双缓冲.NET控件?

我怎样才能设置DoubleBuffered闪烁的窗体上的控件的受保护的DoubleBuffered属性?

这是一个更通用的Dummy解决scheme 。

我们可以使用reflection来获得受保护的DoubleBuffered属性,然后可以将其设置为true

注意 : 如果用户在terminal服务会话中运行 (例如,远程桌面),您应该支付开发人员的税款,而不要使用双缓冲。如果此人在远程桌面上运行,则此辅助方法不会启用双缓冲。

 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时,它有太多的标签。 因人而异。

将此代码粘贴到您的表单类中:

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

这种技术与Winform的双缓冲支持的最大区别在于Winform的版本只能在一个控件上工作。 你仍然会看到每个单独的控制油漆本身。 这也可以看起来像一个闪烁的效果,特别是如果未上漆的控制矩形与窗口的背景形成鲜明对比的话。

 System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control) .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); aProp.SetValue(ListView1, true, null); 

伊恩有更多关于在terminal服务器上使用它的信息。

 public void EnableDoubleBuffering() { this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); this.UpdateStyles(); } 

一种方法是扩展你想要双缓冲区的特定控件,并在控件的ctor中设置DoubleBuffered属性。

例如:

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

nobugz在他的链接获得方法的功劳,我只是重新发布。 将此重写添加到窗体:

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

这对我来说是最好的,在Windows 7上,当我调整控件大小的窗体时,出现了大块的黑色块。 控制现在反弹! 但是更好。

在尝试双缓冲之前,请参阅SuspendLayout()/ ResumeLayout()是否解决您的问题。

扩展方法打开或closures控件的双缓冲

 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):

 DataGridView _grid = new DataGridView(); // ... _grid.MakeDoubleBuffered(true); 

这让我有了两天的第三方控制的悲痛,直到我追查下来。

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

我最近有很多漏洞(粪便)时,重新resize/重绘包含其他控件的控件。

我试过WS_EX_COMPOSITED和WM_SETREDRAW,但没有任何工作,直到我用这个:

 private void myPanel_SizeChanged(object sender, EventArgs e) { Application.DoEvents(); } 

只是想传递它。

您也可以将控件inheritance到您自己的类中,并在其中设置属性。 这个方法也很好,如果你在所有的控件上都做了很多的设置。

我发现只需在窗体上设置DoubleBuffered设置就可以自动设置这里列出的所有属性。

然而; 我发现winforms提供的双缓冲不是很好。 这个代码片段的小gem 确实有所作为,认真地尝试它。 我花了很长时间寻找一个解决scheme,最终发现:-)

vb.net版本这个好解决scheme….:

 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