描述

嵌入式图形用户界面( GUI, Graphic UserInterface)系统作为嵌入式系统中的一大关键技术,为用户提供设备的控制接口,其性能的好坏,界面的美观程度,影响着用户对产品的购买意愿和使用感受。

当前嵌入式系统中GUI 的实现方式主要有两种:一是采用现有的GUI 库;第二种是开发商基于嵌入式操作系统设计特有的GUI 系统。采用第1种方式一般要对通用GUI 库进行剪裁和个性化定制,也往往要支出额外的成本来获得软件授权。相对而言,第2 种方法实现的GUI 占用资源较小、容易满足嵌入式系统的实时性和个性化需求。

本文采用第2 种方式,在嵌入式Linux下使用C 语言实现了一个界面美观、轻量级、占用资源少、执行效率高的图形用户界面系统SKY-GUI.本文的结构如下:第1 部分介绍SKY-GUI 的基本结构;第2部分给出具体的模块设计;第3 部分给出其实验和测试结果;最后总结。

1 SKY-GUI 基本结构

SKY-GUI 系统的功能主要有以下四点:

(1)接收各种输入设备的输入。

(2)建立消息循环,将设备的输入翻译为抽象的事件。

(3)建立窗口和控件对象系统,组织好各个抽象模块的关系,处理各种GUI 事件。

(4)将GUI 对象通过具体形状显示在屏幕上,通过动画将系统的状态变化呈现给用户。

基于这样的设计目标,SKY-GUI 结构如图1 所示。

图1 SKY-GUI 的整体架构

它主要由输入抽象层、显示抽象层、事件系统和窗口系统四大部分组成。输入抽象层管理所有的输入设备,将用户的操作转化成消息送入事件系统。

显示抽象层操作显示设备,提供给窗口系统绘画、贴图、显示字体接口。事件系统为窗口系统提供消息获取、存储和处理的机制。窗口系统是SKY-GUI 的核心,定义了各种控件和窗口,描述它们之间的逻辑关系和消息循环关系。下面将分别对这四大组成部分的设计进行介绍。

2 SKY-GUI 模块设计

2. 1 输入抽象层

输入抽象层为各种输入设备对事件系统的输入接口,它是一个单独的线程,其流程如图2 所示。

图2 输入抽象层流程。

输入抽象层首先对GUI 所需的各种输入设备初始化,而后等待各个设备的输入。当接到设备输入,就把用户对设备的操作翻译成消息,送至事件系统最底层消息队列(在异2. 3. 2 详细讨论)中。

设备输入的翻译过程根据具体的输入设备而定。对于键盘,只要将其键值和该键的状态封成消息。对于鼠标,除了要记录其按键状态,还要根据鼠标当前的位置和屏幕的大小将输入的位移分量转化成鼠标的新位置封入消息。

2. 2 显示抽象层

显示抽象层的作用是为窗口系统提供显示接口函数,包括基本图形接口(画点、画线、填充矩形、区域拷贝、Alpha 混合等)、贴图接口和字体接口三大功能,其结构如图3 所示。

图3 显示抽象层的结构。

显示抽象层在嵌入式Linux 下的基础设备为帧缓冲,对其按坐标写入或读出颜色值即可实现基本的图形接口的功能。

简单的贴图功能用基本图形接口加bmp 格式的文件(图片不经过压缩,其颜色分量按坐标顺序存储)就可以实现。为了让界面更加美观,SKY-GUI移植了开源的jpeg 库和png 库来解压相应格式的压缩图片文件,实现了对这两种图片格式的支持。

对字体的支持当然必不可少。点阵字体把字体的位图按12伊12、16伊16 等格式存入二进制文件,可以比较容易地实现字体接口,但字体不能随意放大缩小,且放大后字体有明显的锯齿。矢量字体用数学方程加字形上的关键点来描述字体,可以进行无级缩放,为界面的绘制带来极大的灵活性。SKY-GUI 移植了开源的Freetype 库,用其寻址矢量字体文件并生成字体位图,实现了对矢量字体的支持。

2. 3 事件系统

事件系统为SKY-GUI 的其他三大部分提供消息发送、存储、获取和处理的功能。其核心为消息、消息队列和消息处理函数。

