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

时间:2008-09-16 20:57:43

标签: c# winforms flicker doublebuffered

如何在遭受闪烁的表单上设置控件的受保护DoubleBuffered属性?

13 个答案:

答案 0 :(得分:85)

这是Dummy's solution的更通用版本。

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

注意:您应该pay your developer taxes而不是use double-buffering if the user is running in a terminal services session(例如远程桌面)如果此人在远程桌面上运行,则此辅助方法不会启用双缓冲。< / p>

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); 
}

答案 1 :(得分:65)

检查this thread

重复该答案的核心,您可以打开窗口上的WS_EX_COMPOSITED样式标志,以使表单及其所有控件双重缓冲。样式标志自XP起可用。它不会使绘画更快,但是整个窗口都是在屏幕外缓冲区中绘制的,并且在一次打击中对屏幕进行了打开。使用户的眼睛立即看起来没有可见的绘画工件。它并非完全没有问题,一些视觉样式渲染器可能会出现问题,特别是当TabControl有太多标签时。 YMMV。

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

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

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

答案 2 :(得分:18)

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提供了有关在终端服务器上使用此功能的更多信息。

答案 3 :(得分:12)

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

答案 4 :(得分:8)

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

例如:

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

答案 5 :(得分:5)

nobugz在他的链接中获得了该方法的功劳,我只是重新发布。将此覆盖添加到表单:

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

这对我来说效果最好,在Windows 7上,当我调整控件重型表单时,我出现了大的黑色块。控制现在反弹!但它更好。

答案 6 :(得分:5)

扩展方法可为控件打开或关闭双缓冲

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

答案 7 :(得分:4)

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

答案 8 :(得分:4)

这导致我在第三方控制的情况下连续两天悲伤很多,直到我追踪它为止。

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

在重新调整/重新绘制包含其他几个控件的控件时,我最近有很多漏洞(粪便)。

我尝试了WS_EX_COMPOSITED和WM_SETREDRAW,但在我使用它之前没有任何效果:

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

只是想传递它。

答案 9 :(得分:2)

这个精美解决方案的vb.net版本....:

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

答案 10 :(得分:1)

您还可以将控件继承到自己的类中,并在其中设置属性。如果您倾向于在所有控件上进行大量设置,那么此方法也很不错。

答案 11 :(得分:0)

我发现只需在表单上设置DoubleBuffered设置就会自动设置此处列出的所有属性。

答案 12 :(得分:-1)

FWIW

建立在我之前的人的工作基础上:
Dummy's SolutionIan Boyd's SolutionAmo's Solution

这是一个使用反射在 PowerShell 中通过 concat 设置双缓冲的版本

SetStyle