22

I have an app that has a ton of controls on it. And it has a massive amount of flicker, particularly on startup.

I applied this fix to it.

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

This worked great - the flickering was reduced by a pretty unbelievable amount. However, the side effect is that the Minimize, Maximize and the Close buttons in the top right of the window don't animate when I move the mouse over or click on them (they still work though). This gives the app a hung feel.

How do I keep the WS_EX_COMPOSITED while still retaining the usability of Maximize, Minimize and Close buttons?

This happens on Windows XP. As @fallenidol pointed out, this is not an issue on Windows 7.

Community
  • 1
  • 1
AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • 6
    Perfect question (I want this functionality, I've tried this resolution, how do I achieve this functionality with this new constraint). – Matt Mitchell Jul 20 '10 at 01:34
  • BTW, I tried this fix in a test app running on Windows 7 and the Maximise, Minimise and Close buttons still seem to animate. – pmcilreavy Jul 21 '10 at 07:21
  • @fallenidol. That's good to know. All my clients are on XP. – AngryHacker Jul 21 '10 at 16:37
  • 1
    I know this is an old post, but when WS_EX_COMPOSITED is enabled on Win 7 SP1 the animation on Maximize, Minimize and Close buttons disappeared. – Ignacio Mar 27 '19 at 23:28

5 Answers5

14

I figured it out. The trick is to remove the WS_EX_COMPOSITED flag after the form is shown. The full explanation and code at my blog:

How to get rid of flicker on Windows Forms applications

AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • @Hossein yeah, the blog is down for now...hopefully will restore at some point this month. – AngryHacker Aug 07 '16 at 19:02
  • 3
    @Hossein Meanwhile, get it here: https://web.archive.org/web/20160405111506/http://www.angryhacker.com/blog/archive/2010/07/21/how-to-get-rid-of-flicker-on-windows-forms-applications.aspx – AngryHacker Aug 07 '16 at 19:03
  • Hi @AngryHacker! I tried what you suggested and have problems in Win 10 with flickering in and MDI form. In Win 7 the animation on the minimize, restore and close button still don´t work. Could you please give me any clues on this? Thank you in advanced! – Ignacio Mar 28 '19 at 23:21
8

I know this question is a little old, but better late than never. I used your original example you linked to come up with one that toggles it on when resizing, then toggles it back off to draw everything else perfectly. Hopefully it helps others searching for a solution to this problem. As the OP knows, DoubleBuffering alone properties don't solve flickering issues.

Here's a work-around to stop flickering when a user resizes a form, but without messing up the drawing of controls such as DataGridView, NumericUpDown, etc. 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
  • Good point. I've had this code in my app, but neglected to add it to my blog entry. Will update it in a couple of days. – AngryHacker Jun 29 '11 at 16:45
  • Nice, but if I apply this solution, then when the form is resized, the flickering comes back again. If I just use CreateParams as in the question, the flickering goes away even when the form is resized. Perhaps, I´m missing something... – Ignacio Mar 27 '19 at 23:34
4

Try the following code. This should go in the main form and any other custom user controls you have.

        // Enable double duffering to stop flickering.
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.SupportsTransparentBackColor, false);
        this.SetStyle(ControlStyles.Opaque, false);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.ResizeRedraw, true);
pmcilreavy
  • 3,076
  • 2
  • 28
  • 37
  • The whole point of the code I posted is that you do this once, not for every single user control (which there are hundreds + a ton of 3rd party controls). – AngryHacker Jul 20 '10 at 15:53
  • 3
    This is another option for other people seeing this page who might not have access to the whole app and are just developing a user control in isolation. Next time you are developing a single user control you can use my code snippet above. Then you might not end up in a situation where you have hundreds of flickering controls. – pmcilreavy Jul 21 '10 at 07:18
0

I just came across this post and realize it is a little old. However, I am having the same issue with my form and discovered (for XP, anyway) an inelegant solution seems to be not enabling visual styles.

Tebc
  • 121
  • 7
  • As a follow up, I seem to have no issue with flicker when I override OnPaintBackground. If I don't want the background painted, I call e.Graphics.Clear([appropriate color]) and return, otherwise the base event method is called. As I said, this "seems" to alleviate the issue. However, I am wondering what unforeseen repercussions may arise. – Tebc Dec 10 '12 at 15:01
  • Correction. The aforementioned override seems to work as long as the form's minimum size property is set to the current size. – Tebc Dec 10 '12 at 15:11
0

Your should try standard windows forms control property called DoubleBuffered. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

Kru
  • 149
  • 2
  • That only works on a per-control basis. The example I provided forces double-buffering onto every control on the form. – AngryHacker Jul 20 '10 at 07:43
  • You can use reflection at the start of the app to fill this property of every control. – Kru Jul 20 '10 at 07:51
  • I can't do it for the 3rd party controls that don't expose this property. – AngryHacker Jul 21 '10 at 16:32
  • Hmmm, any third party control has to be inherited from Windows.Forms.Control. Even if this property is closed, you can use reflection to access any private or protected property as well. – Kru Jul 22 '10 at 07:55