你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STEMWIN 自定义控件demo 学习使用官方没有的控件 带注释 精华  

[复制链接]
lovewyufeng 发布时间:2014-12-12 14:50
本帖最后由 lovewyufeng 于 2014-12-13 23:11 编辑

STemWin  无疑非常好用,系统提供的各种机制让我们攻城尸 敲GUI代码如虎添翼,事半功倍
可是仍然会遇到一些问题与困惑。  比如想要的功能系统没有提供怎么办,想用的控件没有提供怎么办。
STemWin 可以自定义控件吗?  可以更改  原控件的行为吗? 回答是肯定改变行为通过回调函数很容易办到,
并且网上应该有大量教程代码,这里就不介绍了。


举个例子,假如开发一台检测 重量的东西,屏幕上根据重量显示类似强度条一样的东西,
并且 轻的时候强度条是绿色的重则是红色, 由轻到重 从绿色到红色渐变。 在使用 STemWin 想要实现这个功能,
应该没有任何控件可以实现  唯一的实现方式是使用  底层绘图函数。,但是这里有个问题,使用底层绘图函数
则表示你抛弃了  WM管理器的各种功能,分层,重叠,渲染,无效化,回调!等等,这会使你开发其他地方很郁闷。

笔者正是希望有这样一个控件而着手试着自定义一个控件。并将经验传授给大家抛砖引玉,以后大家都有自己的自定义控件
,更自由的使用STemWin。同时为了马克下代码 以免忘记

下面先传两张效果图
QQ图片20141212143733.png QQ图片20141212143942.png


