C#,WinForms中的双缓冲区?

时间:2011-02-23 18:21:18

标签: c# doublebuffered

        private void button3_Click(object sender, EventArgs e)
    {

        this.DoubleBuffered = true;

            for (int i = 0; i < 350; i++)
            {
                using (Graphics g = this.CreateGraphics() )
                {
                    g.Clear(Color.CadetBlue);
                    g.DrawImage(Properties.Resources._256, 100, 100, i-150, i-150);
                }
            }
    }

然而,我认为我将DoubleBuffered设置为true,图像仍然闪烁。有什么想法我做错了什么? 谢谢!

3 个答案:

答案 0 :(得分:6)

正如Neil所说,你不需要(也不应该)在循环的每次迭代中创建一个新的Graphics对象。这些是相对昂贵的资源,不应该毫无疑问地创建。

此外,您不应该在按钮内部进行绘制通过调用CreateGraphics来单击处理程序。它可能会导致问题,最明显的是当调用绘制处理程序时(即,每次窗口收到WM_PAINT消息并刷新时)您的绘图都“撤消”。您应该通过覆盖OnPaint来完成所有绘画,并在需要更新表单时简单地调用Invalidate()。

至于闪烁,将DoubleBuffered设置为true通常会处理它,但滚动自己的双缓冲是微不足道的。试试看。还要意识到在这样的循环中绘制可能不是你想要做的。如果要每隔一段时间更新一次,请使用计时器。您的代码正在以循环执行的速度执行,这通常是不可取的。

private void someTimer_Tick( ... )
{
    Invalidate();
}
protected override void OnPaint( PaintEventArgs e )
{
    using( var tempBmp = new Bitmap( ... ) )
    using( var g = Graphics.FromImage( tempBmp ) )
    {
        // draw to tempBmp
        e.Graphics.DrawImage( tempBmp, new Point( 0, 0 ) );
    }
}

答案 1 :(得分:2)

问题是你是在循环的每次迭代中创建一个新的图形对象

在using语句中移动for语句,您应该会看到显着的性能提升:

using (Graphics g = this.CreateGraphics() )
{
     for (int i = 0; i < 350; i++)
     {
        g.Clear(Color.CadetBlue);
        g.DrawImage(Properties.Resources._256, 100, 100, i-150, i-150);
     }
}

那,将您正在加载的资源文件移动到局部变量中也是一个好主意。

答案 2 :(得分:2)

Double-buffering仅对Paint事件启用。您正在使用CreateGraphics()直接绘制到屏幕,g.Clear()调用非常明显,因为它会立即擦除绘制的图像。不在Paint事件或OnPaint方法中绘图几乎总是一个错误。