科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Windows窗体的.Net框架绘图技术

Windows窗体的.Net框架绘图技术

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文针对那些Windows 窗体开发人员并有助于他们在应用程序编制过程中使用简单的绘图技术。

作者:xuejinyoulan 来源:天极网 2007年11月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

具备双重缓冲区技术的且使用AntiAliasing(反锯齿)属性的SpiderWeb_DblBuff示例程序

完成了简单的双重缓冲区应用后有两个问题需要向读者阐明,.Net中的某些控件例如:Button、PictureBox、Label还有PropertyGrid都已经很好的利用了该技术!这些控件在默认状态下会自动启用双重缓冲区技术,用户可以通过对“DoubleBuffer”属性的设置来就可以实现双重缓冲区技术。所以,用户若使用PictureBox来绘制蜘蛛网将会更有效率一些,而且也使程序变得更加简单了。

我们在这里讨论的双重缓冲区技术既不是完全被优化但也没有什么太大的负面影响。双重缓冲区技术是减少Windows 窗体绘制时闪烁的一条重要途径,但是它也确实消耗不少内存,因为它将会使用双倍的内存空间:应用程序所显示的图像和屏幕后方内存中的图像。每次Paint事件被激活时都会动态的创建位图对象,这种机制会相当耗费内存。而自带双重缓冲区技术的控件在使用DoubleBuffer属性后执行起来的优化程度则会更好一些。

使用GDI+的DIB(与设备无关的位图)对象来实现这种画面以外的内存缓冲,自带双重缓冲区机制的控件则能好的利用该位图对象。DIB是底层Win32的对象用于高效的屏幕绘制。同样,值得注意的是GDI+的第一个版本GDI中仅与硬件加速有关以及一些简单功能可以直接使用,由于这样的限制,像反锯齿和半透明等屏幕绘制方法执行起来的速度则相当慢。尽管双重缓冲区机制消耗了一些内存但是它的使用不容置疑的增强了程序的执行性能。

智能重绘,在绘制前需要斟酌一下

“智能无效”(智能重绘)就是在暗示程序员应该明白仅应对程序中无效的区域进行重绘,对Regions对象所对应的无效区域进行重绘可以提高绘制性能,使用Regions对象你可以仅排除或绘制控件和窗体的部分区域已获得更好的性能。我们现在就开始来看一下BasicClip示例程序,这个程序使用保存在PaintEventArgs对象的ClipRectangle对象,之前我们已经提及,无论何时当程序的大小发生变化时Paint事件都会被激活。BasicClip示例程序用红和蓝两种颜色填充剪切的矩形区域,利用不同的速度调整窗体的大小几次以后,你会发现绘制的矩形区域其实就是窗体的无效区域(包括大于原始窗体大小的区域部分和缩少了的区域部分),示例程序的Paint事件代码如下:

以下是引用片段:
private void BasicClip_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
if (currentBrush.Color == Color.Red)
currentBrush.Color = Color.Blue;
else
currentBrush.Color = Color.Red;
g.FillRectangle(currentBrush, e.ClipRectangle);
g.Dispose();
}

该示例程序的唯一目的就是演示怎样仅针对部分区域进行图形绘制。

BasicClip示例程序中的彩色矩形区域就是表示窗体的下方和右侧的无效区域。

Regions是一种被用来定义Windows 窗体或者控件区域的对象,调整窗体大小后所获得的Regions就是窗体重绘的最小区域。当程序需要进行绘制的时候仅绘制感兴趣的特殊区域,这样绘制更小的区域就会使程序的运行速度更快。

为了更好的演示Regions的用法,请查看TextCliping示例程序。该程序重载了OnPaintBackground和OnPaint方法,直接重载这些方法比侦听事件更能保证代码在其它的绘制操作之前被调用,而且对于自定义控件的绘制也更加有效。为了清楚起见,示例程序提供了一个Setup方法,该方法定义了全局的Graphics对象。

以下是引用片段:
private void Setup()
{
GraphicsPath textPath = new GraphicsPath();
textPath.AddString(displayString, FontFamily.GenericSerif,
0, 75, new Point(10, 50), new StringFormat());
textRegion = new Region(textPath);
backgroundBrush = new TextureBrush(new Bitmap("CoffeeBeanSmall.jpg"),
WrapMode.Tile);
foregroundBrush = new SolidBrush(Color.Red);
}

上面的Setup方法首先定义一个空的GraphicsPath对象变量textPath,下一步字符串“Windows Forms”的边界被添加到该路径中,围绕这个轮廓创建Region。这样,一个被绘制在窗体表面的以字符串轮廓为区域的Region就被创建了。最后,Setup方法创建以材质刷子为背景和以实色刷子为前景来绘制窗体。

以下是引用片段:
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
Graphics bgGraphics = e.Graphics;
bgGraphics.SetClip(textRegion, CombineMode.Exclude);
bgGraphics.FillRectangle(backgroundBrush, e.ClipRectangle);
bgGraphics.Dispose();
}

上面定义的OnPaintBackground方法先立刻调用基类方法,这能够保证所有底层绘制的代码都能够被执行。下一步,从PaintEventArgs中获得Graphics对象,再将Graphics对象的剪切区域定义为textRegion对象。通过指定CombineMode.Exclude参数,明确无论在哪里绘制或怎样绘制Graphics对象都不绘制textRegion区域内部。

以下是引用片段:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics fgGraphics = e.Graphics;
fgGraphics.FillRegion(foregroundBrush, textRegion);
fgGraphics.Dispose();
}

最后,OnPaint事件负责精确的绘制出字符串。可以很容易的通过调用Graphics的FillRegion方法来实现。通过指定的前景刷子foregroundBrush和textRegion且仅是该区域被绘制。结果,Windows 窗体程序在运行之前确实“思考”该怎样进行绘制。

TextClipping示例程序,通过Region定义的Windows Forms字符串。能够使程序在绘制时避开一个区域。

适当的组合使用区域和智能重绘你可以编写出运行速度快且不会引起闪烁的绘制代码,并且比单独使用双重缓冲区绘制还要节省内存的消耗。

结论

如果你的程序确定要进行绘制操作,使用几种技术可以增强绘制性能。确保争取设置控件属性以及适当的Paint事件处理是编写健壮程序的开始。在权衡好利弊后可以使用双重缓冲区技术产生非常“保护视力”的结果。最后,在实际绘制前进行思考到底哪些客户区域或Region需要被绘制将非常有益。

希望通过这篇文章能够使读者更好的理解关于.net框架的绘制技术及其应用。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章