没有注释  大家看的顺序从

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 <stdint.h>
  5. #include "..\GUI\Include\GRAPH_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);


  26. 下面是 .c

  27. #include "demowidget.h"
  28. //这个函数负责显示  控件的外观  主要是调用一下  GUI 2D  绘图函数或者 有必要的话显示文本
  29. void _Paint(DEMO_Widget_Obj *pObj,GUI_HMEM hObj,GUI_RECT * pRectInvalid)
  30. {  
  31.         GUI_RECT RectClient;
  32.         int i,size_x;
  33.         GUI_RECT rClient, rInside,Rect={0,0,0,0},Rect1={0,0,0,0},Rect2={0,0,0,0};
  34.       GUI_GetClientRect(&RectClient);
  35.       rClient = RectClient;
  36.       Rect=rClient;
  37.       GUI_Clear();
  38.       GUI_SetBkColor(pObj->Props.aColor[1]);
  39.       GUI_SetColor(pObj->Props.aColor[2]);

  40.       GUI_DrawRectEx(&Rect);
  41.       GUI__ReduceRect(&Rect, &Rect, 1);
  42.       GUI_DrawRectEx(&Rect);
  43.       Rect=rClient;

  44.       GUI__ReduceRect(&rClient, &rClient, 3);
  45.       LCD_SetBkColor (pObj->aBkColor[0]);
  46.       LCD_SetColor   (pObj->RECT_Color);
  47.       size_x=(rClient.x1-pObj->size_base+1)/2/pObj->Sta_MAX;
  48.       Rect.x0=rClient.x0+pObj->Sta_MAX*size_x;
  49.       Rect.x1=rClient.x1-pObj->Sta_MAX*size_x;
  50.       Rect.y1=(rClient.y1/2)+rClient.y1/(pObj->Sta_MAX*2+1)/2-1;
  51.       Rect.y0=(rClient.y1/2)-rClient.y1/(pObj->Sta_MAX*2+1)/2;
  52.       GUI__ReduceRect(&Rect1,&Rect,0);
  53.       GUI__ReduceRect(&Rect2,&Rect,0);
  54.       GUI_DrawRectEx(&Rect);
  55.       for(i=0;i<pObj->Sta_MAX;i++)
  56.       {
  57.           Rect1.x0+=-size_x;
  58.           Rect1.x1+=+size_x;
  59.           Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
  60.           Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
  61.           Rect2.x0+=-size_x;
  62.           Rect2.x1+=+size_x;
  63.           Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
  64.           Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
  65.           GUI_DrawRectEx(&Rect1);
  66.           GUI_DrawRectEx(&Rect2);
  67.       }
  68.       LCD_SetColor(GUI_GREEN);
  69.       LCD_SetBkColor (pObj->aBkColor[0]);
  70.       GUI__ReduceRect(&Rect1,&Rect,1);
  71.       GUI__ReduceRect(&Rect2,&Rect,1);
  72.       GUI_FillRectEx(&Rect1);
  73.       for(i=0;i<pObj->State;i++)
  74.       {
  75.           LCD_SetColor((255-((255/pObj->Sta_MAX)*i)<<8)|((255/pObj->Sta_MAX*i)));
  76.           Rect1.x0+=-size_x;
  77.           Rect1.x1+=+size_x;
  78.           Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
  79.           Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
  80.           Rect2.x0+=-size_x;
  81.           Rect2.x1+=+size_x;
  82.           Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
  83.           Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
  84.           GUI_FillRectEx(&Rect1);
  85.           GUI_FillRectEx(&Rect2);
  86.       }
  87.       LCD_SetColor(pObj->aBkColor[1]);
  88.       for(;i<pObj->Sta_MAX;i++)
  89.       {
  90.           Rect1.x0+=-size_x;
  91.           Rect1.x1+=+size_x;
  92.           Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
  93.           Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
  94.           Rect2.x0+=-size_x;
  95.           Rect2.x1+=+size_x;
  96.           Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
  97.           Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
  98.           GUI_FillRectEx(&Rect1);
  99.           GUI_FillRectEx(&Rect2);
  100.       }
  101. }
  102. static void _Delete(DEMO_Widget_Obj* pObj) {
  103.     GUI_ALLOC_FreePtrArray(pObj->ahDrawObj, GUI_COUNTOF(pObj->ahDrawObj));
  104. }

  105. void DEMO_Widget_callback(WM_MESSAGE*pMsg)
  106. {
  107.     GUI_HMEM hObj=pMsg->hWin;
  108.     DEMO_Widget_Obj * pObj;
  109.     if (WIDGET_HandleActive(hObj, pMsg) == 0) {
  110.         return;
  111.     }
  112.      pObj= (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj);

  113.      switch(pMsg->MsgId)
  114.      {
  115.          case WM_PAINT://响应重绘命令,显示自己 WM管理器在需要显示的时候自动发送。
  116.              _Paint(pObj, hObj,(GUI_RECT*)pMsg->Data.p);
  117.              return;
  118. case WM_DELETE:
  119. _Delete(pObj);
  120. break; /* No return here ... WM_DefaultProc needs to be called */
  121. //删除控件  这里不能return  因为需要WM_DefaultProc 迭代删除子控件
  122. }
  123. WM_DefaultProc(pMsg);
  124. }

  125. GUI_HMEM Create_demowidget(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id)
  126. {
  127. GUI_HMEM hObj;
  128. GUI_USE_PARA(ExFlags);
  129. /* Create the window */
  130. WM_LOCK();
  131. hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, DEMO_Widget_callback,
  132. sizeof(DEMO_Widget_Obj) - sizeof(WM_Obj));
  133. //创建一个Window  小工具的灵魂, 靠它小工具才受WM管理器管理  各种WM管理器的功能才得以使用
  134. //这里需要注意  设置了N个字节的 userdata ,userdata  和创建的Window  实际使用的内存是连续的
  135. //
  136. if(hObj)
  137. {
  138. DEMO_Widget_Obj * pObj = (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj);
  139. //将Window   句柄转换为DEMO_Widget_Obj   类型的指针  这里的转换关系 需要  仔细思考!
  140. //上面提到userdata  和创建的Window  实际使用的内存是连续的  实际上 Window  实际使用的内存就是 WIDGET
  141. //这也是为什么一开始 说 DEMO_Widget_Obj 的第一项必须是 WIDGET  
  142. WIDGET__Init(&pObj->Widget, Id, WIDGET_STATE_FOCUSSABLE);
  143. DEMO_Widget_INIT_ID(pObj);//下面是设置一些默认属性
  144. pObj->aBkColor[0]=GUI_BLACK;
  145. pObj->aBkColor[1]=GUI_WHITE;
  146. pObj->RECT_Color=GUI_BLUE;
  147. pObj->Sta_MAX=40;
  148. pObj->State=0;
  149. pObj->size_base=5;
  150. pObj->State=0;
  151. pObj->Props = GRAPH__DefaultProps;
  152. }
  153. else
  154. {
  155. GUI_DEBUG_ERROROUT_IF(hObj==0, "DEMO_Widget_Create failed")
  156. }
  157. WM_UNLOCK();
  158. return hObj;
  159. }

  160. //下面的函数都由应用程序  运行过程中调用,
  161. //按照格式改属性然后  使用WM_InvalidateWindow 告诉 WM管理器  控件需要重绘就OK了
  162. void Set_demowidget_Sta(GUI_HMEM hObj,int state)
  163. {
  164. DEMO_Widget_Obj * pObj;
  165. if(hObj)
  166. {
  167. 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 */
  168. }
  169. else
  170. {
  171. return;
  172. }
  173. WM_LOCK();
  174. if(state<=pObj->Sta_MAX)
  175. pObj->State=state;
  176. WM_InvalidateWindow(hObj);
  177. WM_UNLOCK();
  178. }
  179. void Set_demowidget_Sta_MAX(GUI_HMEM hObj,int MAX)
  180. {
  181. DEMO_Widget_Obj * pObj;
  182. if(hObj)
  183. {
  184. 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 */
  185. }
  186. else
  187. {
  188. return;
  189. }
  190. WM_LOCK();
  191. pObj->Sta_MAX=MAX;
  192. WM_InvalidateWindow(hObj);
  193. WM_UNLOCK();
  194. }

  195. void Set_demowidget_Base(GUI_HMEM hObj,int base)
  196. {
  197. DEMO_Widget_Obj * pObj;
  198. if(hObj)
  199. {
  200. 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 */
  201. }
  202. else
  203. {
  204. return;
  205. }
  206. WM_LOCK();
  207. pObj->size_base=base;
  208. WM_InvalidateWindow(hObj);
  209. WM_UNLOCK();
  210. }
