Visual C++ 7.1Visual C++ 7.0Visual Studio .NET 2003Windows 2003.NET 1.1Windows 2000Visual C++ 6.0Windows XPMFC中级开发Visual StudioWindowsC++.NETC#
使用 GDI+ 和 C# 进行无闪烁绘图






4.31/5 (38投票s)
描述如何使用 C# 和 GDI+ 实现无闪烁绘图。
引言
本文介绍了如何使用 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 文章创建。