本帖最后由 lovewyufeng 于 2014-12-13 23:11 编辑
STemWin 无疑非常好用,系统提供的各种机制让我们攻城尸 敲GUI代码如虎添翼,事半功倍
可是仍然会遇到一些问题与困惑。 比如想要的功能系统没有提供怎么办,想用的控件没有提供怎么办。
STemWin 可以自定义控件吗? 可以更改 原控件的行为吗? 回答是肯定改变行为通过回调函数很容易办到,
并且网上应该有大量教程代码,这里就不介绍了。
举个例子,假如开发一台检测 重量的东西,屏幕上根据重量显示类似强度条一样的东西,
并且 轻的时候强度条是绿色的重则是红色, 由轻到重 从绿色到红色渐变。 在使用 STemWin 想要实现这个功能,
应该没有任何控件可以实现 唯一的实现方式是使用 底层绘图函数。,但是这里有个问题,使用底层绘图函数
则表示你抛弃了 WM管理器的各种功能,分层,重叠,渲染,无效化,回调!等等,这会使你开发其他地方很郁闷。
笔者正是希望有这样一个控件而着手试着自定义一个控件。并将经验传授给大家抛砖引玉,以后大家都有自己的自定义控件
,更自由的使用STemWin。同时为了马克下代码 以免忘记
下面先传两张效果图
没有注释 大家看的顺序从
Create_demowidget 到 callback 就行了。
始终记得一点 WM管理器 通过 消息(callback) 来驱动 整个系统。
比如当你 的控件需要显示的时候 WM管理器会往你的 callback 发送一条 WM_PAINT 消息,此时你负责把控件应该有的样子显示出来就OK了
而这正好是我们想要。,其他消息则使用 WM_DefaultProc 去处理好了。
相信没有注释 你也能看懂的!
下面是代码 .h 和.c
- #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);
- return;
- case WM_DELETE:
- _Delete(pObj);
- break; /* No return here ... WM_DefaultProc needs to be called */
- //删除控件 这里不能return 因为需要WM_DefaultProc 迭代删除子控件
- }
- WM_DefaultProc(pMsg);
- }
- GUI_HMEM Create_demowidget(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id)
- {
- GUI_HMEM hObj;
- GUI_USE_PARA(ExFlags);
- /* Create the window */
- WM_LOCK();
- hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, DEMO_Widget_callback,
- sizeof(DEMO_Widget_Obj) - sizeof(WM_Obj));
- //创建一个Window 小工具的灵魂, 靠它小工具才受WM管理器管理 各种WM管理器的功能才得以使用
- //这里需要注意 设置了N个字节的 userdata ,userdata 和创建的Window 实际使用的内存是连续的
- //
- if(hObj)
- {
- DEMO_Widget_Obj * pObj = (DEMO_Widget_Obj *)GUI_ALLOC_h2p(hObj);
- //将Window 句柄转换为DEMO_Widget_Obj 类型的指针 这里的转换关系 需要 仔细思考!
- //上面提到userdata 和创建的Window 实际使用的内存是连续的 实际上 Window 实际使用的内存就是 WIDGET
- //这也是为什么一开始 说 DEMO_Widget_Obj 的第一项必须是 WIDGET
- WIDGET__Init(&pObj->Widget, Id, WIDGET_STATE_FOCUSSABLE);
- DEMO_Widget_INIT_ID(pObj);//下面是设置一些默认属性
- pObj->aBkColor[0]=GUI_BLACK;
- pObj->aBkColor[1]=GUI_WHITE;
- pObj->RECT_Color=GUI_BLUE;
- pObj->Sta_MAX=40;
- pObj->State=0;
- pObj->size_base=5;
- pObj->State=0;
- pObj->Props = GRAPH__DefaultProps;
- }
- else
- {
- GUI_DEBUG_ERROROUT_IF(hObj==0, "DEMO_Widget_Create failed")
- }
- WM_UNLOCK();
- return hObj;
- }
- //下面的函数都由应用程序 运行过程中调用,
- //按照格式改属性然后 使用WM_InvalidateWindow 告诉 WM管理器 控件需要重绘就OK了
- void Set_demowidget_Sta(GUI_HMEM hObj,int state)
- {
- DEMO_Widget_Obj * pObj;
- if(hObj)
- {
- 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 */
- }
- else
- {
- return;
- }
- WM_LOCK();
- if(state<=pObj->Sta_MAX)
- pObj->State=state;
- WM_InvalidateWindow(hObj);
- WM_UNLOCK();
- }
- void Set_demowidget_Sta_MAX(GUI_HMEM hObj,int MAX)
- {
- DEMO_Widget_Obj * pObj;
- if(hObj)
- {
- 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 */
- }
- else
- {
- return;
- }
- WM_LOCK();
- pObj->Sta_MAX=MAX;
- WM_InvalidateWindow(hObj);
- WM_UNLOCK();
- }
- void Set_demowidget_Base(GUI_HMEM hObj,int base)
- {
- DEMO_Widget_Obj * pObj;
- if(hObj)
- {
- 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 */
- }
- else
- {
- return;
- }
- WM_LOCK();
- pObj->size_base=base;
- WM_InvalidateWindow(hObj);
- WM_UNLOCK();
- }
复制代码
继续阅读:
树形 文件 目录 执行 初始化速度 和 内存优化
|
#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);
写了两次 提交之后 代码就只剩下一点点了!!!真心不想再写了 版主能解释一下么
我就认为大家都看懂了哈
楼主还是上贴一下注释?可能有的朋友没看懂,但是没好意思说。
楼主还是上贴一下注释?可能有的朋友没看懂,但是没好意思说。
谢过
还不太会 编辑 帖子内容, 注释 改天奉上!
帖子不要沉
明晚 上注释哈 ,今晚有事情
已注释 欢迎顶贴!
写了两次 提交之后 代码就只剩下一点点了!!!真心不想再写了 版主能解释一下么