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

GraphicsBuffer 类 - 控件动态视觉状态的缓冲

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.95/5 (6投票s)

2004 年 8 月 3 日

4分钟阅读

viewsIcon

37044

downloadIcon

627

本文讨论了一个自定义类的使用,该类缓存自定义图像。该类 GraphicsBuffer 最适合用于缓存控件的视觉状态,而无需担心控件闪烁和不必要的处理器使用。

引言

具有动态用户界面的所有者绘制 UserControls 通常有几种不同的视觉状态。当你开始编写其中一个控件时,你会很快注意到需要大量绘图才能改变状态的控件往往会闪烁,并且根据绘图操作的复杂程度,用户在控件重绘时可能会遇到延迟。虽然通过在控件上设置 ControlStyles.DoubleBuffer 样式可以解决闪烁问题,但这并不能解决处理器延迟问题。本文介绍的类通过提供一种简单的方法来缓存控件可能具有的不同视觉状态,从而解决了这两个问题。演示应用程序通过创建一个具有三种状态的简单按钮控件来说明该类的使用:正常状态、鼠标悬停状态和鼠标按下状态。

背景

本文讨论的主题非常简单,大多数人应该都能轻松理解。但是,假定您在 UserControls 和 GDI+ 的创建方面有一些经验。

源代码分为两个项目:GraphicsBuffer 和 GraphicsBufferText。GraphicsBuffer 项目包含 GraphicsBuffer 类的源代码,GraphicsBufferTest 项目包含使用 GraphicsBuffer 类的演示控件的代码。这两个项目都创建于 Visual Studio .NET 2003 中,但代码均未使用早期 Visual Studio .NET 版本中不存在的构造。

使用 GraphicsBuffer 对象

使用 GraphicsBuffer 对象是一个三步过程:

  1. 创建缓冲区。
  2. 使用标准的 GDI+ 方法调用写入缓冲区。
  3. 从对象中提取缓存的图像并将其绘制到目标控件上。

1. 创建缓冲区

要创建图像缓冲区,GraphicsBuffer 对象要求您指定缓冲区的键和图像大小。键用于以后访问缓冲区。图像缓冲区的大小一旦创建就无法更改,但可以将其丢弃并创建一个新的。如果缓冲区用于缓存控件的视觉状态,则缓冲区的大小应与控件的大小相同。

  //Create the GraphicsBuffer object and then create three 
  //100x50 px buffer called Normal, MouseDown, and MouseOver
  GraphicsBuffer _graphicsBuffer = new GraphicsBuffer();
  _graphicsBuffer.Create("Normal",100,50);
  _graphicsBuffer.Create("MouseDown",100,50);
  _graphicsBuffer.Create("MouseOver",100,50);

2. 写入缓冲区

缓冲区通过其索引器公开了一个 Graphics 对象。索引器的键是在创建缓冲区时指定的名称。由于公开了 Graphics 对象,因此所有标准的绘图功能都可用。下面的代码在缓冲区上绘制渐变背景,创建实心边框,并在其中心绘制一些文本。

  Graphics g; Rectangle rect;

  StringFormat sf = new StringFormat();
  sf.Alignment = StringAlignment.Center;
  sf.LineAlignment = StringAlignment.Center;
  rect = new Rectangle(0,0,100,50);

  //draw normal state
  g = _graphicsBuffer["Normal"];
  Brush b = new LinearGradientBrush (rect, 
            Color.FromArgb(125,125,150), 
            Color.FromArgb(150,150,200),45F,true);
  g.FillRectangle(b,rect);
  g.DrawRectangle(new Pen(Color.FromArgb(125,125,175),1), rect);
  g.DrawString("Hello World",new Font("Arial",10), 
                new SolidBrush(Color.White),rect,sf);

作为一个实际建议,我建议将绘制到缓冲区的代码包装在一个函数块中,以便可以在应用程序的任何时候调用它。这是因为在某些情况下,您可能希望丢弃缓冲区中的图像并重新生成它。例如,如果您的图像取决于它所显示的控件的大小,那么在控件调整大小时就需要重新创建它。此外,您的控件可能有几个属性会影响控件的视觉外观。当这些属性中的任何一个被更改时,都需要重建缓冲区。要丢弃缓冲区的内容,您可以使用 Clear()Remove() 方法。

  //clear all buffered images
  _graphicsBuffer.Clear();

  //remove a single image from the buffer
  _graphicsBuffer.Remove("Normal");  //removes the item with the "Normal" key

3. 在控件上显示缓存的图像

要从控件检索缓存的图像,请使用 GetImage() 方法。在大多数情况下,这将在控件的 Paint 事件中使用。

  private void BufferedButton_Paint(object sender, 
                         System.Windows.Forms.PaintEventArgs e)
  {
    e.Graphics.DrawImage(_graphicsBuffer.GetImage("Normal"), 
                                         this.ClientRectangle);
  }

上面的示例始终绘制控件的“Normal”状态。在您的应用程序中,您可能会使用 switch 语句来选择要显示的各种可能状态。演示项目中的代码说明了这一点。

结论

GraphicsBuffer 类本身的代码并没有什么革命性的。它的极致酷炫之处在于,当您编写使用它的结构化代码时,它为您的控件增添了清晰度。当正确使用该类时,您的控件只会根据需要重绘自己。许多控件在每次触发 Paint 事件时都会重复所有绘图过程。使用这个简单的类将为您的控件和应用程序的专业性带来可衡量的改进。

历史

  • 2004 年 8 月 3 日 - 初始创建。
© . All rights reserved.