65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 GDI+ 和 C# 进行无闪烁绘图

2003 年 7 月 29 日

公共领域

2分钟阅读

viewsIcon

461079

downloadIcon

8010

描述如何使用 C# 和 GDI+ 实现无闪烁绘图。

Sample Image - flickerFreeDrawing.jpg

引言

本文介绍了如何使用 GDI+ 在 Windows Forms 上实现无闪烁绘图,假设您对 VS.NET、C# 和 .NET 框架有基本的了解。

背景

无闪烁绘图或双缓冲是一种在 Windows 编程世界中广泛使用的技术,用于减少在处理窗口中的绘图事件时出现的闪烁。

通常,通用窗口程序在发生 WM_PAINT(绘图)事件时直接绘制到设备上下文(图形对象)。如果窗口被反复刷新(无效),这可能会导致闪烁。三种可能发生闪烁的例子包括:窗口调整大小或动画(启动计时器,并在计时器事件中刷新窗口)或将对象拖到窗口上(例如 Visio)

我们可以使用一种称为双缓冲的技术来消除闪烁。我们不是直接在图形对象上绘制,而是在一个屏幕外图形对象上绘制,当绘图完成后,我们将屏幕外图形对象绘制到 Paint 事件提供的图形对象上。我们还重写了 OnPaintBackground 方法,以防止 Windows Form 执行任何背景渲染(我们必须在屏幕外图形对象的渲染过程中自行绘制背景,这通常是首先完成的事情)。

双缓冲技术被封装在一个名为 DBGraphics 的简单类中,并且可以轻松地在典型的基于 Windows Form 的应用程序中实现,如下所示。

使用代码

双缓冲类可以在 Windows Form 的范围内使用。以下步骤描述了如何在您的代码中实现 DBGraphics

  • 步骤 1 - 在您的 Windows Form 类中声明 DBGraphics 变量,并在 Windows Form 构造函数中实例化该对象。
using GDIDB; // Declare the namespace
  
 public class MainWnd : System.Windows.Forms.Form
{
     ... Some other code
    private DBGraphics memGraphics;
     ... Some other code
      
    public MainWnd()
    {    
        memGraphics = new  DBGraphics();
    }           
     
}; 
  • 步骤 2 - 处理调整大小和加载事件以创建与 Client 矩形大小相同的双缓冲对象。这在窗体加载事件中完成,因为调整大小事件只有在手动调整窗体大小时才会触发。这里需要注意的一件事是,即使我们不在 Paint 事件中,我们也需要获取窗体的图形对象,这可以通过调用 this.CreateGraphics() 完成,这类似于 GetDC()
                            
private void MainWnd_Load(object sender, System.EventArgs e)
{ 
    memGraphics.CreateDoubleBuffer(this.CreateGraphics(), this.ClientRectangle.Width, this.ClientRectangle.Height);
}                 
                      
private void MainWnd_Resize(object sender, System.EventArgs e)
{ 
    memGraphics.CreateDoubleBuffer(this.CreateGraphics(), this.ClientRectangle.Width, this.ClientRectangle.Height);
    Invalidate(); // Force a repaint after has been resized 
} 

  • 步骤 3 - 覆盖 OnPaintBackground 以允许绘图事件呈现背景。
protected override void OnPaintBackground(PaintEventArgs pevent)
{
}
 
  • 步骤 4 - 最后,实现 Paint 事件
protected override void Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{

    if (memGraphics.CanDoubleBuffer())
    {
    // Fill in Background (for effieciency only the area that has been clipped)
         memGraphics.g.FillRectangle(new SolidBrush(SystemColors.Window), e.ClipRectangle.X,e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height);

        // Do our drawing using memGraphics.g instead e.Graphics
     
        ... Some other code
   
       // Render to the form
        memGraphics.Render(e.Graphics);
    }
}
 

演示代码

演示代码展示了如何使用双缓冲实现简单的拖放界面,它可以用作拖放应用程序(如 Microsoft Visio)的起点。

历史

V1.0 文章创建。

© . All rights reserved.