How to fix Panel flashing (Flickering control) when drawing something?

I made an example when this happens pisca-pisca, just put the control Panel in the form and execute.

    public Form1()
    {
        InitializeComponent();
        this.KeyDown += Form1_KeyDown;
        this.KeyPress += Form1_KeyPress;
        this.panel1.Paint += panel1_Paint;
        rectangle = new Rectangle()
        {
            Width = 20,
            Height = 20,
        };
    }

    Rectangle rectangle;
    Keys keys;

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        keys = e.KeyCode;
    }

    private void Form1_KeyPress(object sender, KeyPressEventArgs e)
    {
        this.panel1.Invalidate();
        switch (keys)
        {
            case Keys.D:
                {
                    rectangle.X += 10;
                }
                break;
            case Keys.A:
                {
                    rectangle.X -= 10;
                }
                break;
            case Keys.W:
                {
                    rectangle.Y -= 10;
                }
                break;
            case Keys.S:
                {
                    rectangle.Y += 10;
                }
                break;
            default:
                break;
        }
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.FillRectangle(new SolidBrush(Color.Red), rectangle);
        e.Graphics.DrawRectangle(new Pen(Color.Blue, 10), this.panel1.ClientRectangle);
    }

You can notice that when you press one of the Keys above, the edge of the Panel and even the retângulo itself flashes simultaneously. When this happened in Form, I would give the following command:

this.DoubleBuffered = true;

Then stopped flashing, but in the panel does not have that. What to do?

Author: Julio Borges, 2019-02-22

1 answers

This is an old problem of Windows Forms applications, what happens is that the graphical processing of the screen can not properly load the update of the screen, because the action taken is faster than the loading of the screen itself.

There are a number of Microsoft articles and solutions that promise to solve the problem, plus each case is a case, because it depends a lot on the amount of graphics you have in your form and also the amount of virtual memory available for the graphic processing of your computer.

Below is a compilation of links and a solution that solves 80% of the cases where Flickering happens.

Links important:

Https://social.msdn.microsoft.com/Forums/windows/en-US/15d8a45c-f2c3-49a6-9312-11ead7b05662/how-to-remove-flickering-from-windows-form-in-c?forum=winforms

Https://stackoverflow.com/questions/8046560/how-to-stop-flickering-c-sharp-winforms

Https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-reduce-graphics-flicker-with-double-buffering-for-forms-and-controls

My solution:

  • Configure your form with the DoubleBuffered option;
  • put the code below in the inside of your form constructor:
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
  • include this code snippet in your Form:
protected override CreateParams CreateParams
{
    get
    {
        CreateParams handleParam = base.CreateParams;
        handleParam.ExStyle |= 0x02000000;
        return handleParam
     }
}

So your code would look like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        this.KeyDown += Form1_KeyDown;
        this.KeyPress += Form1_KeyPress;
        this.panel1.Paint += panel1_Paint;
        rectangle = new Rectangle()
        {
            Width = 20,
            Height = 20,
        };

        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams handleParam = base.CreateParams;
            handleParam.ExStyle |= 0x02000000;     
            return handleParam;
        }
    }

    Rectangle rectangle;
    Keys keys;

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        keys = e.KeyCode;
    }

    private void Form1_KeyPress(object sender, KeyPressEventArgs e)
    {
        this.panel1.Invalidate();
        switch (keys)
        {
            case Keys.D:
                rectangle.X += 10;
                break;
            case Keys.A:
                rectangle.X -= 10;
                break;
            case Keys.W:
                rectangle.Y -= 10;
                break;
            case Keys.S:
                rectangle.Y += 10;
                break;
            default:
                break;
        }
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.FillRectangle(new SolidBrush(Color.Red), rectangle);
        e.Graphics.DrawRectangle(new Pen(Color.Blue, 10), this.panel1.ClientRectangle);
    }
}
 3
Author: Julio Borges, 2019-02-22 17:15:26