久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5205|回復: 1
打印 上一主題 下一主題
收起左側

STEMWIN 自定義控件demo 學習使用官方沒有的控件 帶注釋

[復制鏈接]
跳轉到指定樓層
樓主
STemWin  無疑非常好用,系統提供的各種機制讓我們攻城尸 敲GUI代碼如虎添翼,事半功倍
可是仍然會遇到一些問題與困惑。  比如想要的功能系統沒有提供怎么辦,想用的控件沒有提供怎么辦。
STemWin 可以自定義控件嗎?  可以更改  原控件的行為嗎? 回答是肯定改變行為通過回調函數很容易辦到,
并且網上應該有大量教程代碼,這里就不介紹了。


舉個例子,假如開發一臺檢測 重量的東西,屏幕上根據重量顯示類似強度條一樣的東西,
并且 輕的時候強度條是綠色的重則是紅色, 由輕到重 從綠色到紅色漸變。 在使用 STemWin 想要實現這個功能,
應該沒有任何控件可以實現  唯一的實現方式是使用  底層繪圖函數。,但是這里有個問題,使用底層繪圖函數
則表示你拋棄了  WM管理器的各種功能,分層,重疊,渲染,無效化,回調!等等,這會使你開發其他地方很郁悶。

筆者正是希望有這樣一個控件而著手試著自定義一個控件。并將經驗傳授給大家拋磚引玉,以后大家都有自己的自定義控件
,更自由的使用STemWin。同時為了馬克下代碼 以免忘記

下面先傳兩張效果圖



沒有注釋  大家看的順序從

Create_demowidget 到 callback 就行了。

始終記得一點  WM管理器 通過 消息(callback) 來驅動 整個系統。


比如當你 的控件需要顯示的時候  WM管理器會往你的 callback 發送一條 WM_PAINT 消息,此時你負責把控件應該有的樣子顯示出來就OK了

而這正好是我們想要。,其他消息則使用 WM_DefaultProc 去處理好了。



相信沒有注釋  你也能看懂的!



下面是代碼  .h 和.c
  1. #include "WM.h"
  2. #include "DIALOG_Intern.h"      /* Req. for Create indirect data structure */
  3. #include "WIDGET.h"
  4. #include
  5. #include "..GUIIncludeGRAPH_Private.h"
  6. #define  DEMO_Widget_ID      0x34455854 /* DEMO_Widget */
  7. #define DEMO_Widget_INIT_ID(p) p->DebugId = DEMO_Widget_ID
  8. typedef struct {
  9.     WIDGET Widget;//第一項必須窗口 控件WM管理器使用
  10.     GUI_COLOR aBkColor[2];//根據需要添加  本控件 的兩項顏色值   分別為上圖的 背景黑色 和白色
  11.     GUI_COLOR RECT_Color;//上圖外框的藍色
  12.     WM_HMEM hpText;//未用到
  13.     WM_HMEM ahDrawObj[1];//未用到
  14.     int size_base;//中間最短一條的長度
  15.     GRAPH_PROPS Props;//盜用其他控件的  顏色, 繪外框的時候使用
  16.     uint16_t Sta_MAX;//控件的最大條數
  17.     uint16_t State;//當前顯示的 信息

  18. #if GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_ALL
  19.     int DebugId;
  20. #endif  
  21. } DEMO_Widget_Obj;
  22. GUI_HMEM Create_demowidget(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id);
  23. void Set_demowidget_Sta(GUI_HMEM hObj,int state);
  24. void Set_demowidget_Sta_MAX(GUI_HMEM hObj,int MAX);
  25. void Set_demowidget_Base(GUI_HMEM hObj,int base);
復制代碼