复制代码


继续阅读:
树形 文件 目录  执行 初始化速度 和 内存优化


收藏 5 评论35 发布时间:2014-12-12 14:50

举报

35个回答
lovewyufeng 回答时间:2014-12-13 22:47:04

#include "WM.h"
#include "DIALOG_Intern.h"      /* Req. for Create indirect data structure */
#include "WIDGET.h"
#include <stdint.h>
#include "..\GUI\Include\GRAPH_Private.h"
#define  DEMO_Widget_ID      0x34455854 /* DEMO_Widget */
#define DEMO_Widget_INIT_ID(p) p->DebugId = DEMO_Widget_ID
typedef struct {
    WIDGET Widget;//第一项必须窗口 控件WM管理器使用
    GUI_COLOR aBkColor[2];//根据需要添加  本控件 的两项颜色值   分别为上图的 背景黑色 和白色
    GUI_COLOR RECT_Color;//上图外框的蓝色
    WM_HMEM hpText;//未用到
    WM_HMEM ahDrawObj[1];//未用到
    int size_base;//中间最短一条的长度
    GRAPH_PROPS Props;//盗用其他控件的  颜色, 绘外框的时候使用
    uint16_t Sta_MAX;//控件的最大条数
    uint16_t State;//当前显示的 信息

#if GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_ALL
    int DebugId;
#endif  
} DEMO_Widget_Obj;
GUI_HMEM Create_demowidget(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id);
void Set_demowidget_Sta(GUI_HMEM hObj,int state);
void Set_demowidget_Sta_MAX(GUI_HMEM hObj,int MAX);
void Set_demowidget_Base(GUI_HMEM hObj,int base);


下面是 .c

#include "demowidget.h"
//这个函数负责显示  控件的外观  主要是调用一下  GUI 2D  绘图函数或者 有必要的话显示文本
void _Paint(DEMO_Widget_Obj *pObj,GUI_HMEM hObj,GUI_RECT * pRectInvalid)
{  
        GUI_RECT RectClient;
        int i,size_x;
        GUI_RECT rClient, rInside,Rect={0,0,0,0},Rect1={0,0,0,0},Rect2={0,0,0,0};
      GUI_GetClientRect(&RectClient);
      rClient = RectClient;
      Rect=rClient;
      GUI_Clear();
      GUI_SetBkColor(pObj->Props.aColor[1]);
      GUI_SetColor(pObj->Props.aColor[2]);

      GUI_DrawRectEx(&Rect);
      GUI__ReduceRect(&Rect, &Rect, 1);
      GUI_DrawRectEx(&Rect);
      Rect=rClient;

      GUI__ReduceRect(&rClient, &rClient, 3);
      LCD_SetBkColor (pObj->aBkColor[0]);
      LCD_SetColor   (pObj->RECT_Color);
      size_x=(rClient.x1-pObj->size_base+1)/2/pObj->Sta_MAX;
      Rect.x0=rClient.x0+pObj->Sta_MAX*size_x;
      Rect.x1=rClient.x1-pObj->Sta_MAX*size_x;
      Rect.y1=(rClient.y1/2)+rClient.y1/(pObj->Sta_MAX*2+1)/2-1;
      Rect.y0=(rClient.y1/2)-rClient.y1/(pObj->Sta_MAX*2+1)/2;
      GUI__ReduceRect(&Rect1,&Rect,0);
      GUI__ReduceRect(&Rect2,&Rect,0);
      GUI_DrawRectEx(&Rect);
      for(i=0;i<pObj->Sta_MAX;i++)
      {
          Rect1.x0+=-size_x;
          Rect1.x1+=+size_x;
          Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
          Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
          Rect2.x0+=-size_x;
          Rect2.x1+=+size_x;
          Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
          Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
          GUI_DrawRectEx(&Rect1);
          GUI_DrawRectEx(&Rect2);
      }
      LCD_SetColor(GUI_GREEN);
      LCD_SetBkColor (pObj->aBkColor[0]);
      GUI__ReduceRect(&Rect1,&Rect,1);
      GUI__ReduceRect(&Rect2,&Rect,1);
      GUI_FillRectEx(&Rect1);
      for(i=0;i<pObj->State;i++)
      {
          LCD_SetColor((255-((255/pObj->Sta_MAX)*i)<<8)|((255/pObj->Sta_MAX*i)));
          Rect1.x0+=-size_x;
          Rect1.x1+=+size_x;
          Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
          Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
          Rect2.x0+=-size_x;
          Rect2.x1+=+size_x;
          Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
          Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
          GUI_FillRectEx(&Rect1);
          GUI_FillRectEx(&Rect2);
      }
      LCD_SetColor(pObj->aBkColor[1]);
      for(;i<pObj->Sta_MAX;i++)
      {
          Rect1.x0+=-size_x;
          Rect1.x1+=+size_x;
          Rect1.y0+=-rClient.y1/(pObj->Sta_MAX)/2;
          Rect1.y1+=-rClient.y1/(pObj->Sta_MAX)/2;
          Rect2.x0+=-size_x;
          Rect2.x1+=+size_x;
          Rect2.y0+=+rClient.y1/(pObj->Sta_MAX)/2;
          Rect2.y1+=+rClient.y1/(pObj->Sta_MAX)/2;
          GUI_FillRectEx(&Rect1);
          GUI_FillRectEx(&Rect2);
      }
}
static void _Delete(DEMO_Widget_Obj* pObj) {
    GUI_ALLOC_FreePtrArray(pObj->ahDrawObj, GUI_COUNTOF(pObj->ahDrawObj));
}

