内容发布更新时间 : 2024/12/27 9:57:15星期一 下面是文章的全部内容请认真阅读。
一种基于自定义剪切区集合的MFC程序
GDI绘图优化方法
罗幸明,徐伟强
浙江中控技术股份有限公司,浙江杭州,310053
摘 要: 传统MFC程序GDI绘图仅考虑屏幕刷新闪烁的优化,而对于绘图内容本身的优化考虑有限。常规应用下,GDI绘图本身确实不会成为程序的性能瓶颈,但在高分辨率、复杂画面的绘制显示时,这个问题就不得不考虑了。通常我们会使用系统剪切区进行优化控制,但是实际应用发现当分辨率或者画面复杂度大于一定程度后,该优化的性能提升有限。鉴于此,本文提出了一种简单可行的基于自定义剪切区集合判断的MFC程序GDI绘图优化方法,可以有效解决高分辨率、复杂画面的GDI绘图性能问题。
关键词: 自定义剪切区、MFC、GDI、绘图
One Optimizing Design Based On Custom Clipping Region
Sets Of MFC Programs Drawing With GDI
Luo Xingming,Xu Weiqiang
Zhejiang SUPCON Co.,Ltd, Hangzhou, Zhejiang, 310053
Abstract:When drawing with GDI of traditional MFC programs,the most considering things is the
screen flashing problems but not drawing itself.Normally drawing performance will not be the choke point,but it really will be when screen resolution is high enough or graphics is complex enough.It is usual to resolve this problem by using system clipping region,but after some industial practice we found that the benefits from this optimizing is limited.Based on this situation,this paper presents a simple effective and practical optimizing design based on custom clipping region sets which can effectivly improve drawing performance of complex graphics in industrial field.
Keyword:Custom Clipping Region Sets, MFC, GDI, Drawing
基金项目“石化、轨道交通行业分布式综合监控系统(SCADA)研发及应用示范”资助
1. GDI概述
GDI(Graphics Device Interface)是Windows操作系统的传统图形子系统,负责与设备无关的图形绘制,Win32 API为应用程序提供了丰富的绘图函数和功能,而MFC又对他们进行了C++类的封装。
传统GDI是随Windows 1.0于1985年11月推出的,新的GDI+则是随Windows XP于2001年10月推出的GDI的改进版,增加了α变色、渐变画刷、样条曲线、矩阵变换、图像处理、持久路径等新功能。随着Winsows Visa及.NET框架3.0的推出,微软于2006年11月又推出了基于DirectX和.NET框架的全新图形子系统WPF(Windows Presentation Foundation),它统一了桌面和浏览器等客户端应用程序的图形界面,采用XML声明式编程,将用户界面的设计和编程彻底分离开来,是Windows的下一代GUI显示系统。
本文提出了一种基于MFC应用框架的GDI绘图的优化方法,且这种方法在笔者公司实际发布的产品中已经被成熟使用且经过现场应用证明是行之有效的。
2. MFC程序绘图的一般方法
MFC应用程序中,绘图一般在视图类(屏幕/打印机)的绘图函数OnDraw中进行,例如:
void CSCDrawView::OnDraw(CDC* pDC) { }
CSCDrawDoc* pDoc = GetDocument(); If(!pDoc) {
return; }
// TODO:此处添加绘图逻辑 ......
当应用程序需要重绘窗口时(如程序启动、窗口大小改变、全部或部分窗口重现、程
序员主动调用RedrawWindow或InvalidateWindow/UpdateWinow),MFC框架都会调用这个函数来重新绘制窗口客户区。绘图一般是通过MFC封装的设备上下文类(CDC)提供的各种绘图函数实现,如绘制直线、矩形、文字等,绘图前先要获取客户区大小及CDC对象,设置绘图颜色、文字对齐方式,再根据文档数据或者用户操作绘制各种图形。
3. GDI绘图的常见优化
3.1. 双缓冲绘图
如果在OnDraw函数中直接使用传入的设备上下文进行图形绘制操作,一个可能的结果就是程序会出现严重的闪烁现象。闪烁的原因在于短时间内存在多次的画面变化刷新操作,每调用一次设备上下文的区域绘图操作,如FillRect、BitBilt等,Windows的图形显示系统就会对屏幕中的指定区域进行一次刷新操作,而实际的绘图逻辑中往往需要多次调用类似的绘图函数以实现所需要的绘图效果,从而造成屏幕的频繁刷新,即我们所看到的屏幕闪烁现象。
解决这个问题的一个思路就是尽可能减少不必要的屏幕刷新操作,如果每次的绘制逻辑都只需要对屏幕刷新一次,尽可能减少与设备之间的直接交互次数,自然解决了屏幕闪烁的问题,同时也提升了绘图的效率,这就是我们常说的“双缓冲绘图”的原理。
关于“双缓冲绘图”的原理及实现方法网上有很多相关的文章讨论,这里就不再赘述。
3.2. 系统剪切区交集判断
“双缓冲绘图”可以有效解决屏幕闪烁的问题,但是对于较大数据量或者较复杂图形绘制的效率提升效果并不明显。这种情况下,可以考虑使用系统剪切区判断有效绘图区域的方式优化绘图效率(系统剪切区交集判断)。设备上下文提供了一个获取系统当前剪切区的函数(GetClipBox),使用该函数可以获取一个矩形区域,表示系统当前有效的刷新区域,在每次OnDraw函数调用时,只需重绘那些包含在该剪切区范围内的对象即可,其他对象保留上一次绘图的效果,从而有效减少重绘对象的数目,提升绘图效率。
系统剪切区交集判断流程示图如下: