Windows Embedded 系统应用软件框架设计
Windows Embedded 做为嵌入式系统(包含 Windows CE),实际实用的领域还是很多的,例如:
(1)(工业)控制
(2)医疗
(3)瘦客户机
(4)探测仪器一类
(5)车载
(6)电梯的轿内显示器
(7)PND
(8)测试仪表
工控领域,使用 Windows XP Embedded 的比较多,当然也有用到 Windows CE 系统。在消费类电子领域,如车载、PND等,使用 Windows CE 的产品比较多。
由于 Windows Embedded 系统的标准窗体界面无法满足车载及其它产品的需求,主要是因为用户在小屏幕的设备上操作系统提供的控件不方便。其实,在 PC 上也常见此种实现方式,例如:银行的一些客户终端,使用的是 Windows XP 系统,但从界面上是看不到系统提供的哪些控件,也感觉不到使用的是 Windows XP 系统。
一般使用 Windows Embedded 的产品都会采用自定义、个性化的 UI。UI 的实现方案也是千差万别,操作方便、美观是最基本的要求。其它如扩展性、稳定性等等要求,在设计时也是必须要考虑的。
整个框架暂且不说,比如功能的扩展性等,先简单说说 UI 最终的实现方法,即 UI 是如何呈现给用户的。
(1) 使用 GDI 贴图可能是大家最容易想到,是的,这确实是最通用的。其对系统的要求也比较低,不必考虑硬有件是否支持;
如果使用 GDI 感觉速度不能满足要求,可以参考通过显示驱动,直接写显存。这种方法,需要驱动人员配合,在定制系统时提供相应的接口,一般通过 IOControl 来实现。
(2) 为了实现一些特殊的效果,在产品方案支持的情况下使用 overlay 结合贴图,利用 overlay 的特性完成 UI 之间的快速切换。例如:使用以下 CPU 的方案Telechips、SiRF Prima、iMX,MStar785等使用 Overlay 是没有问题的;但 SiRF A5、MStar 2521等低端的 CPU 则不支持。
这两种方案,基本上都是使用 Windows Embedded 系统提供的功能。
(3) 使用诸如 Open GL ES 做出的支持较好的动画效果的 UI。
(4) 使用 Windows Embedded 新特性的 Silverlight 来实现的 UI 产品,现在也慢慢的出现在车载系统中。但使用 Silverlight 对系统的硬件配置要求比较高,现在也只出现在一些高端的产品中。
(5) 第三方工具或开源项目,例如:QT、MiniGUI。
接下来说说框架,在 Windows Embedded 下编程,怎么也逃脱不了 Windows 消息框架,至于是使用 MFC 还是使用 Win32 编程,那可以说是仁者见仁智者见智。但无论选用哪一种,它也只是一个基础。UI 框架如何设计,功能如何与 UI 完美的结合,以达到修改 UI 时尽可能不去关心功能代码?这也是 Silverlight 推出时的设计想法:UI 设计和实现,与功能的实现分开。这种分开,个人认为简单的说就是耦合度降到最低,不可能彻底分开的。UI 与功能之间一般通过消息、回调或定时等机制结合在一起。例如有一种使用定时刷新的 UI 方案,界面刷新的工作由一个独立的线程控制,定时检查各 UI 控件是否需要刷新、及如何刷新?功能模块在功能实现时,只需要触发控件的刷新标志即可。
例如如下刷新线程与功能代码:
1 // 刷新线程代码: 刷新各类型控件 2 while 3 { 4 // 字符串显示控件 5 foreach(各个字符串控件) 6 { 7 if(控件.bRefreshFlag) // 如果控件的刷新标志 8 { 9 控件.bRefreshFlag = FALSE; 10 // 刷新操作 11 } 12 } 13 // 按键控件 14 foreach(各个按键控件) 15 { 16 if(控件.bRefreshFlag) // 如果控件的刷新标志 17 { 18 控件.bRefreshFlag = FALSE; 19 // 刷新操作 20 } 21 } 22 // ...... // 其它类型控件 23 Sleep(50); 24 } 25 26 27 // 功能代码 28 // 功能: 字符串显示控件功能代码 29 // 参数说明: csStr 控件显示的字符串; bRefreshFlag 刷新控件标志 30 void StrSettingFunction(CString &csStr,BOOL &bRefreshFlag) 31 { 32 // 根据功能代码赋值新的字符串 33 CString csNewStr; 34 if(条件1) 35 csNewStr= L"XXX"; 36 else 37 csNewStr = L"YYY"; 38 if(csStr != csNewStr) 39 { 40 csStr = csNewStr; 41 bRefreshFlag = TRUE; // 赋值刷新标志 42 } 43 } 44 // 功能: 按键控件功能功能代码 45 // 参数说明: bEnable 按键使能标志(对应显示Enable/Disable图片); bSelect 按键按下或选中图片; bRefreshFlag 刷新标志 46 void BtnSettingFunction(BOOL &bEnable,BOOL &bSelect,BOOL &bRefreshFlag,...) 47 { 48 BOOL bNewEnable; 49 BOOL bNewSelect; 50 if(条件1) 51 bNewEnable = TRUE; 52 else 53 bNewEnable = FALSE; 54 if(条件2) 55 bNewSelect = TRUE; 56 else 57 bNewSelect = FALSE; 58 if(bEnable != bNewEnable) 59 { 60 bEnable = bNewEnable; 61 bRefreshFlag = TRUE; // 赋值刷新标志 62 } 63 if(bSelect != bNewSelect) 64 { 65 bSelect = bNewSelect; 66 bRefreshFlag = TRUE; // 赋值刷新标志 67 } 68 }
以上功能函数只是一个示例,例如:按键控件可能需要显示字符串,其必然包含一个与字符串显示类似的函数。各个控件都会有显示/隐藏属性,这个在功能代码中也需要体现出现。为了方便控件布局,一般都会支持子窗口,这是一个多个功能的集合。
将 UI 与功能分开,是框架设计的核心思路。分层的好坏,决定了后继开发与维护的难易程度。
如何使 UI 的设计具有简单、方便的移植性?这是大家在设计时都会考虑的内容。只所以这样考虑,是想在功能不变、或简单变化的情况下,能快速完成修改、且保证产品的稳定性。特别是一些车载方案公司,对于一些要求不高的小客户在快速确定 UI 后几天就可以完成产品的交付。这种修改,一般包括换图和图片位置的调整。如何简单有限的记录图片与图片的位置等信息呢?早在几年前,就有通过简单的格式化文本来完成的方案。后来标记语言兴起,在嵌入式方案中也得到广泛应用,特别是 XML 语言。XML 语言的特点这里就不多说了,有兴趣的童鞋在网络上查找一下,就能得到答案。在这些方案中,都有用到图片处理的技术,以实现透明、半透明等效果。图片一般采用 BMP 和 PNG 格式,为了方案的保密性等其它一些考虑,图片一般通过工具打包,甚至于,XML 文件也一起打包。这样在不了解打包后文件格式的情况下,客户就必须依赖于软件设计者。将 UI 部分通过可视化工具来实现,可以大大加快 UI 的开发速度。一般是通过 PC 上的程序来直接操作,刚刚毕业的学生在经过2到3天的培训,就可以完成 UI 部分的工作。
以上三部分结合在一起,就构成了车载应用系统中单个应用软件的框架:控件/子窗体/完整的界面。再给合一个对多个应用控制的逻辑,完成应用启动/关闭(显示/隐藏)等的控制,以完成一个完整的系统的设计实现。