9

I have a .net app that I've written in c#. On some forms I frequent update the display fields. In some cases every field on the form (textboxes, labels, picturebox, etc) has its value changed. Plus the frequency of the changes could possibly be every second. However, currently there is a horrible flickering everytime the form is updated. How can I stop the flickering? Is there a way to maybe double buffer? Please help!

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510

10 Answers10

7

the short answer is

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

the long answer is: see MSDN or google

just for fun, try calling Application.DoEvents() after each element is updated, and see if the problem gets better or worse ;-)

Martin Brown
  • 24,692
  • 14
  • 77
  • 122
Steven A. Lowe
  • 60,273
  • 18
  • 132
  • 202
  • I'm not sure that will help. It sounds like the problem is with the standard controls are flickering, and OptimizedDoubleBuffer will only help with custom rendered controls. – Cameron MacFarland Oct 08 '08 at 05:03
6

This worked for me.

http://www.syncfusion.com/faq/windowsforms/search/558.aspx

Basically it involves deriving from the desired control and setting the following styles.

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
SetStyle(ControlStyles.DoubleBuffer, true); 
Brian Hasden
  • 4,050
  • 2
  • 31
  • 37
4

You could try to call this.SuspendLayout(); before you start your update and this.ResumeLayout(false); when you have finished setting all the values in this way it should prevent the form from writing values one at a time.

FryHard
  • 10,305
  • 7
  • 35
  • 38
  • 1
    suspendlayout/resumelayout are for suppressing events related to adding and moving controls – Steven A. Lowe Oct 08 '08 at 05:13
  • 1
    Correct, the events only prevent layout functions from being called multiple times when updating large groups of controls. As such these functions will speed up layout but will not prevent flicker. Using them in conjunction with Double Buffering will yield best results. – Toji Oct 08 '08 at 13:01
4

I know this question is old, but may be it will others searching for it in the future.

DoubleBuffering doesn't always work well. To force the form to never flicker at all (but sometimes causes drawing issues):

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

To stop flickering when a user resizes a form, but without messing up the drawing of controls (provided your form name is "Form1"):

int intOriginalExStyle = -1;
bool bEnableAntiFlicker = true;

public Form1()
{
    ToggleAntiFlicker(false);
    InitializeComponent();
    this.ResizeBegin += new EventHandler(Form1_ResizeBegin);
    this.ResizeEnd += new EventHandler(Form1_ResizeEnd);
}

protected override CreateParams CreateParams
{
    get
    {
        if (intOriginalExStyle == -1)
        {
            intOriginalExStyle = base.CreateParams.ExStyle;
        }
        CreateParams cp = base.CreateParams;

        if (bEnableAntiFlicker)
        {
            cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED
        }
        else
        {
            cp.ExStyle = intOriginalExStyle;
        }

        return cp;
    }
} 

private void Form1_ResizeBegin(object sender, EventArgs e)
{
    ToggleAntiFlicker(true);
}

private void Form1_ResizeEnd(object sender, EventArgs e)
{
    ToggleAntiFlicker(false);
}

private void ToggleAntiFlicker(bool Enable)
{
    bEnableAntiFlicker = Enable;
    //hacky, but works
    this.MaximizeBox = true;
}
John Suit
  • 1,254
  • 12
  • 17
2

You can just replace original control with custom one which has protected DoubleBuffered property to true. E.g. for ListView it would be something like this:

internal class DoubleBufferedListView : ListView {

    public DoubleBufferedListView()
        : base() {
        this.DoubleBuffered = true;
    }

}

After that you just visit *.Designer.cs file and replace all mentions of native control with this one.

P.S. Instead of inheriting from control you can also set this property via reflection:

listView1.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(lsvReport, true, null);

It is not clean nor recommended but it requires no changes in *.Designer.cs files.

Josip Medved
  • 3,631
  • 1
  • 28
  • 36
2

It could also be caused by your coding, not the absence of doublebuffering. I came here just now with a similar problem but realised it's because:

  1. I set a frame to invisible when an item is not selected.
  2. In between user selections, the index is cleared by the ListView control.
  3. I'm bound to the SelectedIndexChanged event

In other words:

  • User clicks item 1
    ~ SelectedIndexChanged(1)
  • User clicks item 2
    ~ SelectedIndexChanged(-1) <---- This causes the flicker
    ~ SelectedIndexChanged(2)

So what's the solution? How to avoid thousands of needless ListView.SelectedIndexChanged events?

Community
  • 1
  • 1
Kind Contributor
  • 17,547
  • 6
  • 53
  • 70
1

You didn't research this well. There is a DoubleBuffered property in every Form. Try setting that to true. If you havn't overloaded anything on the form painting, then everything should work.

Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
1

You can double buffer almost every windows forms control, although most of the time it requires that you inherit from the desired control and override a protected property. Be cautioned, though, that I've spent quite a bit of time on the same issue and I've yet to fully remove flicker on my more complex forms.

If you want truly flicker-free windows, I suggest looking at WPF.

Toji
  • 33,927
  • 22
  • 105
  • 115
0

i had the same problem with OpenGLES, which is how i found this thread. of course i realize u are not using ogl, but maybe this helps u anyway ;)

protected override void OnPaintBackground(PaintEventArgs e) { }

0

The ghosting is usually caused because you're running in a single thread and it's being held up with the field updates so the paint event doesnt fire. One way to fix this would be to put the heavy lifting in asynchronous methods. This will allow the form to repaint itself and update whatever is needed when they async method calls back.

DaveK
  • 4,509
  • 3
  • 33
  • 33