• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > Windows窗体的.Net框架绘图技术实现方法

Windows窗体的.Net框架绘图技术实现方法

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了windows窗体应用程序,c#windows窗体设计,c#windows窗体编程,windows窗体,vs2010 windows窗体等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

本文实例讲述了Windows窗体的.Net框架绘图技术实现方法,非常实用,具体内容如下:

一般来说,当编写一个典型的Windows 窗体程序时,窗体和控件的绘制、效果等操作是不需要特别加以考虑的。这是为什么呢?因为通过使用 .Net 框架,开发人员可以拖动一系列的控件到窗体上,并书写一些简单的与事件相关联的代码然后在IDE中按F5,一个完完全全的窗体程序就诞生了!所有控件都将自己绘制自己,窗体或者控件的大小和缩放都调整自如。在这里经常会用到的,且需要引起一点注意的就是控件效果。游戏,自定义图表控件以及屏幕保护程序的编写会需要程序员额外撰写用于响应 Paint 事件的代码。

  本文针对那些Windows 窗体开发人员并有助于他们在应用程序编制过程中使用简单的绘图技术。首先,我们会讨论一些基本的绘图概念。到底谁在负责进行绘制操作?Windows 窗体程序是如何知道何时该进行绘制的?那些绘制代码究竟被放置在哪里?之后,还将介绍图像绘制的双重缓冲区技术,你将会看到它是怎样工作的,怎样通过一个方法来实现缓存和实际显示的图像间的交替。最后,我们将会探讨”智能无效区域”,实际就是仅仅重绘或者清除应用程序窗体上的无效部分,加快程序的显示和响应速度。希望这些概念和技术能够引导读者阅读完本文,并且有助于更快和更有效的开发Windows 窗体程序。

  Windows 窗体使用GDI+图像引擎,在本文中的所有绘图代码都会涉及使用托管的.Net 框架来操纵和使用Windows GDI+图像引擎。

  尽管本文用于基本的窗体绘图操作,但是它同样提供了快速的、有效的且有助于提高程序性能的技术和方法。所以,在通读本文之前建议读者对.Net框架有个基本的了解,包括Windows 窗体事件处理、简单的GDI+对象譬如Line,Pen和Brush等。熟悉Visual Basic .Net或者C#编程语言。

概念

  Windows 应用程序是自己负责绘制的,当一个窗体”不干净”了,也就是说窗体改变了大小,或者部分被其它程序窗体遮盖,或者从最小化状态恢复时,程序都会收到需要绘制的信息。Windows把这种”不干净”状态称为”无效的(Invalidated)”状态,我们理解为:需要重绘,当Windows 窗体程序需要重绘窗体时它会从Windows消息队列中获取绘制的信息。这个信息经过.Net框架封装然后传递到窗体的 PaintBackground 和 Paint 事件中去,在上述事件中适当的书写专门用于绘制的代码即可。

  简单的绘图示例如下:

   using System; 
   using System.Drawing; 
   using System.Windows.Forms; 
   public class BasicX : Form 
   { 
   public BasicX() 
   { 
   InitializeComponent(); 
   } 
   private void BasicX_Paint(object sender,  PaintEventArgs e) 
   { 
   Graphics g = e.Graphics; 
   Pen p = new Pen(Color.Red); 
   int width = ClientRectangle.Width; 
   int height= ClientRectangle.Height; 
   g.DrawLine(p, 0,0, width, height); 
   g.DrawLine(p, 0, height, width, 0); 
   p.Dispose(); 
   } 
   private void InitializeComponent() 
   { 
   this.SetStyle(ControlStyles.ResizeRedraw,  true); 
   this.ClientSize = new  System.Drawing.Size(300, 300); 
   this.Text = "BasicX"; 
   this.Paint += new  PaintEventHandler(this.BasicX_Paint); 
   } 
   [System.STAThreadAttribute()] 
   public static void Main() 
   { 
   Application.Run(new BasicX()); 
   } 
   }