下面是 .c
  1. #include "demowidget.h"
  2. //這個函數負責顯示  控件的外觀  主要是調用一下  GUI 2D  繪圖函數或者 有必要的話顯示文本
  3. void _Paint(DEMO_Widget_Obj *pObj,GUI_HMEM hObj,GUI_RECT * pRectInvalid)
  4. {  
  5.         GUI_RECT RectClient;
  6.         int i,size_x;
  7.         GUI_RECT rClient, rInside,Rect={0,0,0,0},Rect1={0,0,0,0},Rect2={0,0,0,0};
  8.       GUI_GetClientRect(&RectClient);
  9.       rClient = RectClient;
  10.       Rect=rClient;
  11.       GUI_Clear();
  12.       GUI_SetBkColor(pObj->Props.aColor[1]);
  13.       GUI_SetColor(pObj->Props.aColor[2]);

  14.       GUI_DrawRectEx(&Rect);
  15.       GUI__ReduceRect(&Rect, &Rect, 1);
  16.       GUI_DrawRectEx(&Rect);
  17.       Rect=rClient;

  18.       GUI__ReduceRect(&rClient, &rClient, 3);
  19.       LCD_SetBkColor (pObj->aBkColor[0]);
  20.       LCD_SetColor   (pObj->RECT_Color);
  21.       size_x=(rClient.x1-pObj->size_base+1)/2/pObj->Sta_MAX;
  22.       Rect.x0=rClient.x0+pObj->Sta_MAX*size_x;
  23.       Rect.x1=rClient.x1-pObj->Sta_MAX*size_x;
  24.       Rect.y1=(rClient.y1/2)+rClient.y1/(pObj->Sta_MAX*2+1)/2-1;
  25.       Rect.y0=(rClient.y1/2)-rClient.y1/(pObj->Sta_MAX*2+1)/2;
  26.       GUI__ReduceRect(&Rect1,&Rect,0);
  27.       GUI__ReduceRect(&Rect2,&Rect,0);
  28.       GUI_DrawRectEx(&Rect);
  29.       for(i=0;iSta_MAX;i++)
  30.       {
  31.           Rect1.x0+=-size_x;
  32.           Rect1.x1+=+size_x;
  33.           Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
  34.           Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
  35.           Rect2.x0+=-size_x;
  36.           Rect2.x1+=+size_x;
  37.           Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
  38.           Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
  39.           GUI_DrawRectEx(&Rect1);
  40.           GUI_DrawRectEx(&Rect2);
  41.       }
  42.       LCD_SetColor(GUI_GREEN);
  43.       LCD_SetBkColor (pObj->aBkColor[0]);
  44.       GUI__ReduceRect(&Rect1,&Rect,1);
  45.       GUI__ReduceRect(&Rect2,&Rect,1);
  46.       GUI_FillRectEx(&Rect1);
  47.       for(i=0;iState;i++)
  48.       {
  49.           LCD_SetColor((255-((255/pObj->Sta_MAX)*i)<<8)|((255/pObj->Sta_MAX*i)));
  50.           Rect1.x0+=-size_x;
  51.           Rect1.x1+=+size_x;
  52.           Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
  53.           Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
  54.           Rect2.x0+=-size_x;
  55.           Rect2.x1+=+size_x;
  56.           Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
  57.           Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
  58.           GUI_FillRectEx(&Rect1);
  59.           GUI_FillRectEx(&Rect2);
  60.       }
  61.       LCD_SetColor(pObj->aBkColor[1]);
  62.       for(;iSta_MAX;i++)
  63.       {
  64.           Rect1.x0+=-size_x;
  65.           Rect1.x1+=+size_x;
  66.           Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
  67.           Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
  68.           Rect2.x0+=-size_x;
  69.           Rect2.x1+=+size_x;
  70.           Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
  71.           Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
  72.           GUI_FillRectEx(&Rect1);
  73.           GUI_FillRectEx(&Rect2);
  74.       }
  75. }
  76. static void _Delete(DEMO_Widget_Obj* pObj) {
  77.     GUI_ALLOC_FreePtrArray(pObj->ahDrawObj, GUI_COUNTOF(pObj->ahDrawObj));
  78. }

  79. void DEMO_Widget_callback(WM_MESSAGE*pMsg)
  80. {
  81.     GUI_HMEM hObj=pMsg->hWin;
  82.     DEMO_Widget_Obj * pObj;
  83.     if (WIDGET_HandleActive(hObj, pMsg) == 0) {
  84.         return;
  85.     }
  86.      pObj= (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj);

  87.      switch(pMsg->MsgId)
  88.      {
  89.          case WM_PAINT://響應重繪命令,顯示自己 WM管理器在需要顯示的時候自動發送。
  90.              _Paint(pObj, hObj,(GUI_RECT*)pMsg->Data.p);
  91.              return;
  92. case WM_DELETE:
  93. _Delete(pObj);
  94. break; /* No return here ... WM_DefaultProc needs to be called */
  95. //刪除控件  這里不能return  因為需要WM_DefaultProc 迭代刪除子控件
  96. }
  97. WM_DefaultProc(pMsg);
  98. }

  99. GUI_HMEM Create_demowidget(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id)
  100. {
  101. GUI_HMEM hObj;
  102. GUI_USE_PARA(ExFlags);
  103. /* Create the window */
  104. WM_LOCK();
  105. hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, DEMO_Widget_callback,
  106. sizeof(DEMO_Widget_Obj) - sizeof(WM_Obj));
  107. //創建一個Window  小工具的靈魂, 靠它小工具才受WM管理器管理  各種WM管理器的功能才得以使用
  108. //這里需要注意  設置了N個字節的 userdata ,userdata  和創建的Window  實際使用的內存是連續的
  109. //
  110. if(hObj)
  111. {
  112. DEMO_Widget_Obj * pObj = (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj);
  113. //將Window   句柄轉換為DEMO_Widget_Obj   類型的指針  這里的轉換關系 需要  仔細思考!
  114. //上面提到userdata  和創建的Window  實際使用的內存是連續的  實際上 Window  實際使用的內存就是 WIDGET
  115. //這也是為什么一開始 說 DEMO_Widget_Obj 的第一項必須是 WIDGET  
  116. WIDGET__Init(&pObj->Widget, Id, WIDGET_STATE_FOCUSSABLE);
  117. DEMO_Widget_INIT_ID(pObj);//下面是設置一些默認屬性
  118. pObj->aBkColor[0]=GUI_BLACK;
  119. pObj->aBkColor[1]=GUI_WHITE;
  120. pObj->RECT_Color=GUI_BLUE;
  121. pObj->Sta_MAX=40;
  122. pObj->State=0;
  123. pObj->size_base=5;
  124. pObj->State=0;
  125. pObj->Props = GRAPH__DefaultProps;
  126. }
  127. else
  128. {
  129. GUI_DEBUG_ERROROUT_IF(hObj==0, "DEMO_Widget_Create failed")
  130. }
  131. WM_UNLOCK();
  132. return hObj;
  133. }

  134. //下面的函數都由應用程序  運行過程中調用,
  135. //按照格式改屬性然后  使用WM_InvalidateWindow 告訴 WM管理器  控件需要重繪就OK了
  136. void Set_demowidget_Sta(GUI_HMEM hObj,int state)
  137. {
  138. DEMO_Widget_Obj * pObj;
  139. if(hObj)
  140. {
  141. pObj= (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj); /* Don't use use WIDGET_H2P because WIDGET_INIT_ID() has not be called at this point */
  142. }
  143. else
  144. {
  145. return;
  146. }
  147. WM_LOCK();
  148. if(state<=pObj->Sta_MAX)
  149. pObj->State=state;
  150. WM_InvalidateWindow(hObj);
  151. WM_UNLOCK();
  152. }
  153. void Set_demowidget_Sta_MAX(GUI_HMEM hObj,int MAX)
  154. {
  155. DEMO_Widget_Obj * pObj;
  156. if(hObj)
  157. {
  158. pObj= (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj); /* Don't use use WIDGET_H2P because WIDGET_INIT_ID() has not be called at this point */
  159. }
  160. else
  161. {
  162. return;
  163. }
  164. WM_LOCK();
  165. pObj->Sta_MAX=MAX;
  166. WM_InvalidateWindow(hObj);
  167. WM_UNLOCK();
  168. }

  169. void Set_demowidget_Base(GUI_HMEM hObj,int base)
  170. {
  171. DEMO_Widget_Obj * pObj;
  172. if(hObj)
  173. {
  174. pObj= (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj); /* Don't use use WIDGET_H2P because WIDGET_INIT_ID() has not be called at this point */
  175. }
  176. else
  177. {
  178. return;
  179. }
  180. WM_LOCK();
  181. pObj->size_base=base;
  182. WM_InvalidateWindow(hObj);
  183. WM_UNLOCK();
  184. }
