How do I enable double-buffering of a control using C# (Windows forms)?
In the constructor of your control, set the DoubleBuffered property, and/or ControlStyle appropriately.
For example, I have a simple DoubleBufferedPanel whose constructor is the following:
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.ContainerControl |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.SupportsTransparentBackColor
, true);
Winforms Double Buffering
This only has an effect on the form itself, not the child controls. If you have a lot of them then the time they need to take turns painting themselves becomes noticeable, it leaves a rectangular hole where the control goes that doesn't get filled up until the child control gets it turn.
What you'd need to combat this is double-buffering the entire form and the controls. That's an option available since Windows XP which made the WS_EX_COMPOSITED style flag available. Paste this into your form to turn it on:
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
It doesn't speed up the painting at all, but the form snaps onto the screen after a delay. Eliminating the visible paint artifacts. Really fixing the delay requires not using controls. Which you'd do by using the OnPaint method to draw the 'controls' and making the OnMouseClick event smart about what 'control' got clicked by the user.
How to double buffer .NET controls on a form?
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);
}
Double buffering with Panel
I should have posted my solution a long time ago...
Well, here is my solution:
Bitmap buffer = new Bitmap(screenWidth, screenHeight);//set the size of the image
System.Drawing.Graphics gfx = Graphics.FromImage(buffer);//set the graphics to draw on the image
drawStuffWithGraphicsObject(gfx);//draw
pictureBox1.Image = buffer;//set the PictureBox's image to be the buffer
Makes me feel like a complete idiot for finding this solution years after asking this question.
I have tried this with a Panel, but it has proven to be slower when applying the new image. Somewhere I had read, that it is better to use Panel instead of PictureBox. I don't know if I have to add something to the code to speed things up for the Panel, though.
Winforms Graphics flickering. (Double buffering doesn't help!)
Short answer - keep DoubleBuffered = true
and use Paint
event.
When I tried to use a PaintEvent for my graphics functionality, nothing happened
When you do some modifications and want to reflect them, use Control.Invalidate method, which according to the documentation
Invalidates the entire surface of the control and causes the control to be redrawn.
In your case, something like this
void timer_Tick(object sender, EventArgs e)
{
Tick();
Invalidate();
}
WinForms Flickering after Maximizing - Double Buffering
Had to remove any sort of double buffering / createparams etc. from the master form, and put it exclusively into the child forms....
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
frmChild()
{
ResizeRedraw = true;
this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
}
Despite double buffering, the ticker still flickers
Turning Hans Passant's comment into an answer so that I can accept it:
This effect is not called flicker, it is called tearing. You see part
of the old bitmap and part of the new bitmap. Which becomes very
noticeable on moving objects, they appear jittery. Not fixable in
Winforms, google "vertical blanking interval". – Hans Passant
C#, double buffer in WinForms?
As Neil noted, you don't need to (and shouldn't) create a new Graphics object in each iteration of the loop. These are relatively expensive resources and should not be created willy nilly.
Also, you shouldn't be painting like that inside of a button Click handler by calling CreateGraphics. It can lead to problems, most notably your drawing being "undone" when the paint handler is invoked (i.e., every time the window is receives a WM_PAINT message and is refreshed). You should do all of your painting by overriding OnPaint and simply call Invalidate() when you need to update your form.
As for the flickering, setting DoubleBuffered to true will usually take care of it, but rolling your own double buffering is trivial. Give it a try. Also realize that drawing in a loop like that probably isn't what you want to do. Use a timer if you want to update once per some interval. Your code is being executed as fast as the loop can execute, which is not usually desirable.
private void someTimer_Tick( ... )
{
Invalidate();
}
protected override void OnPaint( PaintEventArgs e )
{
using( var tempBmp = new Bitmap( ... ) )
using( var g = Graphics.FromImage( tempBmp ) )
{
// draw to tempBmp
e.Graphics.DrawImage( tempBmp, new Point( 0, 0 ) );
}
}
Related Topics
Setting the Default Json Serializer in ASP.NET MVC
How to Evaluate a C# Expression Dynamically
Dpi Awareness - Unaware in One Release, System Aware in the Other
How to Perform a Left Outer Join Using Linq Extension Methods
How to Prevent And/Or Handle a Stackoverflowexception
What Is App.Config in C#.Net - How to Use It
How to Read Appsettings Values from a .Json File in ASP.NET Core
How to Get Formatted Json in .Net Using C#
Find Control by Name from Windows Forms Controls
Can You Overload Controller Methods in ASP.NET MVC
Visual Studio Publish Project into One Simple Installer
Check If a Class Is Derived from a Generic Class
Associate File Extension With Application
How to Load a .Net Assembly At Runtime and Instantiate a Type Knowing Only the Name