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個像素,這樣看上去就是平滑移動的!
窗口管理還有很多的內容,以后慢慢再貼出來。
這些東西決的原創,歡迎大家提意見,隨意轉載,但請注明出處和作者。
uC/GUI NIOS II移植及應用筆記 下
更新時間: 2008-03-19 16:53:00來源: 粵嵌教育瀏覽量:1397