`
java-mans
  • 浏览: 11413854 次
文章分类
社区版块
存档分类
最新评论

用MFC如何高效地绘图

 
阅读更多

显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。 而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。 MFC的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单, 只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。 我想就我长期(呵呵当然也只有2年多)使用MFC绘图的经验谈谈 我的一些观点。

1、显示的图形为什么会闪烁? 我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏 幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时, 总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容 反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来 在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。 当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来 绘制的图形进行清除,而又叠加上了新的图形。 有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的, 其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。 例如在OnDraw(CDC *pDC)中这样写:

pDC->MoveTo(0,0);

pDC->LineTo(100,100);

这个绘图过程应该是非常简单、非常快了吧,但是拉动窗口变化时还是会看见 闪烁。其实从道理上讲,画图的过程越复杂越慢闪烁应该越少,因为绘图用的 时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。 比如:清楚屏幕时间为1s绘图时间也是为1s,这样在10s内的连续重画中就要闪 烁5次;如果清楚屏幕时间为1s不变,而绘图时间为9s,这样10s内的连续重画 只会闪烁一次。这个也可以试验,在OnDraw(CDC *pDC)中这样写:

for(int i=0;i<100000;i++)

{

pDC->MoveTo(0,i);

pDC->LineTo(1000,i);

}

呵呵,程序有点变态,但是能说明问题。 说到这里可能又有人要说了,为什么一个简单图形看起来没有复杂图形那么 闪呢?这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要 闪得厉害一些,但是闪烁频率要低。 那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了, 闪烁是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间 的差异很小所以看起来不闪。如果不信,可以在动画的每一帧中间加一张纯白的帧, 不闪才怪呢。

2、如何避免闪烁 在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉MFC 提供的背景绘制过程了。实现的方法很多, * 可以在窗口形成时给窗口的注册类的背景刷付NULL * 也可以在形成以后修改背景

static CBrush brush(RGB(255,0,0));

SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);

* 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE 这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样, 变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有 图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。

3、如何实现双缓冲 首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:

CDC MemDC; //首先定义一个显示设备对象

CBitmap MemBitmap;//定义一个位图对象

//随后建立与屏幕显示兼容的内存显示设备

MemDC.CreateCompatibleDC(NULL); //这时还不能绘图,因为没有地方画 ^_^

//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小

MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight); //将位图选入到内存显示设备中

//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上

CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);

//先用背景色将位图清除干净,这里我用的是白色作为背景

//你也可以用自己应该用的颜色

MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));

//绘图

MemDC.MoveTo(……);

MemDC.LineTo(……);

//将内存中的图拷贝到屏幕上进行显示

pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);

//绘图完成后的清理

MemBitmap.DeleteObject();

MemDC.DeleteDC();

上面的注释应该很详尽了,废话就不多说了。

4、如何提高绘图的效率 我主要做的是电力系统的网络图形的CAD软件,在一个窗口中往往要显示成千上万个电力元件,而每个元件又是由点、线、圆等基本图形构成。如果真要在一次重绘过程重画这么多元件,可想而知这个过程是非常漫长的。如果加上了图形的浏览功能,鼠标拖动图形滚动时需要进行大量的重绘,速度会慢得让用户将无法忍受。怎么办?只有再研究研究MFC的绘图过程了。 实际上,在OnDraw(CDC *pDC)中绘制的图并不是所有都显示了的,例如:你 在OnDraw中画了两个矩形,在一次重绘中虽然两个矩形的绘制函数都有执行,但是很有可能只有一个显示了,这是因为MFC本身为了提高重绘的效率设置了裁剪区。裁剪区的作用就是:只有在这个区内的绘图过程才会真正有效,在区外的是无效的,即使在区外执行了绘图函数也是不会显示的。因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生,改变的区域并不是整个图形而只有一小部分,这一部分需要改变的就是pDC中的裁剪区了。因为显示(往内存或者显存都叫显示)比绘图过程的计算要费时得多,有了裁剪区后显示的就只是应该显示的部分,大大提高了显示效率。但是这个裁剪区是MFC设置的,它已经为我们提高了显示效率,在进行复杂图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的绘图过程了。可以先用pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。 如果你的绘图过程不复杂,这样做可能对你的绘图效率不会有提高。

分享到:
评论

相关推荐

    用MFC如何高效地绘图.rar_MFC_MFC 绘图_MFC如何绘图_绘图

    讲解如何用MFC如何高效地绘图,深入浅出,很适合初学者

    MFC高效画图

    本文介绍了如何使用双缓存画图的方法,使画图不再抖动,适合2维游戏开发初学者

    MFC使用GDI+双缓存画图

    这段时间做项目用到GDI+绘制图形,在网上找了很多关于双缓存的资料大多是讲图片方面的,关于绘图的讲的很少。自己做了个希望对大家有帮助

    MFC解决窗口保存及重绘闪烁问题的一种比较好的方案 v1.0.5

    包含文件说明: 1. SolveFlashingAndRedrawv1.0.5 纯净版 ... MFC的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单,只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。

    WindowsAPI参考手册

    学习Win32 API 能更深刻的理解MFC 的运作机制,同时使用Win32 API 函数编程要比使用MFC 更灵活, 能编写出更加高效的程序。Microsoft Win32 API 也可以在VB 和Delphi 等语言中使用。 Microsoft Win32 API 函数按照...

    正宗《Visual C++2008入门经典》中文 高清完整版PDF part5(共6部分)

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2008的基础知识,了解如何使用MFC进行本地ISO/ANSI C++ Windows应用程序开发以及如何使用Windows Forms进行C++/CLI Windows应用程序开发...

    正宗《Visual C++2008入门经典》中文版part1 pdf

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2008的基础知识,了解如何使用MFC进行本地ISO/ANSI C++ Windows应用程序开发以及如何使用Windows Forms进行C++/CLI Windows应用程序开发...

    正宗《Visual C++2008入门经典》中文版part3 pdf

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2008的基础知识,了解如何使用MFC进行本地ISO/ANSI C++ Windows应用程序开发以及如何使用Windows Forms进行C++/CLI Windows应用程序开发...

    正宗《Visual C++2008入门经典》中文版part4 pdf

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2008的基础知识,了解如何使用MFC进行本地ISO/ANSI C++ Windows应用程序开发以及如何使用Windows Forms进行C++/CLI Windows应用程序开发...

    正宗《Visual C++2008入门经典》中文版part2 pdf

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2008的基础知识,了解如何使用MFC进行本地ISO/ANSI C++ Windows应用程序开发以及如何使用Windows Forms进行C++/CLI Windows应用程序开发...

    正宗《Visual C++2008入门经典》中文版part6 pdf

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2008的基础知识,了解如何使用MFC进行本地ISO/ANSI C++ Windows应用程序开发以及如何使用Windows Forms进行C++/CLI Windows应用程序开发...

    VC与Labview、Matlab编程论文资料[2].rar

    使用MFC和ADO实现不规则窗口通讯录.pdf 分布式软件动态配置环境可视化的研究与实现.pdf 利用Debug探索VisualC_编程原理.pdf 利用MFC实现Windows下工业控制的高精度定时.pdf 利用VC_6_0实现PLC实时监控.pdf 利用VC_...

    VC与Labview、Matlab编程论文资料

    使用MFC和ADO实现不规则窗口通讯录.pdf 分布式软件动态配置环境可视化的研究与实现.pdf 利用Debug探索VisualC_编程原理.pdf 利用MFC实现Windows下工业控制的高精度定时.pdf 利用VC_6_0实现PLC实时监控.pdf 利用VC_...

    VC与Labview、Matlab编程论文资料[4].rar

    使用MFC和ADO实现不规则窗口通讯录.pdf 分布式软件动态配置环境可视化的研究与实现.pdf 利用Debug探索VisualC_编程原理.pdf 利用MFC实现Windows下工业控制的高精度定时.pdf 利用VC_6_0实现PLC实时监控.pdf 利用VC_...

    Visual C++ 2005入门经典--源代码及课后练习答案

    此外,本书各章后面的习题将有助于读者温故而知新,并尽快成为C++高效程序员。...   作译者  Ivor Horton是世界著名的计算机图书作家,主要从事与编程相关的顾问及撰写工作,曾帮助无数程序员步入编程的殿堂。他...

Global site tag (gtag.js) - Google Analytics