views:

47

answers:

2

I added this to my form's constructor code:

this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);

But it still shows ugly artifacts when it loads the controls, whenever they change (the form is a calendar, it changes often).

What do I need to do differently?

+2  A: 

You could play a bit with LockWindowUpdate

    [System.Runtime.InteropServices.DllImport("User32")]
    private static extern bool LockWindowUpdate(long hWnd);

    public static void LockWindowUpdate(Control c) {
        if (c.IsHandleCreated) {
            LockWindowUpdate(c.Handle.ToInt64());
        }
    }
    public static void UnLockWindowUpdate(Control c) {
        if (c.IsHandleCreated) {
            LockWindowUpdate(0);
        }
    }

Using LockWindowUpdate you can prevent partial screens to show in Windows.

The DoubleBuffering helps when you do a lot of painting (yourself) in the Paint event (or OnPaint) of the control you enable Double buffering for.

But when building/refreshing the controls on the screen, outside of the Paint event, if have found LockWindowUpdate preventing a lot of flickering.

GvS
This has made it a little better but there's still some nasty artifacts. Thank you, though.
Motig
+2  A: 

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.

Hans Passant
Brilliant, thank you!
Motig