服务热线:
您当前的位置:首页 > 世纪星月刊 > 第11期 (2011年11月)

【技术前沿】提高图形程序性能

2011/12/8 16:11:40

 

研发部 杨盛海

 

 

 


  使用VC开发过图形界面程序的程序员们都清楚,那真是一种苦力,使用MFC提供的控件直接搭建的界面光条秃秃的,而且使用起来也是感觉很别扭,不知道哪里不对劲,远没有和VC同时期出现在市场上的其它编程工具好用,比如VB、VFP等,就连不是微软出品的Delphi和C++ Builder都比VC好用得紧。所以市面上有一种声音,VC虽然很强大,但不适合于做界面,经典的开发模式就是,用VC开发功能,封装成动态库,用VB或者delphi做界面,再调用VC做的动态库。

  VC虽然不适合于开发界面,但也给VC爱好者以很大的诱惑,如果不是项目时间很紧,他们会非常乐意使用VC来开发界面。VC除了使用系统自带的控件搭界面之外,还有一个可以做出很漂亮的界面的途径,那就是帖图,使用贴图做界面,麻烦是麻烦一点,但做出来的界面比较专业,尤其在响应鼠标事件时,稍微变换一下贴图,就能做出很炫的效果。

  在VC下开发Windows界面,有一个很挠头的问题,如果你稍微处理不得当,就会造成闪烁,使人不得不对Windows处理图形的能力产生怀疑。Windows有两种可以处理图形的开发库,一种是GDI,一种是Direct Draw, 我们经常使用的是GDI,如果不是对性能有特殊要求的话,谁也不会使用Direct Draw,因为那是为游戏程序准备的,可以直接操作显卡硬件性能超群,但是异常复杂,而且一般应用在独占屏幕的模式下。那我们只剩下GDI一种开发库可以选择,如何使GDI发挥出最大的效能,是我们今天所要讨论的话题。

  我们在使用Windows时经常会看到窗口会卡上一两秒钟然后才能正常打开,这我们都习以为常了,因为窗口在打开的过程中会有一些文件搜索的处理,当系统忙于处理这些事物时,界面展示只好先晾在一边儿了。所以图形展示要想非常平滑,第一要务就是性能,不要在显示画面的程序里加入一些循环往复非常占用CPU的算法,举个例子,要在屏幕上绘制一条铁路的运行数据,铁路非常长,所以要绘制的曲线也非常长,那是不是要把整条铁路的数据都分析完才能绘制曲线呢,显然不是这样,我们可以只绘制当前需要看到的数据,比如当前显示曲线的位置,从第几公里到第几公里,其它的一概略去。所以要显示流畅,就要使显示所要计算的数据量最少化,这是提高显示性能的主要途径。另外一个途径就是优化显示算法,这条就更加容易理解了,画一条线,使用系统画线函数一次画成,是最快的方法,利用系统画点函数一个点一个点地画上去,这是最笨的方法。

  要使画面变得平滑,第二条要务就是不要频繁刷新,而且要使刷新的画面之间的差别最小,如果在前一个0.1秒显示一张全白的画面,而后一个0.1秒显示一张全黒的画面,再一个0.1秒再显示回全白的画面,这时,人眼就会感觉的强烈的闪烁,让人很不舒服。如果中间插入的不是全黒的画面,而是灰白色的画面,人眼的感觉就会好很多,如果中间的画面再靠近白色一点,达到某一程度,人眼就会感觉不到闪烁了,这个实验说明,如果在显示画面时不去经常地刷新,或者在刷新的时候尽量使用和常显画面类似的画面,就会使显示平滑得多。VC里面有一个消息,就是擦除背景的消息(Erase Background),在这个消息里系统默认做的事情就是把所要擦除的背景区域置为黑色,这是造成画面闪烁的罪魁祸首。当程序需要改变画面时,系统就认为需要在改变画面的区域进行一次擦除,结果给人眼的感觉就是闪了一下,然后再把所要改变画面画上去。去掉这种擦除动作就会使画面平滑得多,也就是自己处理擦除背景消息,然后在这个消息处理函数里直接返回。

  现在说一说控件的显示,控件是一个固定的窗口,不需要我们去画它,哪怕是自己写的控件,也只能在控件实现的代码里绘制,而不能在显示控件的程序里去绘制。控件一般要使用MFC框架来开发,所以它的内部处理过程要比我们实现它所写的代码复杂得多,当它在窗口上显示出来,则会占用较多的时间,这个时间我们用肉眼感觉不出来,但是如果控件太多的话,它们一个一个显示出来,总共占用的时间我们就能明显地感觉出来了,那时就会看到画面明显的闪了一下。因为控件是窗口的一种,所以可以使用操作窗口的函数来对控件进行操作,比如MoveWindow之类的函数,凡是对窗口操作的函数,性能都非常的低,假如你在一次画面刷新过程中使用了几十次MoveWindow,就会很明显地感觉出卡来了。而恰恰有许多程序都需要频繁地使用MoveWindow,比如一个双色球程序,把双色球封装成一个控件,然后在一个界面中显示很多期的双色球,旁边有一个滚动条可以上下滚动,使用户可以浏览几十期,甚至上百期的内容。这里就得把这几百上千个小球控件来来回回地MoveWindow。如果不想想办法提高显示性能,效果不堪设想。

  我在一次实践中初步解决了这个问题,那就是将控件的样子绘制下来,复制到一个内存DC中,在滚动条挪动期间,只把内存DC中的控件画面粘贴到显示窗口中,因为相对于MoveWindow所带来的性能损失,在内存DC和窗口DC中来回拷贝图片所点的时间要少得多,可以说两者会差几个数量级,而且在刷新时不去擦除原有的画面,也进一步减少了闪烁。实际效果很好。

  Windows最基础的开发环境VC决定了有时候我们需要考虑很多,如果使用VB来做双色球程序,可以很快就可以完成,性能上可能就不尽如人意了,每一种开发工具都有它自己的特点,我们需要根据不同的需要来选择开发工具和编程语言,这是我们工作的准则,说不定哪天我们在开发一个网络程序时,会抛弃JAVA和PHP,而使用汇编来完成一个对性能要求非常苛刻的功能也说不定呢。

 

 


企业邮箱  |  法律公告  |  隐私保护  |  联系我们  |