2. 3. 1 消息定义

SKY-GUI 的消息定义为:

typedef STruct __MSG {

HWND hWnd;摇/ / 窗口指针

int event;摇/ / 事件编号

void* wParam;摇/ / 事件附加参数1

void* lParam;摇/ / 事件附加参数2

} MSG;

hWnd 为指向窗口的指针,表明此消息需要发给哪个窗口。event 为事件编号,用不同的整数代表不同的事件。wParam 和lParam 为事件的附加参数,它们的含义根据事件类型的不同而定,例如,在鼠标消息中这两个参数就代表光标在屏幕上的坐标位置。

2. 3. 2 消息队列

消息队列是事件系统中的消息的暂存处,它由一个环形先入先出结构的消息数组和一个消息链表组成。消息数组的空间是固定的,一旦被写满,后来的消息只好被丢弃;而消息链表则可以动态扩充大小。在SKY-GUI 中,消息数组主要用来存放底层输入设备的事件(如鼠标、键盘、时钟等等),而消息链表主要用来存放优先级更高且不可丢弃的上层事件(窗口事件和显示事件)。

2. 3. 3 消息操作接口

SKY-GUI 定义了三类消息操作接口:消息发送函数、消息获取函数和事件处理函数。

消息发送函数为输入抽象层和窗口系统提供消息发送接口,包括Post_Msg 函数和Send_Msg 函数,其作用都是向消息队列发送消息,不同之处在于Post_Msg 发送的消息存入消息队列的数组之中,而Send_Msg 发送的消息则存入链表之中。

消息获取函数为Get_Msg 函数,它为窗口提供取得消息的接口。拥有独立线程的窗口( 异2. 4 会描述其结构) 调用它从消息队列中取得一个消息,其中存在链表中的消息更为重要,优先取出。

事件处理函数是窗口处理消息事件的函数接口,在SKY-GUI 中,拥有独立线程的窗口调用Dispatch_Msg 函数来实现对自己消息处理函数的调用。

2. 3. 4 消息处理函数

Dispatch_Msg 只是事件处理的调用接口,窗口收到消息后所采取的具体措施是由消息处理函数决定的,其定义为:

int WndProc ( HWND hwnd, int event, void *wParam,void* lParam);

每一个窗口都有一个函数指针指向自己的消息处理函数,其功能根据不同的窗口有所不同,但总体结构是一样的,如图4 所示。

图4 消息处理函数的结构

其本质上是一个消息处理的分类列表。当窗口调用消息处理函数时,其根据消息类型的不同分别调用底层输入消息、控件消息或显示消息的处理函数,而后再根据具体的消息事件调用相应的处理函数,实现对各种事件的响应。

2. 4 窗口系统

窗口系统为SKY-GUI 系统的核心,它维护了一个完整的窗口列表,定义了窗口系统和事件系统之间的关系,并制定了窗口之间的消息传递机制。

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 的设计方案。实验证明此设计方案可行,可以满足一般嵌入式平台上的图形界面要求。

打开APP精彩内容

点击阅读全文