</div>

  上述代码分成两个基本的步骤来创建示例程序。首先 InitializeComponent 方法包含一些属性的设置和附加窗体 Paint 事件的处理过程。注意,在方法中控件的样式也同时被设置,设置控件的样式也是自定义Windows 窗体及控件行为的一种有效途径,譬如:控件的"ResizeRedraw"属性指示当窗体的大小变化发生以后需要对其完全进行重绘,也就是说重绘时总是需要对整个窗体的客户区域进行重绘。窗体的“客户区域”是指除了标题栏和边框的所有窗体区域。可以进行一个有趣的试验,取消该控件的属性然后再运行程序,我们可以很明显的看出为什么该属性会被经常的设置,因为窗体调整大小后的无效区域根本不会被重绘。

  好了,我们需要注意一下BasicX_Paint方法,正如先前所提到的,Paint 事件在程序需要重绘时被激活,程序窗体利用Paint事件来负责回应需要重绘的系统消息,BasicX_Paint方法的调用需要一个对象 sender 和一个PaintEventArgs类型的变量,PaintEventArgs类的实例或称之为变量 e 封装了两个重要的数据,第一个就是窗体的 Graphics 对象,该对象表示窗体可绘制的表面也称之为画布用于绘制诸如线、文本以及图像等,第二个数据就是ClipRectangle,该Rectangle对象表示窗体上无效的的矩形范围,或者说就是窗体需要重绘的区域。记住,当窗体的ResizeRedDraw设置后,调整大小后该ClipRectangle的大小实际就等于窗体整个客户区域的大小,或者是被其它程序窗体遮盖的那部分剪切区域。关于部分剪切区域的用处我们会在智能重绘章节作更详细的阐述。

双重缓冲区绘图技术

  双重缓冲区技术能够使程序的绘图更加快速和平滑,有效减少绘制时的图像闪烁。该技术的基本原理是先将图像绘制到内存中的一块画布上,一旦所有的绘制操作都完成了,再将内存中的画布推到窗体的或者控件的表面将其显示出来。通过这种操作后的程序能使用户感觉其更加快速和美观。

  下面提供的示例程序能够阐明双重缓冲区的概念和实现方法,这个示例所包含的功能已相当完整,且完全可以在实际应用中使用。在该章节后面还会提及该技术应该配合控件的一些属性设置才能达到更好的效果。

  要想领略双重缓冲区绘图技术所带来的好处就请运行SpiderWeb示例程序吧。程序启动并运行后对窗口大小进行调整,你会发现使用这种绘图算法的效率不高,并且在调整大小的过程中有大量的闪烁出现。

不具备双重缓冲区技术的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); 
   } 
   }

</div>

撰写很简单的用于响应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(); 
   }

</div>

  那么到底作怎么样的改动才能使上面的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(); 
   }

</div>

  上面的示例代码创建了内存位图对象,它的大小等于窗体的客户区域(就是绘图表面)的大小,通过调用Graphics.FromImage将内存中位图的引用传递给Graphics对象,也就是说后面所有对该Graphics对象的操作实际上都是对内存中的位图进行操作的,该操作在C++中等同于将位图对象的指针复制给Graphics对象,两个对象使用的是同

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Windows窗体的.Net框架绘图技术实现方法

相关文章

  • 2017-05-28C#下解析HTML的两种方法介绍
  • 2017-05-28C#简单实现SNMP的方法
  • 2017-05-28C#实现用户自定义控件中嵌入自己的图标
  • 2017-05-28C#使用WinRar命令进行压缩和解压缩操作的实现方法
  • 2017-05-28c#编写webservice服务引用实例分享
  • 2017-05-28C#从字符串中指定位置移除子字符串的方法
  • 2017-05-28C#实现DataTable映射成Model的方法(附源码)
  • 2017-05-28C++中const的实现细节介绍(C,C#同理)
  • 2017-05-28C#实现提高xml读写速度的方法
  • 2017-05-28在Unity中实现动画的正反播放代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C# 获取属性名的方法
    • C#使用Socket发送和接收TCP数据实例
    • C#中math类的全部运算方法(总结)
    • .NET创建、删除、复制文件夹及其子文件的实例方法
    • C#数据结构之顺序表(SeqList)实例详解
    • C#窗口实现单例模式的方法
    • C#迷你猜数实例分析
    • C# 设计模式系列教程-代理模式
    • c#实现汉诺塔问题示例
    • 详解C#批量插入数据到Sqlserver中的四种方式

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有