How to fix Blinking Panel (Flickering Control) when drawing something?

Asked

Viewed 371 times

1

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 tell by pressing one of the Keys above, the edge of the Panel and even the retângulo blink simultaneously. When it happened in the Form, I gave the following command:

this.DoubleBuffered = true;

Then it would stop blinking, but on the panel it doesn’t have that. What to do?

1 answer

3


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

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 that Voce has in its form and also the amount of virtual memory available for the graphic processing of your computer.

Below a compiled links and a solutions that solves 80% of the cases where Flickering (blinker) happens.

Important links:

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 inside your form builder:
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);
    }
}
  • I can do it with any control?

  • 1

    Yes, because the problem is not the control itself but the loading of the form

  • 1

    Remembering that this code is not silver bullet, it depends a lot on the amount of controls in the form and what each control carries, more solves most of the time.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.