嵌入式linux界面开发,基于嵌入式Linux平台实现GUI系统的设计方案相关推荐

  1. Java实现旅游app_基于安卓Android平台的旅游系统APP的设计(Eclipse,MySQL)

    基于安卓Android平台的旅游系统APP的设计(Eclipse,MySQL)(任务书,开题报告,论文15700字,程序代码) 摘  要 随着手机使用的普及,人们获取与保存信息的方式已经发生了激动人心 ...

  2. 业务“多面手”,基于低代码平台的CRM系统

    编者按:本文介绍了CRM系统的概念和作用,并指出基于低代码平台的CRM系统可以更好地满足企业业务多样化需求,最后介绍了相关低代码平台. 概要: (1)CRM系统的概念及作用 (2)基于低代码平台的CR ...

  3. linux复现数据库,基于嵌入式Linux系统平台并可应用于监控组态软件实时数据库的设计方案详解...

    1 引言 实时数据库(real-me database, RTDB)作为组态软件设计与实现的核心内容解决了其所 应对的现代工业生产现场环境中生产数据与控制数据类型复杂多样,数据处理与事件调度时 间约束 ...

  4. 嵌入式基于Linux电机控制,基于嵌入式arm+linux平台的直流电机调速控制系统.pdf

    2012--2013 学年第 二 学期 物电 学院期末考试卷 嵌入式系统与应用 学号 : 姓名 : 班级 : 成绩: 评语: 装 订 (考试题目及要求) 嵌入式大作: 采用实验箱上的电位器作为信号输入 ...

  5. 嵌入式linux矩阵键盘,基于嵌入式Linux的矩阵键盘驱动程序开发

    O 引 言 随着以计算机技术.通信技术和软件技术为核心的信息技术的发展,嵌入式系统在各个行业中得到了广泛的应用.嵌入式系统已成为当今IT行业的焦点之一.而在嵌入式系统中,键盘是重要的人机交互设备之一. ...

  6. 嵌入式linux程序加密,基于嵌入式操作系统uClinux实现网络安全加密系统的设计

    金融安全支付系统是专门针对金融领域应用需求,实现小型化.便捷.安全的自助交易的软硬件平台,能够为多种应用提供高速安全服务,解决目前交易信息在传输过程中存在的各种安全问题,实现金融信息的安全交易.基于该 ...

  7. iptv linux 安卓 盒子,基于嵌入式Linux的IPTV机顶盒设计

    摘要: 随着人们生活水平的提高和Internet技术的发展,IPTV开始走进人们的生活,IPTV是一种集网络.多媒体.通讯等多种技术于一体,向用户提供包括数字电视在内的多种交互式服务的崭新技术.作为I ...

  8. 嵌入式linux电子设计,基于嵌入式Linux的PMP系统设计与实现

    PMP系统简介 便携式多媒体播放器(PMP),也就是通常人们所说的MP4,已成为继MP3以后消费类产品的一个新热点.PMP的主要优点是:携带方便,能够直接播放高品质音/视频文件:也可以浏览图片,以及作 ...

  9. linux移动数据,基于嵌入式Linux移动数据同步研究与实现

    内容介绍 基于嵌入式Linux移动数据同步研究与实现 1.5万字 39页 资料压缩包内包括开题报告,任务书,答辩PPT,论文正文,程序代码,资料内容完整,推荐下载! 摘要 数据同步是移动计算中一种重要 ...

最新文章

  1. 关于手风琴效果延迟执行解决方式
  2. 应云而生,幽灵的威胁 - 云原生应用交付与运维的思考
  3. 基于ARM+DSP进行应用开发-经验共享
  4. hdu1166 敌兵布阵 线段树
  5. Docker基本使用方法(build image \run...)
  6. 借鉴一下人家辞职申请
  7. ansys与solidworks关联失败,将SolidWorks模型导入ansys划分网格总是提示错误
  8. Excel操作:分析工具库
  9. 【Linux】Linux基本操作指令
  10. python 解压zip rar 7z文件
  11. 去阿诗玛的故乡 云南昆明自助攻略
  12. 树莓派人脸打卡机(考勤机)(Python)
  13. 1436:数列分段II
  14. 【已解决】Activity MainActivity has leaked window PhoneWindow$DecorView@ that was originally added here
  15. 计算机管理 存储空间不足,win10系统提示“存储空间不足无法处理此命令”的处理技巧...
  16. 块级、内联、内联块级
  17. child计算机英语作文,Childhood的英语作文(精选8篇)
  18. 固定资产管理系统提升企业固定资产管理效率
  19. 利用 Python 对某网上商城进行战略分析
  20. Vidmore Video Converter for mac(Mac视频转换器)

热门文章

  1. 为树莓派增加MIDI接口
  2. Ice飞冰《配置总结》
  3. App在后台被杀死后重启-重进首页方法
  4. 【好题分享】适合C++初学者(数组的定义与初始化)
  5. 如何用python处理文件(图文详解)
  6. scsi 教程 linux,SCSI存储详解以及Linux下ISCSI的实现
  7. SystemC自带example的pipe研习
  8. linux虚拟主机用织梦,织梦程序用什么虚拟主机好
  9. 从 sourcemap 中获取源码
  10. HRBUST1313-火影忍者之~静音