适用于移动终端的GUI设计与实现
扫描二维码
随时随地手机看文章
在常见的移动终端等小型手持式设备上,由于硬件条件等的限制,我们看到的用户界面都非常简单,几乎看不到PC机上华丽美观的GUI 支持。随着硬件条件的提高,移动终端的嵌入式系统对轻量级GUI的需求会越来越迫切。
用户界面是指计算机与其使用者之间的对话接口[1],它为用户提供与应用系统交互的可视化通道,同时为程序员提供了一种编程模式,即GUI负责系统的可视化界面的生成、管理以及系统与用户之间的信息交互[2-3],而程序员只需专注于对实际应用的分析。
1. GUI在移动终端中的作用
图1显示大部分移动终端软件的系统架构,由图可以清晰看出,GUI在移动终端系统中扮演着很重要的角色,它运行在操作系统抽象层(OSAL)之上,为应用程序提供基于消息机制的图形用户界面编程接口。GUI与其它一些应用引擎一起为实现丰富的移动终端应用而提供支持,从而将应用程序的计算部分与界面分离开来,这样就充分保证了根据不同需求快速定制出功能强大界面丰富的应用程序界面。
图1 移动终端软件架构
2. GUI层次结构
从整体结构上看GUI是分层设计的,其主要成分为层次结构见图2,它的主要组成部分是 :显示驱动、GDI接口、消息队列和窗口管理四部分。
图2. GUI层次结构
2.1 显示驱动
显示设备和打印设备一同组成图形设备,图形设备抽象层(GAL)定义了一组不依赖于任何特殊硬件的抽象接口,所有顶层的图形操作都建立在抽象接口之上。而用于实现这一抽象接口的底层代码类似操作系统中的驱动程序。
显示设备驱动作为GUI最底层驱动,通过显示设备驱动程序接口(DDI)给上层GDI函数一些基础的功能和设施。可以看成是GDI的图形驱动程序,并将底层图形设备和上层接口分离开来。
DDI用GAL中的函数标准结构表示,统一成标准的驱动接口结构,保证显示对窗口透明。主要DDI函数包括:对显示设备进行初始化,管理显示内存使用和为上层GDI提供映射到物理地址空间以及诸如调色板等物理地址上的相关处理。
2.2 GDI接口
GUI系统的一个重要组成部分就是GDI,即图形设备接口(Graphics Device Interface)。通过GDI,GUI程序就可以在计算机屏幕上,或者其他的显示设备上进行图形输出,包括基本绘图和文本输出。
GDI重要函数包括:图形设备上下文管理、绘图函数和使用GDI对象的函数
2.2.1图形设备上下文管理函数[!--empirenews.page--]
要在图形输出设备上绘制图形,在调用图形输出函数时,均要求指定经初始化的图形设备上下文(Device Context,DC),也称作"设备环境"。设备上下文是连接应用程序、设备驱动程序以及输出设备的纽带,见图3。设备上下文包含许多属性,当需要修改这些属性时,只需调用一个GDI函数修改设备上下文中属性的参数。
图3. 设备上下文
一个图形设备上下文所代表的含义很复杂,它起码应该包含如下内容[5]:
· 该设备上下文本所在设备信息(显示模式、色彩深度、显存布局等等);
· 该设备上下文所代表的窗口以及该窗口被其他窗口剪切的信息
· 该设备上下文的基本操作对象(笔、刷子、字体、位图、区域等),及其上下文信息;
· 由程序设定的局部信息(绘图属性、映射关系和局部剪切域等)。
2.2.2 绘图函数
设备上下文的属性决定了有关绘图函数如何工作的细节。通过绘图函数应用程序能够方便地画出直线、矩形、圆、椭圆和其它复杂图形,而不需直接与具体的输出设备打交道。
2.2.3使用GDI对象的函数
当调用绘图函数时,使用当前设备上下文中选择的GDI对象来进行绘图。GDI共有笔、刷子、字体、位图、区域和逻辑调色板六个对象。
例如可以通过在CreatePen、 CreatePenIndirect或ExtCreatePen函数中指定这些特征来建立一个逻辑画笔,这些函数传回一个逻辑画笔的句柄。要使用这个画笔,就要用SelectObject将画笔句柄选进设备内容。这样,画任何线都使用这个画笔,然后可以取消设备内容中的画笔选择,并清除画笔对象。清除画笔对象是必要的,因为画笔定义占用了分配的内存空间。
除了画笔以外,GDI对象还用于建立填入封闭区域的画刷、字体、位图以及GDI的其它一些方面。
2.3 消息队列
移动终端产生的消息主要包括:按键事件消息、协议栈消息及自定义消息等。按键一般有12个标准电话按键、左右2个软键、5个导航键(上、下、左、右、中) 、拨号键和挂机键,由此可产生对应的短按键及长按键消息。按键的按下及释放产生按键事件,对比键码表对按键事件进行解码,获取正确的按键消息。按键消息经消息过滤后送往当前焦点窗口。GSM 协议栈消息是由手机平台产生的送往消息队列的协议栈消息,主要是网络事件及手机状态的响应消息,包括所有对SIM卡、网络状态、通话、短消息等的响应消息。协议栈消息需传送到赋于系统窗口属性的窗口,但窗口并不需要对每一项协议栈消息进行处理,只依据窗口函数的具体属性定义进行消息响应。
GUI采用消息驱动机制,把上面这些消息收集在一个消息队列中,然后将这些消息连同定时器和重画消息一起放入应用程序消息队列中。应用程序消息队列是属于各个应用程序所有的先进先出队列。但是定时器消息和重画消息保留在队列中直到应用程序处理完所有其它消息后才予以处理。GUI将属于一个特定应用程序的消息放入该应用程序的消息队列中,然后应用程序读取这些消息,并将它们发送给相应的窗口函数。[!--empirenews.page--]
GUI将某些消息直接发送给应用程序的窗口函数,而不是将它们放入到应用程序队列中,这样的消息称为非排队消息。通常,非排队消息是那些仅影响该窗口的消息。虽然大多数消息都由GUI产生,但应用程序也可以产生自己的消息并将其加入到应用程序队列中。
一旦应用程序的主函数从队列中获取了消息,就可以将消息传送给相关窗口的窗口函数,并把消息的内容作为参数传递过去,这样,窗口函数就可以处理这个消息,完成相应的工作。当窗口函数返回后,GUI将控制权返回给主函数。主函数可以再从队列中取出下一消息进行处理。
2.4 窗口管理
窗口是终端应用程序的主要输入输出设备。应用程序只有通过窗口才能访问显示设备。窗口由标题条、菜单条、滚动条、边框以及在显示设备上的矩形框里出现的其它特性组成。当创建窗口时,可为窗口指定所要求的特性,然后GUI画出此窗口并管理它。
虽然应用程序创建了某一窗口,并且从技术上来说可以独占它,但该窗口的管理实际上是由应用程序与GUI相互协作来实现的。GUI管理窗口的位置和显示方式,并管理窗口的标准特性,如边框、标题等,同时完成许多由用户初始化并直接影响窗口的任务。而应用程序则管理窗口的其它所有工作,特别是负责管理窗口的“客户区”(窗口边框以内的区域)。应用程序可完全控制属于自己的窗口客户区的显示。
为管理这一协作任务,GUI告知每个窗口其变化可能要受到影响。因此,每个窗口必须具有相应的“窗口函数”,用于接收窗口管理消息。窗口管理消息既可指定该函数要执行的动作,也可请求该窗口函数返回信息。
窗口函数作为窗口最重要的基本属性,处理所有传送到本窗口的消息。窗口的表现及行为特征是由窗口函数定义的对消息的处理所决定的。在正常情况下,具体的窗口函数只处理部分指定的消息,而正是这部分特定消息的处理决定了各个窗口的不同特性。通过调用窗口函数,将消息参数传递到所指定的窗口函数,由窗口函数依据消息所携带的消息参数进行判断处理。对绝大部分消息只需将其送往缺省窗口函数进行处理。缺省窗口函数集成了标准窗口函数对消息的标准处理,是对所有窗口函数的一个共性集合窗口管理收集所有的输入信息,然后把这些输入信息以消息的形式送往合适的窗口。这些消息的执行结果又可能产生新的消息,新消息的传送仍由窗口管理负责。窗口管理通过调用窗口函数,向窗口函数传递消息参数,把消息送到目的窗口。在移动终端中,采用消息分派技术将协议栈消息依次发往所有具有系统属性的窗口。通过窗口树表将非协议栈消息送往所获取的当前焦点窗口。
3. GUI调用流程
下面通过一个具体例子分析GUI函数调用流程:移动终端的窗口系统初始化时首先要创建一个菜单,在注册菜单窗口类时将菜单序号图片全部按顺序读入内存,这就需要GDI用画刷对象来进行矩形填充,下图清晰的显示了GUI在注册这个窗口类时各层调用的流程。
图4. GUI调用流程
4. 结语
GUI系统是一项复杂的软件工程,本文设计和实现的GUI占用资源少、可配置,特别适用于移动终端。它给终端上层应用提供了一个清晰的图形界面。同时,在将它用于多种终端平台时还要尽可能考虑它的可扩展性、兼容性、可移植性等属性。