Earth
Earth

Reputation: 3571

How to prevent flickering when using paint method in c# winforms?

Code:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawRectangle(Pens.White,
    e.ClipRectangle.Left,
    e.ClipRectangle.Top,
    e.ClipRectangle.Width - 1,
    e.ClipRectangle.Height - 1);
    base.OnPaint(e);
}

How to avoid flickering. Above is the panel1_Paint method for Paint event in Panel. Thanks.

Upvotes: 1

Views: 3077

Answers (3)

Lemonseed
Lemonseed

Reputation: 1732

There are a few ways to prevent flickering for container controls, such as the panel control. Each of these methods involves deriving from the Panel base class (or other suitable base class).

The first method is enabling double buffering, which can be accomplished using the following line of code:

this.DoubleBuffered = true;

The second effective method is overriding the CreateParams property and enabling WS_EX_COMPOSITED. This is done using the following code:

private const int WS_EX_COMPOSITED = 0x02000000;

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

In order to access either of these properties, as we have determined we need to derive from the base class. Therefore the entire class declaration might look something like this:

public class GraphicsPanel : Panel
{
    private const int WS_EX_COMPOSITED = 0x02000000;

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

    public GraphicsPanel()
    {
        this.DoubleBuffered = true;
    }
}

Upon rebuilding our solution, a new control will be added to the toolbox called GraphicsPanel, which we can visually design. At run-time, you should notice substantially less flickering.

Upvotes: 0

Stratege
Stratege

Reputation: 151

The problem is most likely caused by not having double buffering enabled. Double buffering is the process of first writing to an internal (invisible) buffer until all draw operations are completed and then blitting said buffer to the visible buffer, this avoids flickering by simplifying the draw operation on the actual buffer.

http://msdn.microsoft.com/en-us/library/3t7htc9c(v=vs.110).aspx lists possible solutions to it. Setting the property DoubleBuffered to true appears to be the easiest way to do such. However, since it is protected you either need to use reflection to access it or inherit from the panel class, set it to true in your new class and use said new class:

public class myPanel : Panel {
    public myPanel() : base() {
        this.DoubleBuffered = true;
    }
}

Upvotes: 1

Dirk
Dirk

Reputation: 10958

Some of the Windows Forms controls don't have double buffering enabled by default. I'm not sure if the panel is one of them, but it can't hurt to try enabling it.

Unfortunately Control.DoubleBuffered is a protected, so unless you inherit from the control you have to resort to reflection to enable it.

Control ctrl;
ctrl.GetType()
    .GetProperty("DoubleBuffered", 
                 BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(control, true, null);

Upvotes: 3

Related Questions