科技行者

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

知识库

知识库 安全导航

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

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

  • 扫一扫
    分享文章到微信

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

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

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

关键字:

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

不具备双重缓冲区技术的SpiderWeb示例程序

纵观程序的源码你会发现在程序Paint事件激活后是通过调用LineDrawRoutine方法来实现线的绘制的。LineDrawRoutine方法有两个参数,第一个是Graphics对象是用于绘制线条的地方,第二个是绘图工具Pen对象用来画线条。代码相当简单,一个循环语句,LINEFREQ常量等,程序从窗体表面的左下一直划线到其右上。请注意,程序使用浮点数来计算在窗体上的绘制位置,这样做的好处就是当窗体的大小发生变化时位置数据会更加精确。

以下是引用片段:
private void LineDrawRoutine(Graphics g, Pen p)
{
float width = ClientRectangle.Width;
float height = ClientRectangle.Height;
float xDelta = width / LINEFREQ;
float yDelta = height / LINEFREQ;
for (int i = 0; i < LINEFREQ; i++)
{
g.DrawLine(p, 0, height - (yDelta * i), xDelta * i, 0);
}
}

撰写很简单的用于响应Paint事件SpiderWeb_Paint的代码,正如前面所提到的,Graphics对象就是从Paint事件参数PaintEventArgs对象中提取出来的表示窗体的绘制表面。这个Graphics对象连同新创建Pen对象一起传递给LineDrawRoutine方法来画出蜘蛛网似的线条,使用完Graphics对象和Pen对象后释放其占用的资源,那么整个绘制操作就完成了。

以下是引用片段:
private void SpiderWeb_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen redPen = new Pen(Color.Red);
LineDrawRoutine(g, redPen);
redPen.Dispose();
g.Dispose();
}

那么到底作怎么样的改动才能使上面的SpiderWeb程序实现简单的双重缓冲区技术呢?原理其实相当简单,就是将应该画到窗体表面的绘制操作改成先画到内存中的位图上,LineDrawRoutine向这个在内存中隐藏的画布执行同样的蜘蛛网绘制操作,等到绘制完毕再通过调用Graphics.DrawImage方法将隐藏的画布上内容推到窗体表面来显示出来,最后,再加上一些小的改动一个高性能的绘图窗体程序就完成了。

请比较下面双重缓冲区绘图事件与前面介绍的简单绘图事件间的区别:

以下是引用片段:
private void SpiderWeb_DblBuff_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen bluePen = new Pen(Color.Blue);
Bitmap localBitmap = new Bitmap(ClientRectangle.Width,ClientRectangle.Height);
Graphics bitmapGraphics = Graphics.FromImage(localBitmap);
LineDrawRoutine(bitmapGraphics, bluePen);
//把在内存里处理的bitmap推向前台并显示
g.DrawImage(localBitmap, 0, 0);
bitmapGraphics.Dispose();
bluePen.Dispose();
localBitmap.Dispose();
g.Dispose();
}

上面的示例代码创建了内存位图对象,它的大小等于窗体的客户区域(就是绘图表面)的大小,通过调用Graphics.FromImage将内存中位图的引用传递给Graphics对象,也就是说后面所有对该Graphics对象的操作实际上都是对内存中的位图进行操作的,该操作在C++中等同于将位图对象的指针复制给Graphics对象,两个对象使用的是同一块内存地址。现在Graphics对象表示的是屏幕后方的一块画布,而它在双重缓冲区技术中起到至关重要的作用。所有的线条绘制操作都已经针对于内存中的位图对象,下一步就通过调用DrawImage方法将该位图复制到窗体,蜘蛛网的线条就会立刻显示在窗体的绘制表面而且丝毫没有闪烁出现。

这一系列的操作完成后还不是特别有效,因为我们先前提到了,控件的样式也是定义Windows 窗体程序行为的一条途径,为了更好的实现双重缓冲区必须设置控件的Opaque属性,这个属性指明窗体是不负责在后台绘制自己的,换句话说,如果这个属性设置了,那么必须为清除和重绘操作添加相关的代码。具备双重缓冲区版本的SpiderWeb程序通过以上的设置在每一次需要重绘时都表现良好,窗体表面用其自己的背景色进行清除,这样就更加减少了闪烁的出现。

以下是引用片段:
public SpiderWeb_DblBuff()
{
SetStyle(ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
}
private void SpiderWeb_DblBuff_Paint(object sender, PaintEventArgs e)
{
Bitmap localBitmap = new Bitmap(ClientRectangle.Width,
ClientRectangle.Height);
Graphics bitmapGraphics = Graphics.FromImage(localBitmap);
bitmapGraphics.Clear(BackColor);
LineDrawRoutine(bitmapGraphics, bluePen);
}

结果怎么样?图像的绘制平滑多了。从内存中将蜘蛛网的线条推到前台以显示出来是完全没有闪烁的,但是我们还是稍微停顿一下,先将内存中的位图修整一下再显示出来,可以添加一行代码以便使线条看上去更加平坦。

以下是引用片段:
bitmapGraphics.SmoothingMode = SmoothingMode.AntiAlias;

在将内存中的位图对象赋给Graphics后通过放置这行代码,我们在画布上所画的每一个线条都使用了反锯齿,使凹凸不平的线条显得更加平坦。

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

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

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