25

I have a panel that has a roulette wheel on it, and I need to double buffer the panel, so that it stops flickering. Can anyone help me out?

EDIT:

Yes, I have tried that.

panel1.doublebuffered does not exist, only this.doublebuffered. And I don't need to buffer the Form, just the Panel.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • 1
    Panel *does* have a DoubleBuffered property (JP linked to the doc for it). Note that the property is protected, which is why you can't get to it. Make a subclass of Panel, and set it in the constructor. – Andy May 04 '09 at 00:57
  • 1
    Perhaps this is a non-issue for others, but setting the value in `InitializeComponent` causes the designer to crash; as mentioned by @Andy, do it in the constructor. – Dan Lugg Feb 01 '12 at 01:19

6 Answers6

27

Another way of doing this is to invoke the member doublebuffered, using the InvokeMember method:

 typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty    
            | BindingFlags.Instance | BindingFlags.NonPublic, null,
            panel2, new object[] { true }); 

By doing it this way, you don't have to create a subclass

Jakob Danielsson
  • 767
  • 1
  • 8
  • 16
  • 3
    This is a good solution. Just precise that you have to put it after the InitializeComponent(); in the constructor of your view. – Alekos Dec 16 '19 at 13:03
  • Is setting protected properties via reflection ugly? Yes. Is sub-classing a control you want to use in the GUI designer even uglier? Also yes. – Lily Finley Apr 24 '20 at 02:02
  • This is perfect - especially in situations where you used a normal panel and can't afford switching it out – zapshe Mar 22 '23 at 21:09
26

You need to derive from Panel or PictureBox.

There are ramifications to this depending on how you choose to enable the buffering.

If you set the this.DoubleBuffer flag then you should be ok.

If you manually update the styles then you have to paint the form yourself in WM_PAINT.

If you really feel ambitious you can maintain and draw your own back buffer as a Bitmap.


using System.Windows.Forms;

public class MyDisplay : Panel
{
    public MyDisplay()
    {
        this.DoubleBuffered = true;

        // or

        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        UpdateStyles();
    }
}
user79755
  • 2,623
  • 5
  • 30
  • 36
5

You can make the DoubleBuffered-Property public in a derivided class of Panel:

public class DoubleBufferedPanel : Panel
{        
    [DefaultValue(true)]
    public new bool DoubleBuffered
    {
        get
        {
            return base.DoubleBuffered;
        }
        set
        {
            base.DoubleBuffered = value;
        }
    }
}
Koopakiller
  • 2,838
  • 3
  • 32
  • 47
  • 9
    Since there's no point in using this class except *with* double buffering on, I'd make it even simpler: `class DoubleBufferedPanel: Panel { public DoubleBufferedPanel(): base() { DoubleBuffered = true; } }`. –  Nov 27 '13 at 23:23
  • 1
    Very simple, indeed. After adding this one-liner to my project, all I had to do, was go to the Designer and change the Datatype of the panel in question at two places and all is well now.. Very cool! – TaW Mar 20 '14 at 21:59
4

Winform panels have a DoubleBuffered property.

Edit: I should have noticed that it was protected. Others have described how to sub-class it. :)

JP Alioto
  • 44,864
  • 6
  • 88
  • 112
1

Just expanding on User79775's answer, if you're trying to achieve this in VB.net, do so like this:

Imports System.Windows.Forms

Public Class MyDisplay
    Inherits Panel

    Public Sub New()
        Me.DoubleBuffered = True

        ' or

        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        UpdateStyles()
    End Sub
End Class
Jyclop
  • 469
  • 1
  • 6
  • 15
0

I was in the exact same predicament as you. I put a Panel inside of a C# WinForm and used it as a display zone for a geometric animation. Multiple redraw operations triggered by a timer, combined with the occasional window resizing, all caused that Panel to flicker terribly. The other solutions offered here all seem to rely on activating the DoubleBuffered flag, but this never made any difference in my experience.

The proper way to go about it is to use the System.Drawing.BufferedGraphics class and harness it in your application.

Here's an overview of it, and an example that actually works (no more flickering!).

That example is a bit overkill since it highlights at least two ways to perform the rendering before flipping the graphic buffers; you only need to keep the one you prefer in your implementation.

I personally chose to subclass the Panel into a new DoubleBufferedPanel class. I simply use the base Panel's Paint() method combined with a call to Refresh() to flip the buffers.