Chinaunix首页 | 论坛 | 博客
  • 博客访问: 390188
  • 博文数量: 107
  • 博客积分: 2536
  • 博客等级: 少校
  • 技术积分: 781
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-14 15:19
文章分类

全部博文(107)

文章存档

2017年(11)

2016年(8)

2015年(14)

2014年(32)

2012年(1)

2011年(1)

2010年(7)

2009年(33)

我的朋友

分类: LINUX

2009-08-04 16:49:44

好像是从《共创软件》上下来的
Linux下嵌入式GUI编程环境
孙宗君

本文介绍在Linux下利用Microwindows和Fltk进行GUI编程的一些经验,如果需要在X-Wi
ndow上编程的话,请您阅读Xlib库编程指南或QT库编程手册,它们提供了完备的控件集
合,我想本文对您没有太多的可读性。

Microwindows和Fltk程序适合于对硬件要求苛刻的环境,由上述两种库产生的程序短小
,因此在某些性能和效果方面远不能和台式机上的GUI程序相提并论。我首先介绍一下两
者的概况。Microwindows是一个遵循GPL的嵌入式GUI开发环境,几乎全部用C语言编写,
有一点点用汇编语言编写,因此如果您想利用其进行开发的话,您必须具备C语言的知识
。Fltk也是一个遵循GPL的自由软件,它是用C++语言编写的一个在Microwindows之上的
控件库,提供了许多GUI控件,如按钮、列表框和对话框等等。

如果您手头没有上述两者的二进制库,那么您可以到共创开源公司的网站上去下载其源
代码文件,源码文件需要编译,在您的机器上必须安装一个C和C++语言编译器,还要有
make工具,最好使用GNU的gcc和make工具。

可供下载的网站网址为:

共创开源公司:
Microwindows:
Fltk:

将上述文件下载到本地,对压缩文件包解压后分别产生microwin 和flnx两个目录,请阅
读两个目录下的Readme文件。对于Microwin请修改src目录下的config文件,里面设置了
许多编译控制开关。你可以选择屏幕、键盘和鼠标的驱动程序种类,如果您有不清楚的
问题,可以到相关的邮件列表或共创开源公司进行联系,那里或许可能会找到你的答案
。对于Fltk,目录flnx下有三个目录:FL、src、test,第一个是库头文件,第二个是库
源文件,第三个是示例程序源文件。请运行flnx目录下的configure程序,在该命令后面
加一选项 -prefix,后面接microwin文件的目录。
如:

./configure -prefix=/home/cclinux/microwin/src

然后make,便可以生成相应的库文件和示例程序。

现在我们分别介绍在Microwindows下进行GUI编程的一般步骤,在Microwindows中,整个
应用程序被分为三层:设备驱动层、图形引擎层和编程API,对于我们这些开发人员来讲
,我们只需利用API即可。如果您是个编程高手并且曾在编过其它GUI程序,您可以将三
层代码全部分析一遍,对您大有裨益。

编程API分为两种风格,一种是Windows的消息机制,另一种是客户/服务器方式。这里仅
介绍后一种编程风格。在客户/服务器环境下,你必须先启动服务器程序nano-X,然后启
动相应的客户程序。如果程序启动后,您发现鼠标无法应用,请运行micrown/src目录下
的mouse.sh脚本文件,该程序启动鼠标服务器程序。我们举一个具体的程序来分析其编
程过程,该例子取自microwin/demos/nanox目录下的字体示例程序,考虑篇幅原因对该
程序有所删改。

这个示例程序用来创建一个窗口,并在窗口中随机某个位置显示指定的字体,在Microw
indow中可支持系统内置字体、truetype字体和中文字体。

#include
#include
#include "nano-X.h"

所有的示例程序几乎都要包含 nano-X.h头文件,该文件定义了客户/服务器方式下编程
所用到的常量、数据结构、事件类型和API原型,这些常量和API都以GR(或Gr)开头。

#define CLIP_POLYGON    0   /* =1 for polygonal region test*/

该程序还可以测试多边形区域的剪裁、刷新,如果你需要测试这些内容,将上一行的0改
为1,打开编译开关。

