制作emwin个性化控件

在之前的某个项目中用到了emwin图形库,有些想要的效果官方的控件无法实现,所以就研究了一下,自己做了几个可以嵌入到emwin官方库的控件.

本文实现的check button和这个有些像(原谅我随便在网上截了个图,硬件暂时不在,等硬件到了会补)没有选中是是一个空心框,选中后是一个实心框,功能和emwin中的checkbox相同,可以认为是checkbox的重写版本,相对官方控件这个更大比较适合触屏的界面,风格也简洁些,更没有旁边一坨丑了吧唧的文字。接口命名和官方保持一致,支持xx_CreateEx和资源列表等所有控件创建方式,还有一些常用参数设置函数。

Check button继承自父控件windows,通过覆盖windows的callback函数实现自定义效果,除父控件windows自身的参数外, check button新增加的相关数据通过userdata的方式存储,另外还需实现check button自身xx_GetUserData和xx_SetUserData函数,用于check button的子类派生。

Checkbutton自身参数结构体如下,主要是控件尺寸和颜色,及开关状态信息。

控件直接创建函数如下,主要是通过传来的参数创建了一个window控件,控件回调使用checkbutton默认回调函数。

注意127行,这个是check button的默认参数,在未设置check button显示参数时会使用这组值。

下面是以资源列表方式创建check button控件的入口函数,相对复杂一点,因为emwin会传入一个资源列表的结构体,需要从结构体中提取出需要的参数。

我们再来看看核心的回调函数是如何实现的

/*********************************************************************
*
*       CheckButton工具默认回调函数
*/
void CHECKBUTTON_Callback(WM_MESSAGE *pMsg)
{
//  WM_HWIN hItem;
//  int     NCode;
//  int     Id;
  static unsigned char tsign=0;
  GUI_RECT area;
  GUI_PID_STATE *pPID;
  CHECK_BUTTON_ITEM RBItem;
  
  WINDOW_GetUserData(pMsg->hWin,&RBItem,sizeof(CHECK_BUTTON_ITEM));//获取自定义数据
  

  switch (pMsg->MsgId) {
  
  case WM_TOUCH:
    pPID=(GUI_PID_STATE *)pMsg->Data.p;
    //点击事件
    if(pPID->Pressed==1)
    {
      //检查是否首次点击
      if(tsign==0)
      {
        WM_NotifyParent(pMsg->hWin,WM_NOTIFICATION_CLICKED);  //发送点击消息
        tsign=1;
        
        //切换状态
        if(RBItem.SWITCH_STATUS==CHECKBUTTON_ON)
          RBItem.SWITCH_STATUS=CHECKBUTTON_OFF;
        else if(RBItem.SWITCH_STATUS==CHECKBUTTON_OFF)
          RBItem.SWITCH_STATUS=CHECKBUTTON_ON;
        //写入数据
        WINDOW_SetUserData(pMsg->hWin,&RBItem,sizeof(CHECK_BUTTON_ITEM));  //写入具体数据
        WM_InvalidateWindow(pMsg->hWin);  //无效化窗口
        WM_NotifyParent(pMsg->hWin,WM_NOTIFICATION_VALUE_CHANGED);  //发送选择更改消息
      }
    }
    //释放事件
    if(pPID->Pressed==0)
    {
      WM_NotifyParent(pMsg->hWin,WM_NOTIFICATION_RELEASED);  //发送释放消息
      tsign=0;//归零点击标志
    }
    break;
  case WM_PAINT:
    //关闭状态时
    if(RBItem.SWITCH_STATUS==0)
    {
      //绘制空白区域
      GUI_SetColor(RBItem.BACK_COLOR);
      area.x0=1;
      area.x1=RBItem.WIN_XSIZE-2;
      area.y0=1;
      area.y1=RBItem.WIN_YSIZE-2;
      GUI_FillRectEx(&area);
      //绘制边框
      GUI_SetColor(RBItem.BORDER_COLOR);
      area.x0=0;
      area.x1=RBItem.WIN_XSIZE-1;
      area.y0=0;
      area.y1=RBItem.WIN_YSIZE-1;
      GUI_DrawRectEx(&area);
    }
    //开启状态时
    else if(RBItem.SWITCH_STATUS==1)
    {
      //绘制空白区域
      GUI_SetColor(RBItem.BACK_COLOR);
      area.x0=1;
      area.x1=RBItem.WIN_XSIZE-2;
      area.y0=1;
      area.y1=RBItem.WIN_YSIZE-2;
      GUI_FillRectEx(&area);
      //绘制中心矩形
      GUI_SetColor(RBItem.CENTER_COLOR);
      area.x0=2;
      area.x1=RBItem.WIN_XSIZE-3;
      area.y0=2;
      area.y1=RBItem.WIN_YSIZE-3;
      GUI_FillRectEx(&area);
      //绘制边框
      GUI_SetColor(RBItem.BORDER_COLOR);
      area.x0=0;
      area.x1=RBItem.WIN_XSIZE-1;
      area.y0=0;
      area.y1=RBItem.WIN_YSIZE-1;
      GUI_DrawRectEx(&area);
    }
    break;
  case WM_DELETE:
    break;
  default:
    BUTTON_Callback(pMsg);
    break;
  }
}

 

回调函数入口处会首先提取自己的私有数据,然后主要需要处理两个消息事件,分别是WM_TOUCH和WM_PAINT,这里采用事件处理和显示刷新分离的方式,当有鼠标或者触屏点击控件时,emwin会向callback发送WM_TOUCH消息,callback通过读取私有数据中控件事件状态和WM_TOUCH消息中具体内容完成事件处理,并把处理结果写回到私有数据中,随后通过WM_InvalidateWindow向调度器发送失效消息无效化自己的显示,并通过WM_NotifyParent向父窗口发送WM_NOTIFICATION_VALUE_CHANGED消息告知父窗口自己的状态已经发送了改变。到这里就完成了事件处理的部分,随后开始显示刷新,emwin在接收到无效化消息并处理完其他的事件后,会再次向窗口发送WM_PAINT消息,然后又是一轮相似的操作,读私有数据,根据数据刷新显示,到这里屏幕上控件显示就已经变化了,一次输入事件处理完成。

除WM_TOUCH和WM_PAINT外,callback还需处理WM_DELETE消息,主要是避免窗口的缺省函数乱删东西,缺省函数使用的BUTTON_Callback,因为我测试发现使用WINDOWS_Callback有时会出现问题,所以使用了一个现成控件的。

核心的部分讲完了,其他的就是一些补充的函数。

Check button用于派生子类的两个函数,子控件可以通过使用xx_GetUserData和xx_SetUserData继承check button全部特征并实现自身特征。

两个和参数读写有关的函数,CHECKBUTTON_GetState和CHECKBUTTON_SetState,其他的参数读写函数,比如说设置边框颜色,设置中心颜色,间距,宽度等等也都是大同小异。

控件使用的方式和emwin官方的控件完全一样,可以直接在资源列表中插入一个check button控件,然后正常使用即可。

到这里制作emwin控件就算基本讲完了,check button控件是一种相对来说比较简单的控件,所有我以它为例讲解了一下控件实现的大体结构,以后有时间可能会讲解一下其他比较复杂的控件。

源码链接:https://download.csdn.net/download/CSDN1344789841/15611114

文章链接:https://blog.csdn.net/CSDN1344789841/article/details/114435225

转载需标明出处

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值