How to prevent flicker in WinForms
By FoxLearn 12/27/2024 3:22:26 AM 23
This flickering happens because the control is being repainted multiple times during updates, which can lead to an undesirable visual effect.
For example, consider the scenario where you have a ListBox
that displays the list of active processes and updates a process’s status every second. If you run this code, you'll likely observe a flicker as the control updates.
private void Form1_Load(object sender, EventArgs e) { string[] processes = { "Process1", "Process2", "Process3", "Process4", "Process5" }; listBox1.BeginUpdate(); foreach (var process in processes) { listBox1.Items.Add(process); } listBox1.EndUpdate(); Timer timer1 = new Timer(); timer1.Interval = 1000; timer1.Tick += (s, ea) => { listBox1.BeginUpdate(); for (int i = 0; i < listBox1.Items.Count; i++) { listBox1.Items[i] = $"{listBox1.Items[i]} - Status: {DateTime.Now.Second}"; } listBox1.EndUpdate(); }; timer1.Enabled = true; }
In this case, each time the timer ticks, the ListBox
's content is being updated, which can cause flicker because the control is redrawn multiple times.
Double buffering works by drawing content to an off-screen buffer first and then displaying it all at once, which minimizes flickering. However, while the Form
class has a DoubleBuffered
property that can be set to true, this only applies to the form itself and not its child controls. For child controls, the DoubleBuffered
property is protected within the Control
class, so it requires a workaround to access it.
Accessing the DoubleBuffered Property
To enable double buffering on controls like ListBox
, you have two options: subclassing the control or using reflection. While subclassing works, a simpler solution is to use reflection to access the protected DoubleBuffered
property.
Here’s an extension method that enables double buffering for any control:
public static class Extensions { public static void SetDoubleBuffered(this Control control, bool enabled) { var prop = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); prop.SetValue(control, enabled, null); } }
Using the Extension Method
After defining the extension method, you can call it to enable double buffering for any control. For example, in the Form1_Load
method, you would use:
listBox1.SetDoubleBuffered(true);
This will eliminate the flickering in the ListBox
as its content updates.