uC/GUI NIOS II移植之Text显示
今天研究了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文件。在这里要用到另外一个程序。
声明:该程序转载自www.ucgui.com,所有权归原作者ucgui所有,这里只是转载。仅上船该程序的可执行文件
http://www.ednchina.com/Upload/Blog/cecb4a69-b388-4a9f-916d-2b216f8edcc9.rar
声明:在这里特便感谢原作者做出的贡献!
首先运行程序,看到如图的程序界面,相当的简单。
然后点击选择字体。按扭出现新的对话框,我选择的字体如图所示。
确定后回到主界面,点击
看到这个对话框文件就转换好了!
直接加载进模拟器工程就可以享受中文字体带来喜悦了!
在这里上传两个转换好的字体宋体(5号字)和Times new roman(5号字)两个字体,供大家参考,其中Times字体去掉了除ascii码之外所有的其他字模。
http://www.ednchina.com/Upload/Blog/622a4994-39aa-4380-a8cc-4cef5e57b7df.rar
说一下这里的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文件和位图原文件。
http://www.ednchina.com/Upload/Blog/abb12d5c-6ee8-4898-b9e0-1a7fc1c424c8.rar
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函数。
http://www.ednchina.com/Upload/Blog/87886f3f-b745-492d-a944-4df06746c217.rar
今天就到此为止!明天继续!有兴趣的朋友还请关注。
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个像素,这样看上去就是平滑移动的!
窗口管理还有很多的内容,以后慢慢再贴出来。
这些东西决的原创,欢迎大家提意见,随意转载,但请注明出处和作者。
文章评论(0条评论)
登录后参与讨论