Can anybody explain the difference and relationship between
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer, true)
and
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
They are required to reduce flickers, but when and how to use them correctly? Can they be used individually, or must be used in pairs, and what's the reason for that?
Thanks!
Credits:
The first code snippet was cited from MSDN page; the second code snippet was found on How to fix the flickering in User controls, the original author is @HansPassant.
Thanks to @terrybozzlo for explanation and @Caramiriel for the great page that clarifies the problem.
I would like to summarize all I got here.
Flickers usually occur when your form, or a container control, such as a Panel
, contains too many controls (and when WS_CLIPCHILDREN
is turned on, which is the case by default). According to @HansPassant:
It draws the BackgroundImage, leaving holes where the child control windows go. Each child control then gets a message to paint itself, they'll fill in the hole with their window content. When you have a lot of controls, those holes are visible to the user for a while. They are normally white, contrasting badly with the BackgroundImage when it is dark. Or they can be black if the form has its Opacity or TransparencyKey property set, contrasting badly with just about anything.
You should set the Control's DoubleBuffered
property to true
. To do this, you need to derive the control (if it's not a user control) from the basic type and set it in the constructor.
For example, to get a Panel
double buffered, you need to do:
public class BufferedPanel : Panel
{
public BufferedPanel()
{
DoubleBuffered = true;
}
}
Alternatively, you can use:
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer, true);
to obtain the identical effect, i.e. they are equivalent.
The above technique will reduce the flicker on control level, which means when the form get redrawn, all controls won't flicker any more. But the ultimate solution is to reduce flicker from the form level: when the form get redrawn, the form and all its children are double buffered.
This requires overriding CreateParams
:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
SetStyle
does the job on control level, and CreateParam
on Form level, and achieves double buffer to all control inside the form.
@terrybozzlo, @Caramiriel, @HansPassant
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With