嵌入式Linux下的图形用户界面系统设计

时间:2014-06-18来源:网络

2. 4. 1窗口的定义

SKY-GUI中,窗口既包含桌面、对话框这种狭义的窗口,也包含窗口控件(如按钮、下拉菜单、编辑框等等)这样的广义窗口,其定义为:

typedef struct __WINDOW {

STR32 caption; / /窗口的名称

RECT rect; / /窗口的大小、位置

int style; / /窗口的类型

MsgQueue* pMsgQ; / /附属于窗口的消息队列

struct __WINDOW*pFocus; / /活动窗口指针

struct __WINDOW*pParent; / /父窗口指针

struct __WINDOW*pChldHead; / /子窗口列表

struct __WINDOW*pNext; / /兄弟窗口或控件指针

struct __WINDOW*pCtrlHead; / /控件列表

WNDPROC WndProc; / /消息处理函数指针

void* data1; / /窗口私有数据

void* data2; / /窗口私有数据

void* data3; / /窗口私有数据

int msg1; / /窗口状态变化消息

} WINDOW;

caption为窗口的名称;rect为保存窗口位置和大小的矩形;style为窗口的类型;pMsgQ为窗口的消息队列的指针;pFocus指向当前窗口的活动子窗口或控件;pParent指向当前窗口的父窗口;pNext指向当前窗口的兄弟窗口;pChldHead用来保存当前窗口的子窗口列表;pCtrlHead保存当前窗口的控件列表。WndProc指向当前窗口的消息处理函数;data1、data2、data3为窗口的私有数据,msg1为窗口状态变化时需要发出的控件消息,它们的意义根据窗口的类型而定。

从窗口的定义可以看出,本文要实现的是一种树形的窗口关系,整个系统可以拥有一个或多个主窗口,每个主窗口拥有自己的控件和子窗口,而子窗口又可以拥有各自的子窗口和控件,依此类推。

2. 4. 2窗口与消息队列的关系

窗口定义中含有指向消息队列的指针,但并不是所有的窗口都有自己的消息队列。主窗口(如桌面)需要随时呈现在用户的面前,可以拥有自己的消息队列;其他的子窗口、控件则没有必要拥有自己的消息队列。这两类窗口用不同的方式使用事件系统。

拥有消息队列的主窗口必须拥有自己独立的线程,其消息发送和处理的流程如图5所示。

 

 

图5拥有消息队列的窗口的消息发送和处理流程。

当其他窗口或输入抽象层需要操作主窗口时,就调用事件系统中的Post_Msg或Send_Msg函数向该窗口的消息队列发送一个消息。而主窗口得知有消息输入,就调用事件系统中的Get_Msg函数取出消息,并使用Dispatch_Msg调用自己的消息处理函数,找到相应的事件处理方法处理事务。这种消息传递的特点是消息的发送和处理分别在不同的窗口线程中完成,一般用于两个主窗口之间或者输入抽象层和主窗口之间的消息通信。

没有消息队列的子窗口或控件处理消息的流程如图6所示。

 

 

图6没有消息队列的窗口的消息处理流程

主窗口调用事件系统中的Post_Msg或Send_Msg函数向子窗口或控件发送消息,由于该窗口没有自己的消息队列,事件系统不会将该消息保存,而是直接调用该窗口的消息处理函数找到具体的事件处理方式完成这次窗口操作。这种消息传递方式中,发送消息和处理消息都在主窗口的线程中完成,向一个窗口发送消息相当于要求该窗口立刻对事件进行处理。

SKY-GUI只设置了一个主窗口,即桌面。其他所有的窗口或对话框都作为桌面的子窗口而存在。

这样系统中只有一个窗口线程和一个消息队列,第一种消息处理方式只存在于输入抽象层和桌面之间,而窗口之间的消息处理都采用第二种方式,这样系统的线程开销和消息循环开销会大大减少,从而提高其运行效率。

2. 4. 3窗口之间的消息传递

窗口之间的消息传递根据消息类型的不同有两种不同方式。

主窗口从消息队列中取得的消息在SKY-GUI中称为底层消息。这类消息是由主窗口处理,还是交给子窗口或是控件处理,是根据窗口定义中的pFocus变量而定的。当一个窗口的pFocus不为空时,表示该窗口上方有子窗口被用户使用,消息应该交给它指向的子窗口处理,而这个子窗口也检查自己的pFocus变量,依此类推;只有当一个窗口的pFocus为空,表示该窗口位于屏幕的最上方,得到的底层消息由窗口自身处理(如图7左边流程)。

而当控件的状态变化产生控件消息时,其消息处理的过程正好跟上面的流程相反。控件产生的消息首先由自己处理,有必要时再送给pParent指针指向的父窗口处理,而后还有必要的话再送给父窗口的父窗口处理,最后也可以由主窗口送入消息队列(如图7右边流程)。

 

 

图7从消息队列读出的消息处理流程(左)和控件产生的消息处理流程(右)。

pFocus变量和pParent变量加上这样树形的窗口系统实质上是实现了很多GUI系统中的窗口的Z序[6](窗口的上下顺序)功能。该功能是建立在子窗口显示在其父窗口之上,且控件显示在其所属窗口之上的思想上的。由于底层消息一般代表用户对输入设备的操作,所以应该送给位于屏幕最上方的用户正在使用的窗口处理,而控件消息一般代表着GUI界面自上而下的图形和数据变化过程,所以应该从上到下逐层处理。

3实验和测试

SKY-GUI现已嵌入已有的视频监控系统项目中予以使用,它有下拉菜单、输入框、密码框、按钮、软键盘等十几种控件,提供视频监控的操控界面和配置界面。其中的一个典型的界面如图8所示。

 

 

图8 SKY-GUI在视频监控系统中的典型界面。

为了测试其的性能,本文利用SKY-GUI和开源的Qt界面库分别为视频监控系统制作了一套用户界面,其参数对比如表1所示。

表1 SKY-GUI与Qt在视频监控系统中的性能比较。

 

 

很显然,Qt在嵌入式监控系统中占用资源过多,导致其运行速度缓慢并影响到系统的正常编解码。

而SKY-GUI加上其所需的开源图片和字体库大小也不超过1 M,运行时只占用4 M左右的内存,这在典型的嵌入式Linux系统中完全可以接受,也不会影响到监控系统本身的性能。可以看出,Qt要运用在该监控系统中还需进行更深层次的剪裁和性能优化,而SKY-GUI则可满足其对界面的功能和性能需求。

4总结

本文描述了一种嵌入式Linux平台下GUI的设计方案。实验证明此设计方案可行,可以满足一般嵌入式平台上的图形界面要求。

1 2

关键词: Linux GUI

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版