c#画图程序闪烁

本文关键字:闪烁 程序 | 更新日期: 2023-09-27 18:16:29

我正在尝试用c#制作一个简单的绘画程序,但是当我绘图时它一直闪烁,就像我需要某种双重缓冲一样,但我不知道如何做到这一点。

我在Panel上画画,我用Bitmap来存储图形。

下面是我的代码:

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);
    }
}

c#画图程序闪烁

你不仅应该把DoubleBuffered变成true,而且还应该用PictureBox代替Panel并在其上绘制。这应该能解决你的问题:).

你需要子类化Panel来做到这一点,因为你需要覆盖某些东西。像这样的Panel应该可以工作:

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.
}

但是,您根本不需要PanelControl添加的功能,也就是说,它可以作为容器使用。所以,事实上,你应该从Control继承,除非你需要子控件。

另一个改进可能是只有Invalidate改变了Rectangle。这将重新绘制一个区域,减少绘图时间。您还可以将srcRect传递给Graphics.DrawImage, srcRecte.ClipRectangle计算,如果子类化Panel不适合您,则可以获得更好的性能。

在Paint事件中绘制像素图时,闪烁通常是由Windows窗体引起的,因为它先绘制背景,然后绘制像素图。因此,闪烁是在几分之一秒内可见的背景。

你可以在面板的ControlStyle属性中设置Opaque样式。这将会开启背景绘制,因为Windows Forms现在假定您的代码将完全绘制面板的内容。

通常,只需在代码中添加this.DoubleBuffered = true;就可以达到目的。

如果没有,将以下代码添加到表单中:

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}
您也可以使用反射来更改它,但是没有任何优势,无论是可读性还是速度。