復制代碼



STemWin 樹形文件 目錄  執行 初始化速度 和 內存優化
不知道大家有沒有  這樣的應用,需要將磁盤上面的文件以列表方式顯示出來。,

TREEVIEW 無疑是最佳選擇了,可是 假如存在這樣一種情況,你的設備經常需要保存文件,  比如每個小時保存一個 文件  每天或者每個月一個文件夾
也許沒這么頻繁,但是無論如何  設備使用到一定時間  磁盤里面的文件數量將不可估量。
那么問題來了

第一、 樹形目錄  一個節點消耗100字節  一個樹葉 消耗  50字節 當你的文件成千上萬的時候  你的內存消耗得起么?
第二、眾所周知磁盤操作速度很慢的,就算你獲取文件名  同樣需要操作磁盤   當你的文件成千上萬的時候 你初始化這個 樹形結構 可能都需要10多秒甚至更多。
         別認為沒那么慢,筆者曾經在 NAND FLASH上使用JFFS2文件系統  從文件一個有500個子文件的文件夾中  遍歷檢索第  100-103 4個文件花的時間長達2s   
         當然這個 JFFS2這個文件系統有關系, 后來使用FATFS文件系統  就快了起來   但是第一點依然是很嚴重的問題


為解決這個問題   筆者提出一個方案。
初始化 TREE的時候只將第一層  節點添加進去,對于文件夾, 在節點內添加一個占位 葉節點,這樣看起來這個節點前面就有一個 +號可以被打開。
當打開這個節點的時候查看子節點是否為預添加的占位符, 如果是 再去遍歷   對應的文件夾,同時刪除占位符,添加節點。
如此  遍歷的時間由單個文件夾的文件數量決定,不會因為總數量 龐大而慢。
內存則由 打開過的文件決定, 甚至  當系統內存不足的是否可以 刪除被關閉的  節點內容 再次添加占位符。釋放內存。






