关键词:MicroWindows API Nano-X 图形用户界面
许多开发者在嵌入式设计中开始使用类似于桌面的操作系统。其中一个方案就是Linux操作系统。由于Linux在嵌入式系统上具有桌面电脑的全部功能和特性,作为一种免费的开放源码,它允许修改和根据用户的要求进行定制。
MicroWindows是一个开放源码的嵌入式GUI软件,目的是把图形视窗环境引入到运行Linux的小型设备和平台上。作为X Window系统的替代品,MicroWindows可以用更少的RAM和文件存储空间(100KB~600KB)提供相似的功能,允许设计得轻松加入各种显示设备、鼠标、触摸屏和键盘等;可移植性非常好,可用C语言实现;支持Intel 16位/32位CPU、MIPS R4000以及基于ARM内核的处理器芯片。
1 体系结构
1.1 分层结构设计
MicroWindows采用分层结构设计方法,在底层提供对屏幕、鼠标、触摸屏和键盘的驱动,在程序能访问实际的硬件设备和其它用户定制设备。在中间层有一个可移植图形引擎,提供绘制线程、区域填充、绘制多边形、裁减和使用颜色模式的方法。在顶层实现多种API以适应不同的应用环境。目前,MicroWindows中使用两种流行的图形编程接口:Microsoft Windows Win32/WinCE图形显示接口(GDI)和Xlib接口。前者应用于所有的Windows CE和Win32应用程序;后者就像Nano-X,应用于所有Linux X插件集的最底层,这样可让Linux图形程序员X接口开发图形应用程序。
1.2 驱动设备
device.h文件中定义设备驱动接口。MicroWindows已实现至少将一个屏幕、鼠标和键盘的驱动与系统相连。独立图形设备引擎的中间层可以使驱动设备直接完成对硬件的具体操作。
(1)屏幕驱动
MicroWindows可运行在支持Framebuffer的32位Linux系统上,也可使用SVGALib[45]库来进行图形显示。此外,还被移植到16位的ELKS和实模式的MSDOS上,实现1、2、4、8、16和32位的像素支持,以及实现VGA16平面模式支持。它的图形引擎能够运行在任何支持readpixel、writepixel、drawhorzline、drawvertline和setpalette的系统之上。如果底层驱动系统实现了Blitting,则上层可提供更多的增强功能。在底层函数的支持之下,上层实现了对位图、字体、光标以及颜色的支持。除了基于调色板的1、2、4和8位像素模式,也实现15、16和32位像素的真彩模式。
(2)鼠标驱动
MicroWindows有三个鼠标驱动程序。GPM驱动程序mou_gpm.c支持Linux系统,串口鼠标驱动程序mou_ser.c支持Linux和ELKS系统,int33驱动程序mou_dos.c支持MSDOS系统。鼠标驱动程序的基本功能,是将鼠标中的数据编码,然后返回关于鼠标位置和按键的相对或绝对数据。
在Linux下,MicroWindows的主循环是select()声明,如果运行的系统不支持select(),MicroWindows则提供Poll()入口。
(3)键盘驱动
MicroWindows提供两个键盘驱动程序:Kbd_tty.c适用于Linux和ELKS系统,键盘被当成文件描述符来读写;Kbd_bios.c用于MSDOS真彩模式下,它是对PC BIOS进行读写来对按键进行操作。
1.3 MicroGUI——独立图形设备引擎
MicroWindows的MicroGUI提供了对屏幕、鼠标、键盘驱动程序和硬件之间的接口。用户应用程序不能直接调用核心图形引擎,但是可通过API函数来实现。核心程序在客户机/服务器模型下常驻在服务器上,使用内部的文本字体和位图文本模式。此外,核心程序使用的是指针,这样不用靠转变成句柄来实现更多的复杂功能。
MicroWindows中的核心程序以GdXXX()开头,与之相连的是图形输出系统而不是窗口管理系统。此外,还控制所有的裁剪和颜色转换功能。以下是组成MicroWindows核心模块的文件:
dvdraw.c——核心图形程序,关于绘制线段、圆、多边形及其填充,文本和位图文件的绘制和颜色转换;
devclip.c——核心裁剪程序;
devrgn.c——动态分配程序;
devmouse.c——鼠标控制程序;
devkbd.c——核心键盘控制程序;
devpalX.c——连接到系统调色板。
1.4 应用程序接口
MicroWindows提供两个应用程序接口:MicroWindows API(源代码在win*.c中)和Nano_XAPI(源代码在nanox*.c中)
在MicroWidows上的API函数的基本模型都是用来初始化屏幕、键盘和鼠标的驱动程序,然后一直等待select()消息循环。当事件发生时,这条信息将送到用户程序。如果是用户请求图形操作,那参数将被编码后送到适当的GdXXX核心程序上。与原始图形操作相对的窗口概念是被该层所控制的,也就是说该层的API函数定义了窗口及其对应系统的概念。这样,系统坐标就能被转成屏幕上显示的坐标,并且可将数据传给GdXXX核心程序,由其作实际操作。该层亦定义图形/显示文件,并且会将此信息包括裁减信息送到核心程序上。
MicroWindows API支持大多数图形绘制、裁减、窗口工具条绘制以及拖拉窗口等这些程序。Nano_x API以mini-X服务器基础,类似于X的一个API,沿用X Window中的Xlib API,命名都是GrXXX()而不是X Windows中的X)。Nano-x API加入了基于网络的客户机/服务器功能,但是没有实现窗口管理,所以对窗口的处理需要使用系统提供的一个插件(widget)集,或者完全由应用程序员自已开发。
2 图形引擎特性与实现
图形引擎层的功能是完成图形在实虚屏之间的转换,以Gd...为开头,并将指针传给PSD作为它的首个参数。PSD参数将指定底层的显示模式,例如设备的垂直和水平尺寸、硬件使用的颜色模式。另外,真正执行画图的程序在这一层中作为功能指针使用。所有屏幕坐标都是COORD类型。
颜色在图形引擎中被指定RGB CILORVAL模式,然后被转换成颜色指针,以PIXELVAL模式传给显示硬件,在32bpp(bit per pixel)真彩显示器环境下不必转换。
(1)区域
区域用来描述屏幕上像素点的分布。在MicroWindows中,区域是用一些无交迭的矩形组成的数组来描述的。目前实现区域有两种方法,最初是用一个静态数组CLIPRECTs来描述复杂区域。在这个数组中任一矩形中的点都被认为是存在这个区域中的,另一个全局变量clipcount用来给这个数组中的矩形计数。这个方法没有给区域管理提供入口点,所以整个数组的数据直接被送到负责裁剪功能的函数数口。新方法则可以创建任何数目的区域。用来描述区域的数组CLIPREGION被定义成动态数据组,可动态分配它所包含矩形的数量,这样那些无交迭的矩形被存放在“y-x”类型的队列中。在同一队列中,所有矩形的垂直高度y是一样的,这意味着在每个队列中只有矩形的宽度可变。实际程序是利用Intersection、Union、Subtraction、Exclusive OR等方法来实现创建、删除一个区域或者是将几个区域或矩形合并。以下是这种方法设计的几个函数。
GdAllocRegion 创建一个区域
GdDestroyRegion 删除一个区域
GdCopyRegion 复制区域
GdUnionRectWithRegion 将一个矩形和一个区域合并
GdIntersectRegion 在两个区域的交集处创建一个新区域
GdSubtractRegion 在两个区域的差集处创建一个新区域
GdUnionRegion 在两个区域的并集创建一个新区域
GdXorRegion
(2)裁剪
图形引擎中有一个由图形操作定义的由一些矩形组成的裁剪区,如果点被包含在这些裁减区内就会被绘制出来。有两个裁剪算法:devclipl.c针对静态矩形数组,devclipc2.c针对新的动态数组。GdSetClipRects是唯一删除区域并指定后来的图形操作的入口点。所有的绘图程序都要调用两个附加程序来决定是否画图。GdClipPoint获取屏幕坐标的(x,y)点,如果该点被绘制出来的话,则返回TRUE。GdClipArea获取屏幕上方最左的或者下方最右的点并回以下值:CLIP_VISIBLE(指定区域在原区域内)、CLIP_INVISIBLE(指定区域不在原区域内)、CLIP_PARTIAL(指定区域部分在原区域内)。
(3)画线
MicroWindows使用GdPoint画点,GdLine画线。画线时使用当前的前景色(DgSetForeground指定)。有两种绘制模式:MODE_SET和MODE_COR。
(4)矩形、圆和椭圆以及多边形
矩形、圆和椭圆的绘制分别调用GdRect和GdEllipse来实现。MicroWindows中定义了一个包含(x,y)多边形顶点的数组来表示多边形,调用GdLine函数画线,把这些点相连就可以实现画多边形。绘制时使用前景色。
(5)区域填充
MicroWindows中使用GdFillRect函数填充矩形区域,填充使用前景色。填充圆和椭圆使用GdFillEillpse函数,填充多边形使用GdFillPoly函数。填充的实现是在屏幕驱动中不断地调用GrawHorzLine函数。
(6)字体和文本输出
MicroWindows支持可变/不可变字体。文本输出时使用GdSetFont定义输出使用的字体,再调用GdText函数输出。
(7)颜色模式和调色板
MicroWindows支持RGB颜色,颜色匹配,真彩和调色板显示,3D效果的显示。
(8)图片绘制
MicroWindows支持两种格式的图片。单色图片用IMAGEBITS结构(1表示前景色,0表示背景色)来定义,绘制时调用GdBitmap程序。彩色图片可以分别定义为1、4、8 bpp的模式,用IMAGEHDR结构来表示。绘制时调用GdDrawImage函数。
(9)映射
映射功能在实虚屏的转换中使用。GdBlit可以实现上层的API将虚拟内存存复制到显示屏上,复制时调用GdBlit函数。
3 MicroWindows API
MicroWindows API中的基本通信机制是消息机制。一个消息机制中包含了message number和两个参数:wParam、lParam。Message被存放在应用程序的message-queue中,GetMessage函数将其取出。WM_GHAR针对键盘输入,WM_LBUTTONDOWN针对鼠标键被按下。窗口创建时使用WMCREATE,删除时使用WM_DESTROY。DispatchMessage将消息传到处理程序的窗口。
以下是处理消息的有关函数:
SendMessage 将消息传到窗口
PostMessage 将消息传到消息队列
PostQuitMessage 传递WM_QUIT消息到消息队列读时中断程序
GetMessage 得到消息后结束中断
TranslateMessage 将按键按下/弹起的消息传到WMCAR
DispatchMessage 将消息传到为它分配的窗口程序
3.2 窗口的创建和删除
RegisterClass 定义新的窗口类型并启动窗口程序
UnRegisterClass 删除窗口类型
CreateWindowsEx 按窗口类型创建一个窗口
DeatroyWindow 删除一个窗口
窗口创建后产生WM_CREATE消息,删除产生WM_DESTROY消息。
3.3 窗口的显示、隐藏和移动
ShowWindow函数指定窗口是否可见。MoveWindow改变窗口的位置和大小。窗口位置改变时,产生WM_MOVE消息;窗口大小改变时,产生WM_SIZE消息。
3.4 窗口的绘制
窗口绘制时产生WM_PAINT消息。窗口的标题栏自动绘制,设置属性使用SetWinowText,察看属性使用GetWindowText。
(1)实虚屏切换
窗口绘制使用的坐标系统是屏幕上的绝对坐标系,MicroWindows API使用的是相对坐标系。GetClientRect和GetWindowRect函数各自返回虚屏和实屏的坐标值。
(2)Device Contexts
调用图形API之间要包含device context。它指定系统所使用的窗口和坐标系,同时还定义系统默认的前景色和背景色。
GetDC用来包含device context。在画标题栏还需调用GetWindowDC。GetDCEx定义子/兄弟窗口的裁剪操作。绘制结束时调用ReleaseDC释放DC。
(3)图形API
见网络补充版(http://www.dpj.com.cn)
3.5 其它实用函数
WndSetDesktopWallpaper 设置桌面的背景图片
WndSetCursor 为窗口创建光标
WndRaiseWindow 拉伸窗口
WndLowerWindow 缩小窗口
WndGetTopWindow 返回最上层窗口的句柄
Sleep 睡眠
(1)设置窗口中心
WM_SETFOCUS和WMKILLFOCUS分别用于获取/删除中心。GetActiveWindow返回ancestor窗口,GetDesktopWINDOW返回当前桌面窗口的句柄。
(2)鼠标捕获
WM_MOUSEMOVE用来表示鼠标被移动。SetCapture获取全部的鼠标移动信息,ReleaseCapture返回到程序,GetCaptrue返回到捕获区域。
(3)区域管理
SetRect 定义一个矩形结构
SetRectEmpty 定义一个空矩形
CopyRect 复制一个矩形
IsRectEmpty 为空矩形时返回TRUE
InflateRect 放大矩形
OffsetRect 移动矩形
PtInRect 判断点是否在矩形区内
4 Nano-X API
(1)Client/Server模型
Nano-X允许应用程序使用Client/Server网络协议或本地UNIX Domain Socket,可让几个应用程序运行在嵌入式设备或远端主机上,并连接到Server上显示出来。
(2)窗口的创建和删除
Nan0-X中使用GrNewWindow创建窗口。GrNewInputWindow定义窗口只允许用来输入。函数定义了窗口的边界和颜色。
(3)窗口的显示、隐藏和移动
GrMapWindow用来显示窗口,GrUnmapWindow用来隐藏,GrRaiseWindow用来拉伸,GrLowerWindow用来缩小,GrMoveWindow用来移动,GrResizeWindow用来改变窗口大小。
(4)窗口中的绘制
①Graphics Context。GrNewGC用来分配graphics Context,删除时使用GrDestroyGC,GrCopyGC用来复制。创建一个Graphics Context后,服务器返回一个Graphics Context的ID,用来作为API的参数。GC中不存放裁剪区和系统坐标系。
②绘图API。见补充版(http://www.dpj.com.cn)。