How to double buffer .NET controls on a form?

走远了吗. 提交于 2019-11-26 03:16:10

问题


How can I set the protected DoubleBuffered property of the controls on a form that are suffering from flicker?


回答1:


Here's a more generic version of Dummy's solution.

We can use reflection to get at the protected DoubleBuffered property, and then it can be set to true.

Note: You should pay your developer taxes and not use double-buffering if the user is running in a terminal services session (e.g. Remote Desktop) This helper method will not turn on double buffering if the person is running in remote desktop.

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



回答2:


Check this thread

Repeating the core of that answer, you can turn on the WS_EX_COMPOSITED style flag on the window to get both the form and all of its controls double-buffered. The style flag is available since XP. It doesn't make painting faster but the entire window is drawn in an off-screen buffer and blitted to the screen in one whack. Making it look instant to the user's eyes without visible painting artifacts. It is not entirely trouble-free, some visual styles renderers can glitch on it, particularly TabControl when its has too many tabs. YMMV.

Paste this code into your form class:

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

The big difference between this technique and Winform's double-buffering support is that Winform's version only works on one control at at time. You will still see each individual control paint itself. Which can look like a flicker effect as well, particularly if the unpainted control rectangle contrasts badly with the window's background.




回答3:


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 has some more information about using this on a terminal server.




回答4:


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



回答5:


One way is to extend the specific control you want to double buffer and set the DoubleBuffered property inside the control's ctor.

For instance:

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



回答6:


nobugz gets the credit for the method in his link, I'm just reposting. Add this override to the Form:

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

This worked best for me, on Windows 7 I was getting large black blocks appearing when I resize a control heavy form. The control now bounce instead! But it's better.




回答7:


Extension method to turn double buffering on or off for controls

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

Usage (for example how to make DataGridView DoubleBuffered):

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



回答8:


Before you try double buffering, see if SuspendLayout()/ResumeLayout() solve your problem.




回答9:


This caused me a lot of grief for two days with a third party control until I tracked it down.

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

I recently had a lot of holes (droppings) when re-sizing / redrawing a control containing several other controls.

I tried WS_EX_COMPOSITED and WM_SETREDRAW but nothing worked until I used this:

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

Just wanted to pass it on.




回答10:


vb.net version of this fine solution....:

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



回答11:


You can also inherit the controls into your own classes, and set the property in there. This method is also nice if you tend to be doing a lot of set up that is the same on all of the controls.




回答12:


I have found that simply setting the DoubleBuffered setting on the form automatically sets all the properties listed here.



来源:https://stackoverflow.com/questions/76993/how-to-double-buffer-net-controls-on-a-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!