C# paint program flickering

99封情书 提交于 2020-01-12 08:28:57

问题


I'm trying to make a simple paint program in C#, but it keeps flickering when I'm drawing, like I need some kind of double buffering, but I don't know how to do it.

I am drawing on a Panel and I'm using a Bitmap to store the graphics.

Here's my code:

public partial class Form1 : Form
{
    private Bitmap drawing;
    private bool leftDown = false;
    private int prevX;
    private int prevY;
    private int currentX;
    private int currentY;

    public Form1()
    {
        InitializeComponent();

        drawing = new Bitmap(panel1.Width, panel1.Height);
    }

    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            leftDown = true;

            prevX = e.X;
            prevY = e.Y;
        }
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (leftDown)
        {
            Graphics g = Graphics.FromImage(drawing);

            currentX = e.X;
            currentY = e.Y;

            g.DrawLine(new Pen(Color.Black), new Point(currentX, currentY), new Point(prevX, prevY));
            panel1.Invalidate();

            prevX = currentX;
            prevY = currentY;

            g.Dispose();
        }
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        leftDown = false;
    }

    private void panel1_MouseLeave(object sender, EventArgs e)
    {
        leftDown = false;
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImageUnscaled(drawing, 0, 0);
    }
}

回答1:


You not only should turn DoubleBuffered to true, but also use PictureBox instead of Panel and draw on it. This should solve your issue :).




回答2:


You need to subclass Panel to do this, because you need to override certain things. A Panel like this should work:

class DoubleBufferedPanel : Panel {
    public DoubleBufferedPanel() : base() {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.DoubleBuffered |
                      ControlStyles.Opaque |
                      ControlStyles.OptimizedDoubleBuffer, true);
    }
    public override void OnPaint(PaintEventArgs e) {
        // Do your painting *here* instead, and don't call the base method.
    }

    // Override OnMouseMove, etc. here as well.
}

However, you don't need the functionality Panel adds to Control at all, that is for it to be functioning as a container. So, in fact, you should be inheriting from Control unless you need subcontrols.

Another improvement might be to only Invalidate with the Rectangle that changed. This will repaint one area and reduce drawing time. You can also pass a srcRect to Graphics.DrawImage, that srcRect being calculated from e.ClipRectangle, for even better performance if subclassing Panel doesn't work for you.




回答3:


When painting pixel maps in the Paint event, the flickering is often caused by Windows forms because it first draws the background and then the pixel map. So the flicker is the background that becomes visible for a fraction of a second.

You can set the Opaque style in the panel's ControlStyle property. That will turn of the background drawing because Windows Forms now assumes that your code will completely draw the contents of the panel.




回答4:


Normally, simply adding this.DoubleBuffered = true; in your code should do the trick.

If it does not, add this code to your form :

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

You can also change it using Reflection, but there is no advantage, neither readability or speed.



来源:https://stackoverflow.com/questions/8369163/c-sharp-paint-program-flickering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!