uGUI的基本工作原理是將GUI組件的像素通過數據修改或者替換的方法疊加在原始圖像數據上
uGUI的使用非常簡單,將下載的ugui.h和ugui.c文件導入PS工程中即可以使用,通過官網手冊和代碼註釋可以查看詳細用法
下載
在官網下載uGUI的最新版本
在網頁的下方可以找到使用手冊,源代碼和示例程序
導入PS工程
可以通過複製粘貼的方式將下載的源碼文件ugui.h和ugui.c文件導入PS工程
將ugui.h中的#include "system.h"
改爲#include "stdint.h"
定義像素點繪製函數
爲了讓uGUI正常工作,還應當在程序中自定義像素點繪製函數,並且在uGUI的初始化函數UG_Init()
中通過參數指定繪製函數,否則uGUI不能工作
目前使用的像素點繪製函數如下:
//自定義像素點(x, y)的填充函數
static void pix_set(UG_S16 x, UG_S16 y, UG_COLOR c)
{
//計算當前像素點在圖像緩衝中的偏移
//LINE_WIDTH爲當前圖像一行數據佔用的字節數目
//PIX_BYTES爲當前圖像中一個像素點佔用的字節數目
u32 pix_addr;
pix_addr = y*LINE_WIDTH+x*PIX_BYTES;
//取得配置顏色的RGB通道數值
u8 r, g, b;
r = (c >> 16) & 0xFF;
g = (c >> 8) & 0xFF;
b = c & 0xFF;
//下方的透明度算法正確,但是uGUI底層接口調用時會在刷新GUI時出現閃爍
#ifdef GUI_ALPHA//如果有透明度要求
//當前像素點值
u8 ro, go, bo;
ro = *(frame_ptr_ping+pix_addr);
go = *(frame_ptr_ping+pix_addr+1);
bo = *(frame_ptr_ping+pix_addr+2);
//當前像素點值與GUI像素點值融合
r = (u8)((float)r*GUI_ALPHA+(float)ro*(1.0F-GUI_ALPHA)+0.5F);
g = (u8)((float)g*GUI_ALPHA+(float)go*(1.0F-GUI_ALPHA)+0.5F);
b = (u8)((float)b*GUI_ALPHA+(float)bo*(1.0F-GUI_ALPHA)+0.5F);
#endif
//當前圖像使用ping/pong雙緩衝,一個緩衝繪製GUI的同時,另一個緩衝接收原始數據
//配置像素點的RGB值
if (frame_flag == 0)
{
//刷新ping緩衝
*(frame_ptr_ping+pix_addr) = r;
*(frame_ptr_ping+pix_addr+1) = g;
*(frame_ptr_ping+pix_addr+2) = b;
}
else
{
//刷新pong緩衝
*(frame_ptr_pong+pix_addr) = r;
*(frame_ptr_pong+pix_addr+1) = g;
*(frame_ptr_pong+pix_addr+2) = b;
}
}
刷新GUI圖像
uGUI使用函數UG_Update()
刷新GUI圖像,在刷新GUI之前必須保證原始圖像不再更改,否則原始圖像的更改將會覆蓋GUI圖像
每次刷新GUI圖像之前,即使Window顯示或者隱藏狀態不變,也必須用UG_WindowShow()
函數或者UG_WindowHide()
函數更新全部Window的顯示狀態
定製GUI
爲了更好的匹配項目需求,大多數情況下需要對uGUI接口函數進行定製
而且uGUI的授權允許對其源碼進行修改
由於項目需要,目前對以下三個功能進行了定製修改
BMP圖像繪製
uGUI的源碼沒有RGB888像素格式的BMP圖像繪製功能,作爲最普遍的像素格式,需要自行添加至uGUI中
首先添加BMP_BPP_24的宏定義,作爲RGB888的格式定義
在ugui.h中找到BMP_BPP_32的宏定義(其中BPP表示Bits Per Pixel),在其下方添加:
#define BMP_BPP_24 (1<<6)
在ugui.c中找到UG_DrawBMP()
函數,將函數內容修改爲以下代碼,注意下方代碼不繪製BMP圖像中的白色,將白色作爲透明色實現
//xp指繪圖起點x座標,yp指繪圖起點y座標
void UG_DrawBMP( UG_S16 xp, UG_S16 yp, UG_BMP* bmp )
{
UG_S16 x,y,xs;
UG_U8 r,g,b;
UG_U16 tmp;
UG_COLOR c;
if ( bmp->p == NULL ) return;
/* Only support 16 BPP so far */
if ((bmp->bpp == BMP_BPP_16) && (bmp->colors == BMP_RGB565))//uGUI原有的BMP繪製功能
{
UG_U16* p;
p = (UG_U16*)bmp->p;
xs = xp;//用xs暫存形參數值
for(y=0;y<bmp->height;y++)
{
xp = xs;//每行繪圖的列起點
for(x=0;x<bmp->width;x++)
{
tmp = *p++;
/* Convert RGB565 to RGB888 */
r = (tmp>>11)&0x1F;
r<<=3;
g = (tmp>>5)&0x3F;
g<<=2;
b = (tmp)&0x1F;
b<<=3;
c = ((UG_COLOR)r<<16) | ((UG_COLOR)g<<8) | (UG_COLOR)b;
UG_DrawPixel( xp++ , yp , c );
}
yp++;
}
}
else if ((bmp->bpp == BMP_BPP_24) && (bmp->colors == BMP_RGB888))//自定義
{
UG_U8* p;
p = (UG_U8*)(bmp->p);
xs = xp;//用xs暫存形參數值
for (y = 0; y < bmp->height; ++y)
{
xp = xs;//每行繪圖的列起點
for (x = 0; x < bmp->width; ++x)
{
b = *p;
g = *(p+1);
r = *(p+2);
c = ((UG_COLOR)r<<16) | ((UG_COLOR)g<<8) | (UG_COLOR)b;
if ((r != 0xFF) || (g != 0xFF) || (b != 0xFF))
{
//白色不繪製,作爲透明顯示
//非白色才繪製
UG_DrawPixel(xp, yp, c);
}
//更新指針
p += 3;
//更新繪圖列座標
++xp;
}
++yp;//更新繪圖行座標
}
}
else
{
return;
}
}
Window背景透明
uGUI中的Window是所有GUI組件的容器,但是Window背景不透明
如果需要Window背景透明,有2種方法:
- 每個GUI組件使用單個Window,Window設置爲無邊框和標題欄,並且GUI組件佔滿Window。由於uGUI中只有Window可以在建立後移動位置,這種方法可以實現GUI組件移動的效果。
- 修改ugui.c中的
_UG_WindowUpdate()
函數,去掉函數中繪製背景的代碼
根據上述第2種方法修改後的_UG_WindowUpdate()
函數如下:
void _UG_WindowUpdate( UG_WINDOW* wnd )
{
UG_U16 i,objcnt;
UG_OBJECT* obj;
UG_S16 xs,ys,xe,ye;
xs = wnd->xs;
ys = wnd->ys;
xe = wnd->xe;
ye = wnd->ye;
wnd->state &= ~WND_STATE_UPDATE;
/* Is the window visible? */
if ( wnd->state & WND_STATE_VISIBLE )
{
// /* 3D style? */
// if ( (wnd->style & WND_STYLE_3D) && !(wnd->state & WND_STATE_REDRAW_TITLE) )
// {
// _UG_DrawObjectFrame(xs,ys,xe,ye,(UG_COLOR*)pal_window);
// xs+=3;
// ys+=3;
// xe-=3;
// ye-=3;
// }
// /* Show title bar? */
// if ( wnd->style & WND_STYLE_SHOW_TITLE )
// {
// _UG_WindowDrawTitle( wnd );
// ys += wnd->title.height+1;
// if ( wnd->state & WND_STATE_REDRAW_TITLE )
// {
// wnd->state &= ~WND_STATE_REDRAW_TITLE;
// return;
// }
// }
// /* Draw window area? */
// UG_FillFrame(xs,ys,xe,ye,wnd->bc);
/* Force each object to be updated! */
objcnt = wnd->objcnt;
for(i=0; i<objcnt; i++)
{
obj = (UG_OBJECT*)&wnd->objlst[i];
if ( !(obj->state & OBJ_STATE_FREE) && (obj->state & OBJ_STATE_VALID) && (obj->state & OBJ_STATE_VISIBLE) ) obj->state |= (OBJ_STATE_UPDATE | OBJ_STATE_REDRAW);
}
}
else
{
// UG_FillFrame(wnd->xs,wnd->xs,wnd->xe,wnd->ye,gui->desktop_color);
}
}
添加中文顯示
uGUI源碼不支持中文顯示
在uGUI顯示中文有2種方法:
- 將中文內容作爲BMP圖像顯示,根據需要自行定義BMP圖像的三種組件Button, TextBox和Image
- 使用點陣取模軟件將需要顯示的中文字體加入代碼,替換uGUI中現有字體
2種方法中前者簡單方便,後者靈活度高適用於大規模的GUI顯示
對於本人而言,使用uGUI還是用第1種方法更合適,如果必須進行大規模的GUI顯示,uGUI本身已經不適用,還是用Linux+Qt更合適