#if HAVE_HZK_SUPPORT
#define BIG5
#define MAXFONTS 1
#ifndef BIG5
#define FONT1 "HZKFONT"
....
#else
#define FONT1 "HZXFONT"
//汉字库16x16或12x12
....
#endif
#elif HAVE_T1LIB_SUPPORT
#define MAXFONTS 5
#define FONT1 "bchr"
....
#else
/* truetype*/
#define MAXFONTS 5
#define FONT1 "lt1-r-omega-serif"
....
#endif
static char * names[5] = { FONT1, FONT2, FONT3, FONT4, FONT5 };

上述代码用来定义要创建的字体名称,并将其放在数组names中.
同常见的C程序一样,Microwindows程序也是以main作为主程序入口点

int main()
{
GR_WINDOW_ID window;   
//窗口的标志号,类似窗口句柄,在一个程序中该号码唯一
GR_EVENT event;
//程序将要处理的事件类型
GR_GC_ID gc;
//绘图设备描述表,类似于Windows中CDC。
GR_FONT_ID  fontid;
//某种字体标志号
int i, x, y;
GR_REGION_ID regionid = 0;
//绘图区域标志号

凡是以GR打头的数据类型都在头文件nano-X.h中声明,在nano-X中,所有的GUI实体都有
一个标志数字用来记录跟踪该实体,如窗口、字体、绘图设备描述表(Graphics Conte
xt)。一旦创建了相应的实体后,相关API便返回该实体的标志数字。

#if CLIP_POLYGON   //是否要测试多边形区域图形效果
GR_POINT points[]={ {0, 0},
                {600, 0},
                {600, 600},
                {0, 600}};
#else
GR_RECT clip_rect={0,0,800,600};
#endif
srand(time(0));
GrOpen();

在nano-X编程方式下,开发人员所做的各种函数调用都是向后台服务器程序nano-X发出
一个服务请求,然后由服务器来完成相应的动作,如创建一个窗口、字体和屏幕刷新等
等。GrOpen调用是用来请求服务器打开控制台设备,服务器将检测鼠标、键盘和屏幕设
备是否可用,如果可用,则为客户程序分配相应的硬件资源。否则,失败退出。您必须
首先调用该函数来完成资源申请,打开显示设备,建立到nano-X服务器的一条通信连接
,然后才可以进行后续工作。

window = GrNewWindow(GR_ROOT_WINDOW_ID, 0,0, 800,600, 4, BLACK,BLUE);
GrMapWindow(window);
gc = GrNewGC();

既然是GUI程序,第一件事毫无疑问是创建一个令人讨厌的窗口,函数GrNewWindow调用
就是完成这个任务。该函数有8个参数,第一个指定待创建窗口的父窗口标志号,后面两
个参数指定窗口的左上角在屏幕上的位置。第四个和第五个参数指定窗口的宽度和高度
。第六个参数指定窗口边框的宽度,第七和第八个参数分别指定窗口的背景色和前景色
。如果大家有进行任何GUI编程方面的经验,相信对这些名词不会陌生。创建完窗口后,
只是有了窗口这个实体,一个数据结构,还需要根据实际信息将其显示到屏幕上。第二
条语句GrMapWindow就是将指定的窗口映射到屏幕上,该函数只有一个参数,就是要显示
的窗口标志符。创建了窗口并把它显示出来,如果不在上面做任何工作就没有任何意义
。第三条语句就是申请图形设备,GrNewGC,并获得一个图形设备标志符。这同Windows
类似:CreateWindow,ShowWindow。

GrSelectEvents(window,GR_EVENT_MASK_ALL);
GrSetGCUseBackground(gc,GR_FALSE);
GrSetGCBackground(gc, GR_RGB(0, 0, 0));

既然是GUI程序,另外一个重要的要素是事件驱动,所有的事件都是针对某个特定的窗口
的,第一个语句GrSelectEvents就是根据第一个参数(指定的窗口)为之选择待处理的
事件类型(第二个参数),事件类型比较多,如鼠标单击、双击、移动、拖曳以及窗口
的创建、刷新和销毁等等。第二条语句设置上面创建的设备描述表gc的一些属性,一个
图形设备描述表应当知道自己的背景、前景颜色,使用的绘图笔的粗细、画刷的宽度颜
色,有那些区域等等信息。你可以用GrSetGCBackground、GrSetGCForeground来设置其
背景和前景颜色。这些函数的第一个参数必须是您要操作的图形设备描述表的标志符(
GrNewGC 返回该值)。

while(1) {
GrCheckNextEvent(&event);

这个While循环是程序的主体,它不断地创建一些字体,在窗口的不同位置显示对应字体
的字符串。上述语句GrCheckNextEvent就是用来检测事件队列中是否有事件在等待
处理,如果有,将它放在参数变量event中,如果没有则返回。

sleep(2);
i = (int)((float)MAXFONTS * rand() / (RAND_MAX + 1.0));
//创建字体
fontid = GrCreateFont(names[i], 20, NULL);
//设置字体尺寸
GrSetFontSize(fontid, 1+(int)(80.0 * rand() / (RAND_MAX+1.0)));
/* 33 degrees 设置字体旋转角度*/
GrSetFontRotation(fontid, 330);
//设置字体属性
GrSetFontAttr(fontid, GR_TFKERNING|GR_TFANTIALIAS, 0);
//将已创建的图形设备描述表同字体关联起来
GrSetGCFont(gc, fontid);
//设置图形设备描述表的前景色
GrSetGCForeground(gc, rand() & 0xffffff);
//生成输出字体的随机坐标值
x = (int) ((MAXW * 1.0) *rand()/(RAND_MAX+1.0));
y = (int) ((MAXH * 1.0) *rand()/(RAND_MAX+1.0));

下面这段代码用来在屏幕上利用指定的图形设备描述表输出指定字体的字符串,字符输
出函数为GrText,该函数的第一个参数为输出字符串的窗口标志号,第二个参数为使用
的图形设备描述符标志号,第三和第四个参数为待输出字符串在窗口上的坐标值,第五
个参数为待输出的字符串,第六个为字符串的长度,第七个为字体编码的符号位。根据
编译开关来决定是输出英文还是中文。

#if HAVE_HZK_SUPPORT
{//to test Unicode 16 chinese characters display ,use HZK font Bitmap font (
Metrix font).
#ifndef BIG5
char buffer[256];
buffer[0]=0x6c;
GrText(window, gc,x,y+20, buffer,17, GR_TFUC16);
x=0;y=16;
GrText(window, gc,x,y+20, buffer,17, GR_TFUC16);
#else
unsigned short buffer[7];
buffer[6]=0x0;
GrText(window, gc,x,y+20, buffer,7, GR_TFUC16);
x=0;y=16;
GrText(window, gc,x,y+20, buffer,7, GR_TFUC16);
#endif
  }
#ifndef BIG5
x=0;y=16;
/* HZK Metrix font test, includes Chinese and English*/
GrText(window, gc,x,y, "Microwindows,欢迎使用中英文点阵字体",
-1, GR_TFASCII);
#else
GrText(window, gc,x,y, "Microwindows,`\275\241\275\241",
-1, GR_TFASCII);
x=0;y=16*3+4;
GrText(window, gc,x,y, "Mincrowindows:", -1, GR_TFASCII);
#endif
GrFlush();

该函数用来刷新图形缓冲区内容,这样强制要求以前所有的绘图请求一并执行。

#else/*!HZK_FONT_SUPPORT*/
#if HAVE_BIG5_SUPPORT
/* ENCODING_BIG5 test*/
GrText(window, gc,x,y, "  ", -1, GR_TFASCII);
#else
#if HAVE_GB2312_SUPPORT
/* ENCODING_GB2312 test*/
GrText(window, gc,x,y, "\275\241\275\241", -1, GR_TFASCII);
#else
/* ASCII test*/
GrText(window, gc,x,y, "Microwindows", -1, GR_TFASCII);
#endif
#endif
#endif /* HZK_FONT_SUPPORT*/
GrDestroyFont(fontid);

GrDestroyFont销毁参数所指定的字体,在您使用完毕创建的字体后,请不要忘记一定要
释放字体所占用的资源。

if(event.type == GR_EVENT_TYPE_CLOSE_REQ) {
            GrClose();
            exit(0);
        }
这个if语句检测事件类型,如果是退出请求,则关闭与服务器的通信连接,并退出整个
应用程序。
    }
GrClose();
}

好了,现在我们来总结一下整个程序结构:

首先,调用建立与nano-X服务器的通信连接;
然后,创建窗口和所需要的资源,如图形设备描述表、字体、绘图区域等等;
接着,选择要处理的事件类型;
进行实际工作的处理,检测事件类型、实际图形输出、计算工作的进行;
完成工作后,销毁指定的字体、图形设备描述表和窗口;
最后,关闭与nano-X服务器的通信连接,退出应用程序,下一次我们介绍在Fltk下利用
其控件进行GUI编程。

阅读(2167) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~