|
2 实现GUI时存在的两个问题
; n" h: a& y3 t( ^* e* S: _ C本系统GUI的实现问题主要是各种图片的显示、动画和选择功能界面的实现。图片的显示方法很简单,因此,在下面只介绍动画和选择功能界面的实现方法及存在的问题。) M* j' H5 T& W" Y+ c7 |
2.1 动画的实现方法及存在的问题
+ m2 P& L, f5 MMiniGUI为实现动画,已提供了animation控件,用animation控件实现动画的过程非常简单:3 o' d% c9 @, ^/ z" E0 f& |, `
①准备动画文件,文件格式应该是GIF格式,GIF格式的动画文件可以用Flash和PhotoShop生成。
1 Z/ r$ @ ?: T0 `& |4 x②用函数CreateAnimationFromGIF89aFile()读入GIF文件。# {* ^2 ^; }# G" K7 [1 m4 ?
③用CreateWindow()创建动画显示窗口。
& R$ F! {) G- t+ T# w④用SendMessage()函数控制动画,该函数的第2个参数为ANM_STARTPLAY表示启动动画,参数为ANM_PLAYSTOP表示暂停动画。也可以用函数SendMessage(GetDlgItem(hInitface,IDC_MAINANIMATION),ANM_SETANIMATION,0,(LPARAM)anim)实现更换动画文件。但是,在嵌入式环境下,使用该方法播放动画时,在状态显示区和主显示区内都产生严重的抖动现象。而且屏幕越大抖动就越明显,分辨率为480×640时的抖动现象比240×320时更明显。减少动画的帧数或延长每一帧的播放时间,抖动仍然存在,严重影响屏幕的显示效果。
8 c: ^2 N9 L& W1 f& L( b1 V9 `, _1 s* T2.2 功能选择界面的实现及存在的问题
8 G E! A6 H$ u& ^功能选择界面一般由多个图片来组成,各表示不同的系统功能,用上下左右键选择不同的功能,按Enter键运行相应程序,即打开另一个窗口,完成相应功能。当关闭窗口时重新显示功能显示界面。为区别被选中功能和未选中功能,放大或下沉显示当前被选中的功能图片,而前一个被选中功能图片恢复成原来的大小,如图3所示。每次用上下左右键选择功能时和关闭功能窗口时,都要重新刷新背景,并重绘窗口客户区的各个图片。因为MiniGUI不保存被覆盖区域的内容,因此在MSG_PAINT消息中需要重绘的内容较多,重绘图片的常用方法是用FillB-oxWithBitmap()函数填充相应图片区域,但是这种方法加重了屏幕刷新负载,引起屏幕明显地闪烁。& U/ r S9 ~1 K% T9 ~
+ X6 R1 a& [7 k6 X' K [
3 关键问题的解决方法& X/ _( J# J# @) c- |# B5 ]
3.1 动画抖动问题的解决) p3 e1 z- ?# a5 [" c
产生动画抖动的主要原因是,用animation控件实现动画时,频繁地产生MSG_PAINT消息,加重了屏幕刷新的请求。MiniGUI通过判断窗口是否含有无效区域来确定是否需要重绘窗口。如果需要重绘就向应用程序发送MSG_PAINT消息。窗口的重绘任务需由应用程序自己完成,因为MiniGUI不保存被覆盖区域的内容。MiniGUI的窗口在响应MSG_PAINT消息的时候进行复杂的图形处理,尤其是在刷新时,对图像的擦除和重写造成了图像颜色的反差。当绘图消息的响应很频繁时,这种反差也就越发明显,于是我们就看到了动画抖动的现象。为了解决动画抖动的问题,系统采用了双缓冲技术和多个图片交替显示的方法。并在实际应用中证明了该方法是行之有效的。双缓冲技术要比直接操作显存速度更快,因此可以解决抖动现象。* M$ i# @. `$ B" O# }$ x
采用双缓冲技术实现动画的基本思路是这样的,首先在系统内存中建立一个类似显示内存的内存设备上行文,然后将待显示图片填充到该内存设备上行文中,最后再通过位拷贝方式复制到显示内存中。为了达到动画的效果,将多个图片循环显示,即设定定时器和静态变量,每当定时器触发时,根据静态变量的值显示不同的图片,静态变量由0到MAX循环。实现动画的详细流程如图4所示。定时器的时间间隔和图片的数量可以根据具体情况任意调整。本系统的主显示区动画采用这种方法实现后,动画效果流畅,不再有抖动现象。 / ?* {% S `$ P. h9 S' w5 v2 U
* K: H7 t5 i6 M! o7 V$ k5 o- s
4 H6 ?, |' |7 Q+ H! V3.2 功能选择界面闪烁问题的解决: X2 C( K1 j# _. Z
功能选择界面闪烁的主要原因是屏幕内容过多,刷新负载过大。本系统采用双缓冲技术和MiniGUI.cfg配置文件的设置方法,实现只刷新屏幕的局部,解决了功能选择界面闪烁问题。每次按上下左右键或关闭功能窗口时,用以下3个步骤实现重绘屏幕无效区域(以图3为例)。3 a( s1 N: N7 U0 j" I
①A区用小图标恢复,用函数StretchBlt(hdcmem,0,0,0,0,hdc,WIN_LEFT,WIN_TOP,WIDTH,HIGHT,(DWORD)0)实现,其中hdcmem是内存设备上下文,是用CreateCompatibleDCEx()函数创建的。该内存设备上行文中已经存有图3下图中的A区域信息(第一次是在窗口的MSG_ CREATE消息中保存的,第二次开始是在第二步骤保存的)。6 b4 q& t9 _3 Z* }$ b$ K8 r( b E4 n# U/ y. x
②将B的图片区域(小图片)复制到内存设备上下文,用函数StretchBlt(hdc,WIN_LEFT,WIN_TOP,WIDTH,HIGHT,hdcmem,0,0,0,0,(DWORD)0)实现。4 L+ u! J' t9 a2 w: _
③B区域的图片放大显示,通过函数FillBoxWithBitmap(hdc,WIN_LEFT,WIN_TOP,WIDTH,HIGHT,DESKIMAGE,&bitmap)实现。
5 f$ @# i. J4 z! z8 L' Q( {0 J$ U其中,WIN_LEFT、WIN_TOP、WIDTH和HIGHT分别表示图片放大显示区域的左、上坐标和宽、高。左、上坐标的定位公式如下:* s. H7 g: J/ ~/ R7 ]) F' @
WIN_LEFT=水平基准坐标+(i%DESKCOLS)×(BLTWIDTH+水平间隔)* {7 A; c* w1 E* w' [# b4 k1 u, K
WIN_TOP=垂直基准坐标+(i/DESKCOLS)×(BLTHIGHT+垂直间隔)
* i1 J2 u% D% p4 B式中,i表示第几个图片,DESKCOLS表示每一行的图片个数,BLTWIDTH和BLTHIGHT各表示图片区域的宽和高。为了减少屏幕刷新负载,不在MSG_PAINT消息中刷新背景,而是用MiniGUI.cfg配置文件中的bgpicture参数指定背景图,并在指定的目录中存放背景图文件。该参数在MiniGUI的4种渲染器中都有,即在不同的渲染器中,都可以用该方法,无需用代码去实现背景图的刷新。$ U% t% b" m' U1 h' ]% Y
|
|