void DEMO_Widget_callback(WM_MESSAGE*pMsg)
{
    GUI_HMEM hObj=pMsg->hWin;
    DEMO_Widget_Obj * pObj;
    if (WIDGET_HandleActive(hObj, pMsg) == 0) {
        return;
    }
     pObj= (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj);

     switch(pMsg->MsgId)
     {
         case WM_PAINT://响应重绘命令,显示自己 WM管理器在需要显示的时候自动发送。
             _Paint(pObj, hObj,(GUI_RECT*)pMsg->Data.p);
lovewyufeng 回答时间:2014-12-13 23:03:04

  1.              return;
  2.          case WM_DELETE:
  3.              _Delete(pObj);
  4.              break;       /* No return here ... WM_DefaultProc needs to be called */
复制代码


lovewyufeng 回答时间:2014-12-13 22:52:46
巅峰残狼 发表于 2014-12-12 15:03
嗯,很不错,谢谢分享


   QQ截图20141213224901.png

写了两次  提交之后  代码就只剩下一点点了!!!真心不想再写了  版主能解释一下么
巅峰残狼 回答时间:2014-12-12 15:03:09
嗯,很不错,谢谢分享
迷途的羔羊-1901330 回答时间:2014-12-12 15:06:05
不错,学习了
Paphiopedilum 回答时间:2014-12-12 15:28:35
我只能默默的顶一下了
lovewyufeng 回答时间:2014-12-12 15:55:11
没有 人要求  上注释  
我就认为大家都看懂了哈
沐紫 回答时间:2014-12-12 16:30:17
lovewyufeng 发表于 2014-12-12 15:55
没有 人要求  上注释  
我就认为大家都看懂了哈

楼主还是上贴一下注释?可能有的朋友没看懂,但是没好意思说。
沐紫 回答时间:2014-12-12 16:30:17
lovewyufeng 发表于 2014-12-12 15:55
没有 人要求  上注释  
我就认为大家都看懂了哈

楼主还是上贴一下注释?可能有的朋友没看懂,但是没好意思说。

谢过
lovewyufeng 回答时间:2014-12-12 17:34:03
沐紫 发表于 2014-12-12 16:30
楼主还是上贴一下注释?可能有的朋友没看懂,但是没好意思说。

谢过

还不太会 编辑  帖子内容, 注释  改天奉上!

帖子不要沉
大器所成 回答时间:2014-12-12 21:02:17
既然没人好意思说上注释,那我说吧,求注释!!!!
lovewyufeng 回答时间:2014-12-12 21:07:07
大器所成 发表于 2014-12-12 21:02
既然没人好意思说上注释,那我说吧,求注释!!!!

明晚 上注释哈 ,今晚有事情
lovewyufeng 回答时间:2014-12-13 22:21:38
大器所成 发表于 2014-12-12 21:02
既然没人好意思说上注释,那我说吧,求注释!!!!

已注释  欢迎顶贴!
lovewyufeng 回答时间:2014-12-13 22:41:33
察。。。注释完了。。。提交 再查看没有内容了,,,只好返回 重新写注释  累死俺了
lovewyufeng 回答时间:2014-12-13 22:50:49
QQ截图20141213224901.png

写了两次  提交之后  代码就只剩下一点点了!!!真心不想再写了  版主能解释一下么
123下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版