Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1014874
  • 博文数量: 238
  • 博客积分: 2842
  • 博客等级: 少校
  • 技术积分: 2765
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-16 00:20
个人简介

stdlf

文章分类

全部博文(238)

文章存档

2013年(6)

2012年(13)

2011年(82)

2010年(89)

2009年(48)

我的朋友

分类:

2010-03-09 23:43:34

今天研究了uC/GUI的文字显示系统。 
这个系统的功能相当强大,提供了一下几个函数。 
GUI_DispChar() 显示一个字符 
GUI_DispCharAt() 在某个位置显示一个字符 
GUI_DispChars() 显示n个设定的字符 
GUI_DispString() 显示一个字符串 
GUI_DispStringAt() 在某个位置显示一个字符串 

还有好大一堆函数,不过这几个是最基本的。 
先看一段有关这些代码的事例程序: 
void MainTask(void) { 
unsigned int i; 
GUI_Init(); 
初始化,设置的默认字体是6*8的一种字体,具体叫什么忘了 
GUI_SetColor(GUI_YELLOW); 设置显示颜色为YELLOW,这里指的是字符的颜色 
GUI_DispChars('*', 108); 从当前坐标起显示108个*,就是截图里面的最上面的那排* 
for(i = 0; i < 480; i+=8) { 
GUI_DispCharAt('*', 1, i); 
} 在第一列显示一列* 
GUI_DispChars('*', 108); 在最下面一行显示一排* 
for(i = 0; i <= 480; i+=8) { 
GUI_DispCharAt('*', 634, i); 
} 在最右边的一列显示一列* 


GUI_SetColor(GUI_GREEN); 设置显示的颜色为GREEN 
GUI_SetFont(&GUI_Font8x10_ASCII); 设置字体为GUI_Font8*10_ASCII 
GUI_DispCharAt('A', 100, 100); 在坐标100,100处显示一个A 
GUI_DispString("! Hello World! "); 显示Hello World!大家注意这是紧跟着A显示出来的,即它是在当前光标处显示字符的 
GUI_SetFont(&GUI_Font32_ASCII); 设置字体 
GUI_SetColor(GUI_YELLOW); 设置显示颜色为YELLOW,下面代码显示的字符都是黄色的 
GUI_DispChars('*', 15); 显示15个* 
GUI_SetBkColor(GUI_BLUE); 设置背景颜色为BLUE,大家注意这个背景颜色,是衬在字下面的,而不是整个的背景 
GUI_DispCharAt('B', 600, 400); 
GUI_SetFont(&GUI_Font32B_ASCII); 
GUI_SetColor(GUI_RED); 
GUI_DispStringAt("Hello World!", 1, 200); 
在1,100这个地方显示字符串,注意覆盖掉了原先显示出来的* 
GUI_Delay(1000); 

效果图 

这样基本的字符显示函数就完了。大家都会使用了。 
在前提到这个GUI支持UNICODE。 
既然支持UNICODE那就应该能显示中文才对啊! 
当然能显示中文,但关键问题是字体! 
这里就讲一讲有关字体的提取。 
首先要用到一个字体转换工具,因为我们得到的uC/GUI代码基本上都是D版的,里面所附的字体转换工具都是DOME版,根本转换不出来正常的字体.c文件。在这里要用到另外一个程序。 
声明:该程序转载自,所有权归原作者ucgui所有,这里只是转载。仅上船该程序的可执行文件 

声明:在这里特便感谢原作者做出的贡献! 
首先运行程序,看到如图的程序界面,相当的简单。 

然后点击选择字体。按扭出现新的对话框,我选择的字体如图所示。 

确定后回到主界面,点击 
看到这个对话框文件就转换好了! 

直接加载进模拟器工程就可以享受中文字体带来喜悦了! 
在这里上传两个转换好的字体宋体(5号字)和Times new roman(5号字)两个字体,供大家参考,其中Times字体去掉了除ascii码之外所有的其他字模。 

说一下这里的5号字对应的就是16*16的汉字字体。 

宋体那个文件体积巨大3Mb多,如果是大字体的话就有十几MB了! 
我们现在运行下面的程序,体验一下中文的喜悦! 
#include "GUI.h" 
extern GUI_FLASH const GUI_FONT GUI_FontHZ_FangSong_GB2312_14; 
extern GUI_FLASH const GUI_FONT GUI_FontHZ_Times_New_Roman_14; 
extern GUI_FLASH const GUI_FONT GUI_Font8x10_ASCII; 
extern GUI_FLASH const GUI_FONT GUI_Font32_ASCII; 
extern GUI_FLASH const GUI_FONT GUI_Font32B_ASCII; /*这几行一定要有,声明从外部引用这个数据结构,建议大家将所有的字体的定义弄成一个头文件,这样子比较方便!*/ 
void MainTask(void) { 
unsigned int i; 
GUI_Init(); 
GUI_SetColor(GUI_YELLOW); 
GUI_DispChars('*', 108); 
for(i = 0; i < 480; i+=8) { 
GUI_DispCharAt('*', 1, i); 

GUI_DispChars('*', 108); 
for(i = 0; i <= 480; i+=8) { 
GUI_DispCharAt('*', 634, i); 

GUI_SetColor(GUI_GREEN); 
GUI_SetFont(&GUI_FontHZ_Times_New_Roman_14); 
GUI_DispCharAt('A', 100, 100); 
GUI_DispString("! Hello World! "); /*仔细看这里的字体已经是Times new roman了和上面的是不一样的*/ 
GUI_SetFont(&GUI_Font32_ASCII); 
GUI_SetColor(GUI_YELLOW); 
GUI_DispChars('*', 15); 
GUI_SetBkColor(GUI_BLUE); 
GUI_DispCharAt('B', 600, 400); 
GUI_SetFont(&GUI_FontHZ_FangSong_GB2312_14); 
GUI_SetColor(GUI_RED); 
GUI_DispStringAt("大家好这里是中文显示演示程序!", 1, 200); /*将上面程序中的Hello World替换成了中文!*/ 
GUI_Delay(10000); 


还有一个郁闷的问题,文件太大了有的编译器有限制!例如VC.NET的编译器。好在NIOS II编译器没有这个限制。 看看图: 

实际测试不影响使用,我们测试了4000多个汉字没有发现什么问题。 
uC/GUI NIOS II移植之2D图形库 

今天继续昨天的话题。 
来看2D图形库。这里面uC/GUI提供了强大的功能。先看看有什么函数。 

里面有不少东西,这是截的图懒的一个一个把他们敲上来了。 

先看第一个函数,GUI_SetDrawMode();设置GUI的绘图模式。靠上去好像很高深。这个函数就有一个参数mode。 
mode又两个选项GUI_DRAWMODE_NORMAL和GUI_DRAWMODE_XOR。 
先看一个例子大家就明白这个MODE是什么意思了。 
void MainTask(void) { 
unsigned int i; 
GUI_Init(); 
GUI_SetFont(&GUI_FontHZ_Times_New_Roman_14); 
GUI_SetDrawMode(GUI_DRAWMODE_NORMAL);设置为GUI_DRAWMODE_NORMAL 
GUI_SetBkColor(GUI_YELLOW); 
GUI_Clear(); //这句话比较有意思,执行了之后他会将整个窗口填充为Bk设置的颜色,要不只有在在绘制的图形的下面才有Bk色。 
GUI_SetColor(GUI_RED); 
GUI_FillCircle(300, 200, 130); //画第一个园,红色的,显眼一点。 
GUI_SetColor(GUI_GREEN); //设置绘图颜色为GREEN 
GUI_FillCircle(140, 200, 130); //以NORMAL方式画第二个圆 
GUI_SetDrawMode(GUI_DRAWMODE_XOR); //设置绘图方式为XOR 
GUI_FillCircle(460, 200, 130); //以XOR方式绘制第三个圆,这里大家仔细看看同样绘制了一GREEN颜色的圆,为什么不是GREEN的?XOR惹的祸。这个函数在黑白显示里面尤为重要! 
GUI_SetColor(GUI_BLUE); 
GUI_DispStringAt("First Circle", 300, 340); 
GUI_DispStringAt("Seconde Circle", 140, 340); 
GUI_DispStringAt("Third Circle", 460, 340); //这些是为了观察方便添上去的 
GUI_SetColor(GUI_BLACK); 
GUI_SetDrawMode(GUI_DRAWMODE_NORMAL); 
GUI_FillCircle(300, 200, 3); 
GUI_FillCircle(140, 200, 3); 
GUI_FillCircle(460, 200, 3); 
GUI_DrawCircle(300, 200, 131); //画圆,但是画出来的只有轮廓,上面调用的函数GUI_FillCircle()是将这员填充颜色的。uC/GUI里面所有的在封闭图形比如说圆和长方形的绘图函数Fill和Draw都有类似的关系 
GUI_Delay(5000); 

效果图 

接下来就应该显示位图了及BMP文件。但是大多数的嵌入式系统不支持文件系统那该怎么办? 
uC/GUI提供了一个解决方案,把位图转化为.C文件。 
这个工具就叫uC-GUI-BitmapConvert.exe 
执行这个工具,打开一个我事先准备好的位图文件。 
然后如图选择转换该文件。 

其实在这里选择把位图转换成多少色的都没有关系,gui会自动适佩目标系统的颜色。 
之所以这么选择是为了节省存储空间,毕竟嵌入式系统容量有限。 
转换好了以后立即就能看到效果。 

在界面的最上方显示的是这个位图的大小这里可看到是419*490。 
下面显示的就是调色板,即这个位图所有能显示出来的颜色。 
线面就是预览了。难看的不行了。 
然后选择另存为,就出现了.c文件这个选项。 

这是转换好的位图.c文件和位图原文件。 

uC/GUI还支持位图文件的压缩。在保存的时候选择就可以了。 

比较一下文件可以看到两个文件的大小相差了一倍。 
为压缩的600多k,压缩的才300。按照他文档的说明,可以提供2的压缩率。 
来看看他们都有什么不同。 
这是为压缩的: 
#include "stdlib.h" 
#include "GUI.H" 

/* Palette 
The following are the entries of the palette table. 
Every entry is a 32-bit value (of which 24 bits are actually used) 
the lower 8 bits represent the Red component, 
the middle 8 bits represent the Green component, 
the highest 8 bits (of the 24 bits used) represent the Blue component 
as follows: 0xBBGGRR 
*/ 

const GUI_COLOR Colors3[] = { 
0x000000,0x0000FF,0x00FF00,0x00FFFF 
,0xFF0000,0xFF00FF,0xFFFF00,0xFFFFFF 
}; /*这个位图的调色板可以看出来里面有8种颜色*/ 

const GUI_LOGPALETTE Pal3 = { 
8, /* number of entries */ 
0, /* No transparency */ 
&Colors3[0] 
}; 

const unsigned char ac3[] = { 
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 
/*这里面存放的就是bitmap的数据太多了就被我精简了,只显示一行。有兴趣的去下载附件看看。*/ 
}; 

const GUI_BITMAP bm3 = { 
419, /* XSize */ 
490, /* YSize */ 
210, /* BytesPerLine */ 
4, /* BitsPerPixel */ 
ac3, /* Pointer to picture data (indices) */ 
&Pal3 /* Pointer to palette */ 
}; 

下面是压缩的: 
#include "stdlib.h" 
#include "GUI.H" 

/* Palette 
The following are the entries of the palette table. 
Every entry is a 32-bit value (of which 24 bits are actually used) 
the lower 8 bits represent the Red component, 
the middle 8 bits represent the Green component, 
the highest 8 bits (of the 24 bits used) represent the Blue component 
as follows: 0xBBGGRR 
*/ 
const GUI_COLOR Colors3_compressed_with_palette[] = { 
0x000000,0x0000FF,0x00FF00,0x00FFFF 
,0xFF0000,0xFF00FF,0xFFFF00,0xFFFFFF 
}; 

const GUI_LOGPALETTE Pal3_compressed_with_palette = { 
8, /* number of entries */ 
0, /* No transparency */ 
&Colors3_compressed_with_palette[0] 
}; 

const unsigned char ac3_compressed_with_palette[] = { 
/* RLE: 418 Pixels @ 000,000*/ 254, 0x07, 164, 0x07, 
/* RLE: 001 Pixels @ 418,000*/ 1, 0x00, 
/* RLE: 418 Pixels @ 000,001*/ 254, 0x07, 164, 0x07, 
/*同上砍掉了很多东西,有兴趣的看附件*/}; 
const GUI_BITMAP bm3_compressed_with_palette = { 
419, /* XSize */ 
490, /* YSize */ 
210, /* BytesPerLine */ 
GUI_COMPRESS_RLE4, /* BitsPerPixel */ 
ac3_compressed_with_palette, /* Pointer to picture data (indices) */ 
&Pal3_compressed_with_palette /* Pointer to palette */ 
,GUI_DRAW_RLE4 
}; 
看看有什么区别,根据我的理解,压缩就是把有信息的象素点标出来。黑色的就不标记。 

不过在显示效果上没有任何区别!但是显示压缩的位图明显能感觉到速度较慢。 
这是测试用的代码: 
extern const GUI_BITMAP bm3; 
extern const GUI_LOGPALETTE Pal3; 
extern const unsigned char ac3[]; 
extern const GUI_BITMAP bm3_compressed_with_palette; 
//这是一些要用到的外部变量声明 

GUI_SetDrawMode(GUI_DRAWMODE_NORMAL); 
GUI_SetBkColor(GUI_BLACK); 
GUI_SetColor(GUI_WHITE); 
GUI_Clear(); /*清理桌面,变成黑的*/ 

GUI_DrawBitmap(&bm3, 10,10); /*在左上角为起始点的10,10座标为圆点显示位图*/ 
GUI_Delay(5000); 
GUI_Clear(); 
GUI_Delay(1000); 
GUI_DrawBitmap(&bm3_compressed_with_palette, 50, 10); /*在左上角为起始点的50,10座标为圆点显示位图,效果上没有区别,但是速度明显的慢*/ 
GUI_Delay(5000); 
直接添加到上段代码的后面就行了。 

超出显示范围的内容就被自动砍掉了。这是第一个显示的截图,第二个由于效果上没却别,就不浪费论坛空间了。 

再来看看GUI_DrawBitmapExp();这个函数,这个函数有多达十个参数。 
void GUI_DrawBitmapExp(int x0, int y0, //显示位图的起始座标(指的是在LCD上的位置) 
int XSize, int YSize, //这个两参数的含义是在待显示的位图中选取一个XSize*YSize大小的范围来显示,从0,0座标开始。取值范围1~~255 
int XMul, int YMul, //比例因数,即放大比率!议会就能看到这个参数的效果 
int BitsPerPixel, &n bsp; //位图的每个象素的位数,可以在bm3这个结构体中找到 
int BytesPerLine, //待显示位图每行的字节数,可以在bm3这个结构体中找到 
const U8* pData, //指向位图,实际存储数据变量的指针。 
const GUI_LOGPALETTE* pPal); //指向GUI_LOGPALETTE数据结构的指针 GUI_Clear(); 
GUI_Delay(1000); 
GUI_DrawBitmapExp(10, 10, 255, 255, 1, 1, bm3.BitsPerPixel, bm3.BytesPerLine, &ac3, &Pal3); //看看这段代码的含义,特别注意pData的取值是指向ac3的指针 
这句的效果 

GUI_Delay(5000); 
GUI_DrawBitmapExp(10, 10, 255, 255, 2, 2, bm3.BitsPerPixel, bm3.BytesPerLine, &ac3, &Pal3); 
这句的效果,图片被放大了! 

GUI_Delay(5000); 

GUI_Clear(); 
GUI_DrawBitmapMag(&bm3 ,10, 10, 2, 2); 
GUI_Delay(5000); 
也是放大显示一个图像!效果和上面的是一样的。 
没有什么区别。 

下来在演示一个polygons的例子。 
static const GUI_POINT _aPointArrow[] = { 
{ 0, 0}, 
{-40, -30}, 
{-10, -20}, 
{-10, -70}, 
{ 10, -70}, 
{ 10, -20}, 
{ 40, -30}, 
}; //定义一个多变性所有的顶点 
GUI_Clear(); 
GUI_SetColor(GUI_BLUE); 
GUI_FillPolygon (&_aPointArrow[0], 7, 260, 180); //填充颜色 
GUI_DrawPolygon(&_aPointStar, 7, 460, 200); 仅有边框 
//7表着个要Fill的多变性有几个顶点 
GUI_Delay(5000); 

效果如图: 

今天用到的main函数。 

今天就到此为止!明天继续!有兴趣的朋友还请关注。 
uC/GUI NIOS II移植之Window Manager(窗口管理器) 

昨天太晚了没有时间更新了。今天继续。 
今天来看看Window manager,窗口管理器。 
先来看一个小例子。 

#define MSG_CHANGE_TEXT WM_USER+0 

#ifndef NULL 
#define NULL 0 
#endif 

typedef struct { 
int x; 
int y; 
int xHere, yHere; 
const GUI_BITMAP* pBitmap; 
} tDrawContext; 

extern GUI_FLASH const GUI_FONT GUI_FontHZ_FangSong_GB2312_14; 
extern GUI_FLASH const GUI_FONT GUI_FontHZ_Times_New_Roman_14; 
extern GUI_FLASH const GUI_FONT GUI_Font8x10_ASCII; 
extern GUI_FLASH const GUI_FONT GUI_Font32_ASCII; 
extern GUI_FLASH const GUI_FONT GUI_Font32B_ASCII; 
extern const GUI_BITMAP bm3; 
extern const GUI_LOGPALETTE Pal3; 
extern const unsigned char ac3[]; 
extern const GUI_BITMAP bm3_compressed_with_palette; 
extern const GUI_BITMAP bmmap; /*以上全部是外部变量声明,有位图,有字体*/ 

static WM_CALLBACK* _cbBkWindowOld; /*声明背景窗口的回调函数(Call back function),后面会具体说明这个Call back是干什么的*/
static char _acInfoText[40]; /*要在背景窗口中显示的文字*/ 

static WM_HWIN _hWindow2; /*窗口2*/ 

static void _cbWindow2(WM_MESSAGE* pMsg) { /*窗口2的call back*/ 
int x, y; 
switch (pMsg->MsgId) { /*pMsg这个参数用来告诉这个回调函数发生了什么事件的!这里列出了系统已经定义好的所有的事件*/ 
case WM_CREATE: 
/*to do add code here*/ 
break; 

case WM_DELETE: 
/*to do add code here*/ 
break; 

case WM_HIDE: 
/*to do add code here*/ 
break; 

case WM_MOVE: 
/*to do add code here*/ 
break; 

case WM_NOTIFY_PARENT: 
/*to do add code here*/ 
break; 

case WM_PAINT: /*这个Paint事件,准确地翻译我不知道,但他的功能主要就是自动重绘窗口,这十分重要,有了自动重绘你只要在这个CB里面告诉GUI你想绘什么东西就行了,GUI会自动在适当的时机重绘*/ 
GUI_SetBkColor(GUI_RED); 
GUI_Clear(); 
GUI_SetColor(GUI_WHITE); 
GUI_SetFont(&GUI_Font24_ASCII); 
x = WM_GetWindowSizeX(pMsg->hWin); 
y = WM_GetWindowSizeY(pMsg->hWin); 
GUI_DispStringHCenterAt("Test Window No.2", x / 2, 1); /*在这里面你可以调用上面贴子中所有出现过的内容,但不是在整个屏幕上绘图了,而是在这个窗口中绘图*/ 
break; 

case WM_SHOW: 
/*to do add code here*/ 
break; 

case WM_SIZE: 
/*to do add code here*/ 
break; 

case WM_TOUCH: 
/*to do add code here*/ 
break; 

default: 
WM_DefaultProc(pMsg); /*在回调函数中还有很多其他系统定义的事件,例如WM_SIZE你可以在发生了该事件后改变窗口的内容。有了这个回调函数就可以实现很多的功能*/ 



static void _ChangeInfoText(char* pStr) { /*将要在背景窗口中显示的文字放到一个全局变量里面去,再由Bk窗口的回调函数自动刷新*/ 
WM_MESSAGE Message; 
Message.MsgId = MSG_CHANGE_TEXT; 
Message.Data.p = pStr; 
WM_SendMessage(WM_HBKWIN, &Message); /*发送一个消息告诉Bk的cb发生了文字改变的事件*/ 
WM_InvalidateWindow(WM_HBKWIN); 


static void _cbBkWindow(WM_MESSAGE* pMsg) { /*Bk窗口的CB函数,在这里可以更清楚地看到cb是怎么工作的*/ 
switch (pMsg->MsgId) { 
case MSG_CHANGE_TEXT: /*发生了MSG change设个事件,将待显示的文本拷贝的变量中去*/ 
strcpy(_acInfoText, pMsg->Data.p); /*这里有点小小的编程技巧,在这里没有使用break,而是直接执行下面的case里面的内容这样就直接刷新的Bk窗口*/ 
case WM_PAINT: 
GUI_SetBkColor(GUI_CYAN); 
GUI_Clear(); 
GUI_SetColor(GUI_RED); 
GUI_SetFont(&GUI_Font24_ASCII); 
GUI_DispStringHCenterAt("WindowManager - Sample", 160, 5); 
GUI_SetFont(&GUI_FontHZ_FangSong_GB2312_14); 
GUI_DispStringAt(_acInfoText, 5, 40); /*在这里就可以看到桌面是怎么来的了,这里的图片和lcd的大小不一样,如果一样就是桌面了*/ 
GUI_DrawBitmap(&bm3, 50, 60); 
break; /*这里就看到了Bk窗口里面发生的一切*/ 
default: 
WM_DefaultProc(pMsg); 


/* 
******************************************************************* 

* main() 

******************************************************************* 
*/ 

void MainTask(void) { 
unsigned int i; 
WM_HWIN hClient; 
GUI_Init(); 

_cbBkWindowOld = WM_SetCallback(WM_HBKWIN, _cbBkWindow); 
GUI_Delay(1000); 
_ChangeInfoText("uC/GUI演示程序!"); 

_hWindow2 = WM_CreateWindow(330, 130, 300, 300, WM_CF_SHOW | WM_CF_FGND, _cbWindow2, 0); 
GUI_Delay(2000); 


这段代码就比较复杂了,可以看出来想把GUI用好不是一件容易的事情! 

那如果不使用call back机制呢。一样可以实现相同的功能。但是屏幕的刷新可就是你的责任了。 
用户就需要调用相关的函数来实现屏幕内容的刷新。 
可能有很多人还不理解这个cb机制。我也说不太清。 

在前几天的所有例子中都是用户控制刷屏的。就直在调用GUI_Delay()的时候内容才会改变! 
单步运行就知道了。 

下面看看队窗口的操作 
WM_ResizeWindow(_hWindow2, -100, -100); 
WM_MoveTo(_hWindow2, 50, 100); 
执行这两句,窗口就变了样了。 

当然了你还可以一次让它移动1个像素,这样看上去就是平滑移动的! 

窗口管理还有很多的内容,以后慢慢再贴出来。 

这些东西决的原创,欢迎大家提意见,随意转载,但请注明出处和作者。 
阅读(3424) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~