那么現在方案有了  具體怎么實現呢?


這里筆者提供一個已經實現的  回調函數  callback
  1. TREEVIEW_ITEM_Handle Item_get_next(TREEVIEW_ITEM_Handle hItem)//用到輔助函數
  2. {
  3.     TREEVIEW_ITEM_OBJ *itemobj;
  4.     if(hItem)
  5.     {
  6.         itemobj=(TREEVIEW_ITEM_OBJ*)GUI_ALLOC_h2p(hItem);
  7.         return itemobj->hNext;
  8.     }
  9.     return 0;
  10. }

  11. void _cbtree(WM_MESSAGE * pMsg)
  12. {
  13.     int Id, NCode;
  14.     TREEVIEW_ITEM_Handle hItem,fristitem;
  15.     char buf[20];
  16.     int num[2]={1,2000};
  17.     TREEVIEW_ITEM_INFO info;
  18.     switch (pMsg->MsgId)
  19.     {
  20.     case WM_KEY://攔截 按鍵消息
  21.         {
  22.             int pressed;
  23.             pressed=((WM_KEY_INFO*)(pMsg->Data.p))->PressedCnt;
  24.             NCode = ((WM_KEY_INFO*)(pMsg->Data.p))->Key;

  25.             switch(NCode)
  26.             {
  27.             default:
  28.                 if(pressed)
  29.                 {
  30.                     if (NCode==GUI_KEY_RIGHT)// 樹默認right 鍵打開節點,再打開前  添加節點
  31.                     {
  32.                         hItem=TREEVIEW_GetSel(pMsg->hWin);
  33.                         TREEVIEW_ITEM_GetInfo(hItem,&info);
  34.                         if(info.IsNode)
  35.                         {
  36.                             fristitem=TREEVIEW_GetItem(pMsg->hWin,hItem,TREEVIEW_GET_FIRST_CHILD);
  37.                             TREEVIEW_ITEM_GetText(fristitem,(uint8_t*)buf,20);
  38.                             if(strcmp("space",buf)==0)//比較是否為占位符
  39.                             {
  40.                                 TREEVIEW_ITEM_Delete(fristitem);
  41.                                 tree_add_filelist(num,0,pMsg->hWin,hItem);//這個函數將  遍歷磁盤文件添加到樹 指定節點
  42.                             }
  43.                         }

  44.                     }
  45.                 }
  46.                 else
  47.                 {
  48.                     ((WM_KEY_INFO*)(pMsg->Data.p))->PressedCnt=1;
  49.                     TREEVIEW_Callback(pMsg);
  50.                 }
  51.                 break;
  52.             }
  53.         }
  54.         break;
  55.     case WM_TOUCH:// 這個是處理觸摸事件   比較麻煩一點  主要是獲得觸摸的地方, 遍歷TREE 取得被點擊的節點  判斷是否為 節點  然后的操作就和  按鍵一樣了
  56.         {
  57.             TREEVIEW_ITEM_Handle hNode;
  58.             GUI_PID_STATE* pState;
  59.             TREEVIEW_OBJ *treeobj;

  60.             pState     = (GUI_PID_STATE*)pMsg->Data.p;
  61.             treeobj       = (TREEVIEW_OBJ*)GUI_ALLOC_h2p(pMsg->hWin);
  62.             if(pState->y/treeobj->Props.MinItemHeight[tr]NumVisItems+1)
  63.             {
  64.                 hNode=TREEVIEW_GetItem(pMsg->hWin,0,TREEVIEW_GET_FIRST);
  65.                 if(hNode)
  66.                 {
  67.                     int num=pState->y/treeobj->Props.MinItemHeight +((pState->y%treeobj->Props.MinItemHeight)>0 ?1:0)-1;//計算被點擊的是第幾個節點
  68.                     if(treeobj->ScrollStateV.v>0)
  69.                         num+=treeobj->ScrollStateV.v;

  70.                     while(num--)//這個while  遍歷得到被點擊的  節點handle
  71.                     {
  72.                         TREEVIEW_ITEM_GetInfo(hNode,&info);
  73.                         if(info.IsNode)
  74.                         {
  75.                             if(info.IsExpanded)
  76.                             {
  77.                                 hNode=TREEVIEW_GetItem(pMsg->hWin,hNode,TREEVIEW_GET_FIRST_CHILD);
  78.                             }
  79.                             else
  80.                             {
  81.                                 hNode=TREEVIEW_GetItem(pMsg->hWin,hNode,TREEVIEW_GET_NEXT_SIBLING);
  82.                             }

  83.                         }
  84.                         else
  85.                         {
  86.                             hNode=Item_get_next(hNode);
  87.                         }
  88.                     }
  89.                 }
  90.                 TREEVIEW_ITEM_GetInfo(hNode,&info);
  91.                 if(info.IsExpanded==0)
  92.                 {
  93.                     if(info.IsNode&&(pState->x<((info.Level+1)*treeobj->Props.Indent-treeobj->ScrollStateH.v))&&
  94.                         pState->x>((info.Level)*treeobj->Props.Indent-treeobj->ScrollStateH.v)
  95.                         )
  96.                     {
  97.                         fristitem=TREEVIEW_GetItem(pMsg->hWin,hNode,TREEVIEW_GET_FIRST_CHILD);
  98.                         TREEVIEW_ITEM_GetText(fristitem,(uint8_t*)buf,20);
  99.                         if(strcmp("space",buf)==0)
  100.                         {
  101.                             TREEVIEW_ITEM_Delete(fristitem);
  102.                             tree_add_filelist(num,0,pMsg->hWin,hNode);
  103.                         }
  104.                     }
  105.                 }
  106.                 else
  107.                 {

  108.                 }
  109.                 TREEVIEW_Callback(pMsg);
  110.             }

  111.         }
  112.         break;
  113.     default:
  114.         TREEVIEW_Callback(pMsg);
  115.         break;
  116.     }

  117. }
復制代碼

效果圖片
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:404925 發表于 2020-3-24 15:19 | 只看該作者
厲害,樓主牛逼
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产二区三区 | 91精品在线播放 | 成人免费在线观看视频 | 四虎最新视频 | 日韩久久精品 | av影音资源 | 中文字幕一区二区三区日韩精品 | 欧美成人黄色小说 | 日韩午夜影院 | 久久久久亚洲 | 免费在线一区二区 | 最新国产精品精品视频 | 五月婷婷在线播放 | 91精品久久久久久久久 | 精品粉嫩超白一线天av | 亚洲免费在线观看 | 精品久久国产 | 色婷婷一区二区三区四区 | 99精品一区二区三区 | 操操网站| 久久久99国产精品免费 | av大片| 91视频a| 天堂资源视频 | 一级片子 | 日本黄色免费大片 | 男女激情网站免费 | 夜夜草天天草 | 欧美中文字幕一区 | xxx.在线观看 | 中文字幕在线精品 | 久在线精品视频 | 91中文在线观看 | 日韩高清成人 | 永久www成人看片 | av网站免费| 欧美一区二区三区 | 国产成人精品网站 | 日韩在线播放中文字幕 | 国产精品一区二区无线 | 日韩一区二区三区视频在线播放 |