(1)emWin通過skinning方式實現控件位圖皮膚:
1)emWin傳統貼皮膚圖片的方法,是調用APP函數XXXX_SetBitmap()方式實現,但非常非常麻煩。
2)要想把控件顯示出來,emWin每種控件都有1個控件繪製函數,而把這個控件繪製函數改成我們自己編寫的"自定義繪製函數",這樣我們想把這個控件畫成什麼樣都行,emWin已經不參與這個控件的繪製工作了;在這個自定義繪製函數裏面我們什麼都不幹,只顯示出這個控件的圖片,這就是用skinning方式實現位圖皮膚。
3)支持整幅圖片貼圖,不需要對整幅圖片進行切片分解,非常便捷。
如上圖所示,(x0,y0)爲整幅圖片的顯示座標,(x1,y1)和(x2,y2)是emWin爲控件自動生成的剪切顯示座標,我們只需要調用GUI_DrawBitmap()函數在(x0,y0)顯示整幅圖片即可,emWin會自動剪切顯示出該控件的位圖皮膚,功能非常強大。
(2)Dropdown控件的自定義繪製函數:
#include "DIALOG.h"
#include "gui.h"
#include "skinning.h"
//獲取父窗口句柄,即主頁面句柄,保存着頁面位圖的指針
static WM_HWIN WM_GetParent1C(WM_HWIN hChild) {return hChild;}
static WM_HWIN WM_GetParent2C(WM_HWIN hChild) {return WM_GetParent(hChild);}
static WM_HWIN WM_GetParent3C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(hChild));}
static WM_HWIN WM_GetParent4C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(hChild)));}
static WM_HWIN WM_GetParent5C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild))));}
static WM_HWIN WM_GetParent6C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild)))));}
static WM_HWIN WM_GetParent7C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild))))));}
static WM_HWIN WM_GetParent8C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild)))))));}
static WM_HWIN (*WM_GET_PARENT[])(WM_HWIN) = {WM_GetParent1C,WM_GetParent2C,WM_GetParent3C,WM_GetParent4C,WM_GetParent5C,WM_GetParent6C,WM_GetParent7C,WM_GetParent8C};
//Dropdown控件的自定義繪製函數
int SKIN_dropdown(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo, unsigned char C)
{
WM_HWIN hWin;
int x0, y0;
WINDOW_BMP *winBMP;
GUI_BITMAP *pBMP;
switch (pDrawItemInfo->Cmd)
{
case WIDGET_ITEM_CREATE:
case WIDGET_ITEM_DRAW_ARROW:
//case WIDGET_ITEM_DRAW_BACKGROUND:
//case WIDGET_ITEM_DRAW_TEXT:
break;
default: return DROPDOWN_DrawSkinFlex(pDrawItemInfo);//emWin默認控件繪製函數
case WIDGET_ITEM_DRAW_BACKGROUND:
hWin = (WM_GET_PARENT[C-1])(pDrawItemInfo->hWin);//位於第幾層修改這裏(WM_GetParent數=層數-1)
WM_GetUserData(hWin, &winBMP, sizeof(winBMP));//從用戶數據區讀出"頁面圖片結構體"指針
//獲取此控件相對於主頁面(比如:WINDOW)位置偏移座標
x0 = WM_GetWindowOrgX(hWin) - WM_GetWindowOrgX(pDrawItemInfo->hWin);
y0 = WM_GetWindowOrgY(hWin) -WM_GetWindowOrgY(pDrawItemInfo->hWin);
//備註:pDrawItemInfo->ItemIndex有BUG,無法定位狀態
if(pDrawItemInfo->ItemIndex == DROPDOWN_SKINFLEX_PI_ENABLED)
GUI_DrawBitmap(winBMP->normal, x0, y0);//從頁面座標顯示圖片,emWin會自己剪切出這個控件範圍的圖片
else if(pDrawItemInfo->ItemIndex == DROPDOWN_SKINFLEX_PI_EXPANDED)
GUI_DrawBitmap(winBMP->mark, x0, y0);
else if(pDrawItemInfo->ItemIndex == DROPDOWN_SKINFLEX_PI_FOCUSSED)
GUI_DrawBitmap(winBMP->focus, x0, y0);
else if(pDrawItemInfo->ItemIndex == DROPDOWN_SKINFLEX_PI_DISABLED)
GUI_DrawBitmap(winBMP->disable, x0, y0);
else
GUI_DrawBitmap(winBMP->normal, x0, y0);
break;
}
return 0;
}
//Dropdown控件的自定義繪製函數,位於第2層(比如:WINDOW->DROPDOWN)
int SKIN_dropdown2C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){
return SKIN_dropdown(pDrawItemInfo, 2);
}
//Dropdown控件的自定義繪製函數,位於第3層(比如:FRAMEWIN->CLIENT->DROPDOWN)
int SKIN_dropdown3C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){
return SKIN_dropdown(pDrawItemInfo, 3);
}
//Dropdown控件的自定義繪製函數,位於第4層(比如:WINDOW->FRAMEWIN->CLIENT->DROPDOWN)
int SKIN_dropdown4C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){
return SKIN_dropdown(pDrawItemInfo, 4);
}
//Dropdown控件的自定義繪製函數,位於第5層(比如:WINDOW->MULTIPAGE->CLIENT->WINDOW->DROPDOWN)
int SKIN_dropdown5C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){
return SKIN_dropdown(pDrawItemInfo, 5);
}
(3)Skinning方式實現位圖皮膚的實施步驟:
1)創建窗體時,將"頁面圖片結構體指針"保存於窗體中:
WINDOW_BMP *winBMP;
static WINDOW_BMP BMP_WIN_main;//爲"WIN_main"頁面定義1個"頁面圖片結構體"
BMP_WIN_main.normal = &bmPage2_N;//將不同狀態的頁面BMP位圖賦值給"頁面圖片結構體"
BMP_WIN_main.mark = &bmPage2_M;
BMP_WIN_main.focus = &bmPage2_N;
BMP_WIN_main.disable = &bmPage2_N;
BMP_WIN_main.thumbN = &bmPage2_N;
BMP_WIN_main.thumbM = &bmPage2_N;
winBMP = &BMP_WIN_main;
hWin = CreateWindow2(WM_HBKWIN);//創建WINmain頁面
WM_SetUserData(hWin, &winBMP, sizeof(winBMP));//將"頁面圖片結構體"指針寫到用戶數據區
2)在窗體初始化WM_INIT_DIALOG消息中,把DROPDOWN控件的繪製函數改成自定義繪製函數:
hItem = WM_GetDialogItem(pMsg->hWin, ID_DROPDOWN_0);//獲取句柄
DROPDOWN_SetSkin(hItem, SKIN_dropdown2C);//將這個DROPDOWN控件改成自定義繪製函數
(4)總結:
以整幅圖片實現emWin位圖皮膚應該是諾嵌光電業界首創的方法,可以大大減輕控件貼圖的工作量,保守估計貼圖工作效率至少提高10倍以上。如果把每個控件對應的圖片先切片分解下來,然後再轉換成C文件,最後再貼圖到控件上面去,那樣工作量將是非常恐怖的!
源碼下載: \docs\demoEM\demo_emwin_CodeBlocks\skinPRJ_WINemWin530noOS_CodeBlocks_v127.rar
如何打開源碼看博文:emWin
2天速成實例教程000_如何快速入門ucGUI/emWin