Reputation: 3571
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
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
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
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