emWin實現BMP位圖皮膚之Dropdown篇

(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控件的自定義繪製函數

SKIN_dropdown.c

skinning.h

#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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章