关闭

MFC 显示图形如何避免闪烁

标签: 图形mfcnull网络
641人阅读 评论(0) 收藏 举报
分类:

转载地址: http://hi.baidu.com/moreeffort/blog/item/35a90b4e0bc1d7ecd62afc53.html


显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。   
  而且多数人认为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()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。   
  如果你的绘图过程不复杂,这样做可能对你的绘图效率不会有提高。

0
0
查看评论

显示图形如何避免闪烁

显示图形如何避免闪烁显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。MFC的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单,只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。我想就我长期(呵呵当然...
  • iiprogram
  • iiprogram
  • 2008-04-16 11:52
  • 749

自绘CListCtrl防止闪烁的方法

自绘控件中经常会遇到闪烁的问题,主要原因是某个区域发生了重复性的绘制而导致的,而列表控件在自绘后闪烁原因是WM_ERASEBKGND消息所导致的。解决定办法可以将这个消息屏蔽掉,然后使用双缓存,在Windows 5.1版本以后可以使用LVS_EX_DOUBLEBUFFER样式,为了各个版本的兼容性我...
  • mynamelj
  • mynamelj
  • 2011-06-27 23:03
  • 2342

完全解决在MFC中连续贴图重绘闪烁问题

这是小弟写的一个五子棋程序,由于程序的黑白棋子的安放是利用贴图来完成,所以当发生重绘时界面闪烁的非常严重,屏幕卡死!拉不动! 小弟各方百度都没有发现解决办法,但是而然看到一个论坛回复中,一高手介绍利用CMemDC来解决,经过小弟的实验果然成功。特将此方法介绍给大家。   CMemDC...
  • u012105526
  • u012105526
  • 2013-09-13 09:29
  • 1012

MFC防止绘图闪烁——双缓冲技术

转自: http://blog.163.com/fk1007@126/blog/static/3003673920092189224923/ 在VC/MFC用CDC绘图时,频繁的刷新,屏幕会出现闪烁的现象,CPU时间占用率相当高,绘图效率极低,很容易出现程序崩溃。 ...
  • u011295947
  • u011295947
  • 2017-05-23 23:03
  • 270

MFC如何避免闪烁

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

转载:显示图形如何避免闪烁

转载来源:http://bbs.csdn.net/topics/290028003 转载来源:http://my.csdn.net/ilovedrv   显示图形如何避免闪烁          ...
  • chunyexiyu
  • chunyexiyu
  • 2014-01-02 16:28
  • 721

引用:显示图形如何避免闪烁

我知道在内存中做 然后贴上去 但那样还是很闪回复人: windows_editor(等咱有钱了,每天早上喝两大碗豆浆)显示图形如何避免闪烁    显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。...
  • lei001
  • lei001
  • 2005-04-26 20:37
  • 914

MFC中屏幕刷新闪烁问题解决方法总结

在MFC中经常遇到屏幕刷新的问题,下面是几种解决方法。 1,刷新整个程序区域,有明显的闪烁情况     Invalidate( TRUE );     UpdateWindow();  2,刷新指定区域,...
  • longzaitianya1989
  • longzaitianya1989
  • 2014-01-14 16:54
  • 11210

MFC如何避免重绘闪烁

只需要重写OnPaint()和OnEraseBkgnd(CDC* pDC)即可 OnPaint()代码如下: if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinte...
  • T_Sky
  • T_Sky
  • 2012-01-16 09:53
  • 501

关于MFC OnDraw重绘时画面闪烁问题的解决

图形为什么会闪烁的原因是:我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现...
  • zhangxuye_fujitsu
  • zhangxuye_fujitsu
  • 2011-03-30 11:20
  • 1306
    个人资料
    • 访问:309575次
    • 积分:4131
    • 等级:
    • 排名:第8875名
    • 原创:76篇
    • 转载:34篇
    • 译文:13篇
    • 评论:44条
    联系方式
    文章分类