STemwin 实现滑动切换主页 滑动翻页 滑动解锁功能

2023-05-16

STM32上实现类似iPhone的解锁和滑屏功能,emwin这个库官方的文档中控件没有一样的,但是有一个上下滑动的,基本上能够完成大致上的功能,但是如果想使用emwin实现类似的效果的话,需要懂这些知识点:

1、内存设备的使用

2、窗口的建立和消息

3、总之需要熟悉这个库的使用

由于本次测试中没有使用到外部SRAM,使用的单一的内部RAM,所以壁纸没有使用内存缓存下来,使用的单调色,基本上还算比较流畅,下面是代码正文,有兴趣的朋友可以参考下。

下面是我自己做的效果视频:

STemwin 实现滑动解锁 翻转主页

摇杆界面的控制视频

主页代码

/*********************************************************************
*                                                                    *
*                SEGGER Microcontroller GmbH & Co. KG                *
*        Solutions for real time microcontroller applications        *
*                                                                    *
**********************************************************************
*                                                                    *
* C-file generated by:                                               *
*                                                                    *
*        GUI_Builder for emWin version 5.32                          *
*        Compiled Oct  8 2015, 11:59:02                              *
*        (c) 2015 Segger Microcontroller GmbH & Co. KG               *
*                                                                    *
**********************************************************************
*                                                                    *
*        Internet: www.segger.com  Support: support@segger.com       *
*                                                                    *
**********************************************************************
*/

// USER START (Optionally insert additional includes)
// USER END

#include "DIALOG.h"
#include "GUI_app/gui_thread.h"
#include "GUI.h"
#include "LCD/lcd.h"
#include "config.h"

/*********************************************************************
*
*       注意
*  1、所有图标必须是正方形
*
**********************************************************************
*/

/*********************************************************************
*
*       user config
*
**********************************************************************
*/

#define MAIN_PAGE_SMILE_ICON_Y0   (LCD_ysize/2-STATUS_BAR_HEIGHT)   //笑脸图标的中心点Y方向
#define VIEW_ICON_BK_COLOR        0x00FFC880
#define ICON_BAR_BK_COLOR         0x00F0e6c8
#define ICON_SELECTED_COLOR       (0x22uL<<24)|GUI_LIGHTBLUE
/********VIEW_ICON********/
//锁定画面尺寸定义
#define VIEW_ICON_RATE      0.72f                            //解锁条在界面的比例位置
#define VIEW_ICON_X         0
#define VIEW_ICON_Y         STATUS_BAR_HEIGHT               //滑动图标区的Y起点
#define VIEW_ICON_XSIZE     (LCD_xsize-VIEW_ICON_X)
#define VIEW_ICON_YSIZE     (int)((LCD_ysize-VIEW_ICON_Y)*VIEW_ICON_RATE)
#define VIEW_SCREEN_YSIZE   (LCD_ysize-VIEW_ICON_Y)         //主页的Y尺寸

//显示控制参数
#define VIEW_ICON_POSITIONING_VALUE  6       //复位定位值
#define VIEW_ICON_REFRESH_RATE 5  //主页VIEW_ICON更新率
//图标和主页数量
#define MAIN_PAGE_NUM     2       //主页的数量
#define ICON_NUM_X        3       //每行图标个数
#define ICON_NUM_Y        3       //每列图标个数
#define ICON_X_INTERVAL   10      //每行图标间隔
#define ICON_Y_INTERVAL   10      //每列图标间隔

#define ICON_NUM          (ICON_NUM_X*ICON_NUM_y)   //单页支持的最大图标数量
#define VIEW_ICON_EDGE_XSIZE    0       //图标被选中后的边框距离,单位像素
#define VIEW_ICON_EDGE_YSIZE    4       //图标被选中后的边框距离,单位像素
#define TEXT_EDGE_SIZE    2       //文本和位图间距,单位像素
#define VIEW_ICON_TEXT_OFFSET    2       //文本偏移
#define TEXT_FONT         GUI_FONT_6X8_ASCII  //使用字体
  
//调试
#define VIEW_DEBUG        0

/********ICON_BAR********/
#define ICON_BAR_X         0
#define ICON_BAR_Y         (VIEW_ICON_Y+VIEW_ICON_YSIZE)    //图标条的Y起点,相对于LCD
#define ICON_BAR_XSIZE     (LCD_xsize-ICON_BAR_X)
#define ICON_BAR_YSIZE     (LCD_ysize-ICON_BAR_Y)

#define ICON_BAR_OUTSIDE_INTERVAL      30     	//图标区域X间距
#define ICON_BAR_MIDDLE_INTERVAL      10     	//图标区域X间距
#define ICON_BAR_Y_INTERVAL      10    	//图标区域y间距

#define ICON_BAR_REFRESH_RATE 1000  	//主页 ICON_BAR 更新率
#define ICON_BAR_ICON_NUM_X    	3		//行个数
#define ICON_BAR_ICON_NUM_Y     1		//列个数
#define ICON_BAR_TEXT_EDGE_SIZE    2       //文本和位图间距,单位像素
#define ICON_BAR_TEXT_OFFSET    -1       //文本偏移

#define ICON_BAR_EDGE_SIZE    2       //图标被选中后的边框距离,单位像素
//行为相关
#define MOVE_TRIGGER_DISTANCE   10   //判定为触摸移动的距离,单位像素
/*********************************************************************
*
*       variables
*
**********************************************************************
*/
//函数声明
static void clean_icon_view(void);
static void clean_icon_bar(void);
static void clean_all_icon_flag(void);
static void init_all_mainpage(void);
static void init_mainpage(void);
WM_HWIN CreateTips(void);

//图标位图
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_appstore;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_calculator;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_calendar;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_camera;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_clock;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_compass;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_menssages;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_music;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_phone;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_photos;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_weather;


//背景位图
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_smile;

//_icon图标对象表示的是包含位图和文本的所有区域
//由于都是使用GUI等接口进行绘制图形,如果使用窗口管理器,在哪个窗口绘制就是坐标系就是这个窗口原点。
struct _icon {
  //变量
  unsigned char flag;             //图标状态,1:被选择 2:被双击
  signed short icon_x;            //图标左上角点x坐标,
  signed short icon_y;            //图标左上角点y坐标
  unsigned short icon_xsize;        //图标x尺寸
  unsigned short icon_ysize;        //图标y尺寸
  
  signed short text_y;            //文本区域左上角点y坐标,包含位图和文本间距
  signed short text_c_x;          //文本区域中心点x坐标
  signed short text_h_y;          //文本区域顶点Y坐标
  
  signed short bitmap_x;          //位图区域左上角点x坐标
  signed short bitmap_y;          //位图区域左上角点y坐标
  unsigned short bitmap_xsize;      //位图区域x尺寸,起点和图标一致
  unsigned short bitmap_ysize;      //位图区域y尺寸
  unsigned short bitmap_size;       //位图尺寸,图标区域,始终正方形
  
  float bitmap_rate;                //位图缩放比例
  WM_HWIN (*fun)(void);                // 双击后的回调函数
  GUI_MEMDEV_Handle men_handle;
  //赋初值
  const char       * pText;         //图标名称
  const GUI_BITMAP * pBitmap;       //图标位图
};
typedef struct _icon _ICON;
typedef struct _icon* _ICON_T;

struct _page {
  unsigned char init;               //初始化状态
  unsigned char icon_num;           //图标数量
  _ICON_T icon_list;                //图标集
  const GUI_FONT * pFont;
};
typedef struct _page _PAGE;
typedef struct _page* _PAGE_T;

//主页1图标列表
static _ICON icon_list1[]={
  {.pText="calculator",.pBitmap=&bmiconview_calculator,.fun=CreateTips},
  {.pText="calendar",.pBitmap=&bmiconview_calendar,.fun=CreateTips},
  {.pText="camera",.pBitmap=&bmiconview_camera,.fun=CreateTips},
};
//主页2图标列表
static _ICON icon_list2[]={
  {.pText="menssages",.pBitmap=&bmiconview_menssages,.fun=CreateTips},
  {.pText="weather",.pBitmap=&bmiconview_weather,.fun=CreateTips},
};

//icon_bar 图标列表
static _ICON icon_bar_list[]={
  {.pText="phone",.pBitmap=&bmiconview_phone,.fun=CreateTips},
  {.pText="app",.pBitmap=&bmiconview_appstore,.fun=CreateTips},
  {.pText="photo",.pBitmap=&bmiconview_photos,.fun=CreateTips},
};

static _PAGE _main_page[MAIN_PAGE_NUM]={
{.icon_num=GUI_COUNTOF(icon_list1),.icon_list=icon_list1,.pFont=TEXT_FONT},
{.icon_num=GUI_COUNTOF(icon_list2),.icon_list=icon_list2,.pFont=TEXT_FONT},
};

//变量
static signed short scr_offset_c=0;         //屏幕偏移的当前值
static signed short scr_offset_o=0;         //屏幕偏移的目标值
static unsigned char c_page=0;              // 0表示第一页  1表示第二页
static signed char icon_view_bp_offset=0;         //位图偏移到中心点的偏移量 ,注意位图始终为同比例边长   
static signed char icon_bar_bp_offset=0;         //位图偏移到中心点的偏移量 ,注意位图始终为同比例边长   

//移动行为
static signed short move_touch_sxf;             //移动触发时的X起点(加上偏移)
static signed short move_touch_sx;              //移动触发时的X起点
static signed short move_touch_x;               //点击时的x值
static signed short move_touch_c;               //此处触发的移动值
static unsigned char move_touch_f;              //移动触发开始标志位, 1:表示没有触发  2:触摸  3:触摸并滑动

//触摸单击行为
static signed short touch_click_x;               //点击时的x值
static signed short touch_click_y;               //点击时的y值
static unsigned char touch_click_f;              //点击标志,1:触摸单击触发  2:触摸单击已经绘制

//触摸双击行为
static unsigned char double_click;               //双击触发

//页面稳定
static unsigned char page_stability_f=1;    //自动返回触发开始标志位
static unsigned short icon_bar_y=0;      //预计算出icon_bar_y的起点

//窗口刷新标志位
static unsigned char win_refresh;       //标志位 第一位 icon_view 第二位 icon_bar
//窗口句柄
static WM_HWIN icon_view;
static WM_HWIN icon_bar;
static WM_HWIN icon_tips;

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define ID_WINDOW_0         (GUI_ID_USER + 0x00)
#define ID_ICONVIEW_0       (GUI_ID_USER + 0x01)
#define ID_TEXT_0           (GUI_ID_USER + 0x02)
#define ID_BUTTON_0         (GUI_ID_USER + 0x03)
#define ID_FRAMEWIN_0       (GUI_ID_USER + 0x04)
#define TIMER_0           0
#define TIMER_1           1

static void init_all_mainpage(void)
{
  double_click=0;
  scr_offset_c=0;
  scr_offset_o=0;
  move_touch_f=0;
  c_page=0;
  clean_all_icon_flag();
}

static void init_mainpage(void)
{
  double_click=0;
  move_touch_f=0;
  clean_all_icon_flag();
}

#if(VIEW_DEBUG==1)
static void debug_view_icon()
{
  unsigned char i;
  unsigned char t;
  for(i=0;i<MAIN_PAGE_NUM;i++){                   //页号
    for(t=0;t<_main_page[i].icon_num;t++) {       //图标号
      //绘制图标区域   
      GUI_SetColor(GUI_WHITE);        
      GUI_DrawRect(_main_page[i].icon_list[t].icon_x, _main_page[i].icon_list[t].icon_y, 
        _main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].icon_xsize, 
        _main_page[i].icon_list[t].icon_y+_main_page[i].icon_list[t].icon_ysize);
      
      //绘制位图区域  
      GUI_SetColor(GUI_BLACK);       
      GUI_DrawRect(_main_page[i].icon_list[t].bitmap_x, _main_page[i].icon_list[t].bitmap_y, 
        _main_page[i].icon_list[t].bitmap_x+_main_page[i].icon_list[t].bitmap_size, 
        _main_page[i].icon_list[t].bitmap_y+_main_page[i].icon_list[t].bitmap_size); 
      
      //绘制文本区域
      GUI_SetColor(GUI_ORANGE);
      GUI_DrawRect(_main_page[i].icon_list[t].icon_x, _main_page[i].icon_list[t].text_y, 
        _main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].icon_xsize, 
        _main_page[i].icon_list[t].text_y+_main_page[i].pFont->YSize+TEXT_EDGE_SIZE);
      
      //绘制文本中心
      GUI_SetColor(GUI_RED);
      GUI_FillCircle(_main_page[i].icon_list[t].text_c_x, _main_page[i].icon_list[t].text_h_y, 2);
    }
  }
}

static void debug_icon_bar()
{
  unsigned char t;               
  for(t=0;t<GUI_COUNTOF(icon_bar_list);t++) {       //图标号
    //绘制图标区域   
    GUI_SetColor(GUI_WHITE);        
    GUI_DrawRect(icon_bar_list[t].icon_x, icon_bar_list[t].icon_y, 
      icon_bar_list[t].icon_x+icon_bar_list[t].icon_xsize, 
      icon_bar_list[t].icon_y+icon_bar_list[t].icon_ysize);
    
    //绘制位图区域  
    GUI_SetColor(GUI_BLACK);       
    GUI_DrawRect(icon_bar_list[t].bitmap_x, icon_bar_list[t].bitmap_y, 
      icon_bar_list[t].bitmap_x+icon_bar_list[t].bitmap_size, 
      icon_bar_list[t].bitmap_y+icon_bar_list[t].bitmap_size); 
    
    //绘制文本区域
    GUI_SetColor(GUI_ORANGE);
    GUI_DrawRect(icon_bar_list[t].icon_x, icon_bar_list[t].text_y, 
      icon_bar_list[t].icon_x+icon_bar_list[t].icon_xsize, 
      icon_bar_list[t].text_y+_main_page[0].pFont->YSize+ICON_BAR_TEXT_EDGE_SIZE);
    
    //绘制文本中心
    GUI_SetColor(GUI_RED);
    GUI_FillCircle(icon_bar_list[t].text_c_x, icon_bar_list[t].text_h_y, 2);
  }
}
#endif



/*********************************************************************
*
*       viewicon_cbDialog
*/
static void clean_icon_view(void)
{
  unsigned char i;
  unsigned char t;
  //清除VIEW_ICON
  for(i=0;i<MAIN_PAGE_NUM;i++){                   //页号
    for(t=0;t<_main_page[i].icon_num;t++) {       //图标号
      _main_page[i].icon_list[t].flag=0;
    }
  }
}

static void clean_icon_bar(void)
{
  unsigned char t;
  //清除ICON_BAR
  for(t=0;t<ICON_BAR_ICON_NUM_X;t++) {            //图标号
      icon_bar_list[t].flag=0;
  }
}
    
static void clean_all_icon_flag(void)
{
  clean_icon_view();
  clean_icon_bar(); 
}
  
static void viewicon_cbDialog(WM_MESSAGE * pMsg) 
{
//  WM_HWIN hItem;
  unsigned char i;
  unsigned char t;
  unsigned short temp;
  unsigned short temp1;
  GUI_PID_STATE  pState;
  
//  long ram;

  switch (pMsg->MsgId) {
  case WM_CREATE: 
    //初始化页参数
  
    // 优化:后期可以分段创建子窗口
    for(i=0;i<MAIN_PAGE_NUM;i++){                   //页号
      for(t=0;t<_main_page[i].icon_num;t++) {       //图标号
        /*图标区域定位*/
        _main_page[i].icon_list[t].icon_xsize=(VIEW_ICON_XSIZE-(ICON_NUM_X+1)*ICON_X_INTERVAL)/ICON_NUM_X;
        _main_page[i].icon_list[t].icon_ysize=(VIEW_ICON_YSIZE-(ICON_NUM_Y+1)*ICON_Y_INTERVAL)/ICON_NUM_Y;
        temp=t%ICON_NUM_X;                  //所在行
        //图标区域的左上角起点X坐标
        _main_page[i].icon_list[t].icon_x=(temp+1)*ICON_X_INTERVAL+temp*_main_page[i].icon_list[t].icon_xsize+VIEW_ICON_XSIZE*i;
        temp=t/ICON_NUM_X;                //所在列
        _main_page[i].icon_list[t].icon_y=(temp+1)*ICON_Y_INTERVAL+temp*_main_page[i].icon_list[t].icon_ysize;
        //计算尺寸
        _main_page[i].icon_list[t].text_y=_main_page[i].icon_list[t].icon_y+
            _main_page[i].icon_list[t].icon_ysize-
            _main_page[i].pFont->YSize-TEXT_EDGE_SIZE;
        
        _main_page[i].icon_list[t].bitmap_xsize=_main_page[i].icon_list[t].icon_xsize;
        _main_page[i].icon_list[t].bitmap_ysize=_main_page[i].icon_list[t].text_y-_main_page[i].icon_list[t].icon_y;
        
        //文本区域的中心点起点X坐标,由icon_x计算
        _main_page[i].icon_list[t].text_c_x=(_main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].bitmap_xsize/2);
        _main_page[i].icon_list[t].text_h_y=_main_page[i].icon_list[t].text_y+TEXT_EDGE_SIZE+VIEW_ICON_TEXT_OFFSET;
        
        //绘制位图比例和选边
        if(_main_page[i].icon_list[t].bitmap_xsize>_main_page[i].icon_list[t].bitmap_ysize){
          //以Y尺寸绘图,y为短边
          temp=(_main_page[i].icon_list[t].bitmap_xsize - _main_page[i].icon_list[t].bitmap_ysize)/2;       //X方向多余部分,绘制正方形图标
          //位图区域的左上角起点X坐标,由icon_x计算
          _main_page[i].icon_list[t].bitmap_x=_main_page[i].icon_list[t].icon_x+temp;
          _main_page[i].icon_list[t].bitmap_y=_main_page[i].icon_list[t].icon_y;
          _main_page[i].icon_list[t].bitmap_rate=
            (float)_main_page[i].icon_list[t].bitmap_ysize/_main_page[i].icon_list[t].pBitmap->XSize;   //缩放图标比例
          _main_page[i].icon_list[t].bitmap_size=_main_page[i].icon_list[t].bitmap_ysize;
        }else{
          //以x尺寸绘图,x为短边
          temp=(_main_page[i].icon_list[t].bitmap_ysize - _main_page[i].icon_list[t].bitmap_xsize)/2;  
          //位图区域的左上角起点X坐标,由icon_x计算
          _main_page[i].icon_list[t].bitmap_x=_main_page[i].icon_list[t].icon_x;
          _main_page[i].icon_list[t].bitmap_y=_main_page[i].icon_list[t].icon_y+temp;
          _main_page[i].icon_list[t].bitmap_rate=
            (float)_main_page[i].icon_list[t].bitmap_xsize/_main_page[i].icon_list[t].pBitmap->XSize;   //缩放图标比例 
          _main_page[i].icon_list[t].bitmap_size=_main_page[i].icon_list[t].bitmap_xsize;
        }  
        
        /*创建内存设备*/    
        //内存设备区域的左上角起点X坐标  ,由icon_x计算        
         _main_page[i].icon_list[t].men_handle=GUI_MEMDEV_CreateFixed(_main_page[i].icon_list[t].bitmap_x, _main_page[i].icon_list[t].bitmap_y,
        _main_page[i].icon_list[t].pBitmap->XSize, _main_page[i].icon_list[t].pBitmap->YSize,
        GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_16, GUICC_M565);
        //绘制位图
        GUI_MEMDEV_Select(_main_page[i].icon_list[t].men_handle);
        GUI_DrawBitmap(_main_page[i].icon_list[t].pBitmap, 
        _main_page[i].icon_list[t].bitmap_x,
        _main_page[i].icon_list[t].bitmap_y);     
      }
    }
    //提示此时生成位图的正方形边长
    i=0; t=0;
    //对齐到位图区域中心
    icon_view_bp_offset=-(_main_page[i].icon_list[t].pBitmap->XSize-_main_page[i].icon_list[t].bitmap_size)/2;

    xprintf("icon_view bitmap_size:%d\r\n",_main_page[i].icon_list[t].bitmap_size);
//    ram=GUI_ALLOC_GetNumFreeBytes();      //获取GUI剩余内存空间
//    xprintf("icon_view GUI_Free_ram is %d\r\n",ram);
      
    //重新指定LCD输出
    GUI_MEMDEV_Select(0);
    icon_bar_y=VIEW_ICON_Y+VIEW_ICON_YSIZE;
    break;
  
  case WM_PAINT:
    //重绘背景
    GUI_SetBkColor(VIEW_ICON_BK_COLOR);         //自定义调色
    GUI_Clear();
//    GUI_DrawBitmapEx(&bmicon_smile, VIEW_ICON_XSIZE/2, //耗费CPU资源
//    MAIN_PAGE_SMILE_ICON_Y0,bmicon_smile.XSize/2,bmicon_smile.YSize/2,1000,1000);  
#if(VIEW_DEBUG==1)
    debug_view_icon();
#endif

    //绘制滑动图标区域
    for(i=0;i<MAIN_PAGE_NUM;i++){                   //页号
      for(t=0;t<_main_page[i].icon_num;t++) {       //图标号
        //绘制被选择背景
        if(c_page==i && _main_page[i].icon_list[t].flag==1 ){
          GUI_SetColor(ICON_SELECTED_COLOR);
          GUI_FillRect(_main_page[i].icon_list[t].icon_x-c_page*VIEW_ICON_XSIZE - VIEW_ICON_EDGE_XSIZE,
          _main_page[i].icon_list[t].icon_y - VIEW_ICON_EDGE_YSIZE,
          _main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].icon_xsize-c_page*VIEW_ICON_XSIZE + VIEW_ICON_EDGE_XSIZE ,
          _main_page[i].icon_list[t].icon_y+_main_page[i].icon_list[t].icon_ysize + VIEW_ICON_EDGE_YSIZE  );
        }

        //绘制图标区域      
        GUI_MEMDEV_WriteAt(_main_page[i].icon_list[t].men_handle,
        _main_page[i].icon_list[t].bitmap_x+icon_view_bp_offset+scr_offset_c
        ,_main_page[i].icon_list[t].bitmap_y+icon_view_bp_offset+VIEW_ICON_Y);
        
//      GUI_MEMDEV_WriteExAt();消耗大
        
        //绘制文本区域
        GUI_SetColor(GUI_BLACK);
        GUI_SetTextMode(GUI_TM_TRANS);          //透明背景
        GUI_DispStringHCenterAt(_main_page[i].icon_list[t].pText, _main_page[i].icon_list[t].text_c_x+scr_offset_c, 
        _main_page[i].icon_list[t].text_h_y);
      }
    }
  break;

  case WM_TIMER:
    if(double_click==1){
      WM_DeleteTimer(pMsg->Data.v);       //双击行为后 main_page 不在更新
      break;
    }
    else{
      WM_RestartTimer(pMsg->Data.v, VIEW_ICON_REFRESH_RATE);
    }
    GUI_PID_GetState(&pState); 
    
    // 移动行为 页面没有达到 单击行为 
    if(move_touch_f==3 || scr_offset_o!=scr_offset_c){
      WM_InvalidateWindow(pMsg->hWin);
    }
    
    // 点击行为刷新
    if( touch_click_f==1 || touch_click_f==2)            //VIEW_ICON 中的图标触发选中
    {
      WM_InvalidateWindow(pMsg->hWin);
      WM_SendMessageNoPara(icon_bar, MSG_WIN_INVAILD);   //发送到 icon_bar ,刷新页面
    }
    /***********行为***********/

    /*行为:点击 和 滑动 */
    if(pState.Pressed==1 && move_touch_f==1 ){
      move_touch_sxf=pState.x-scr_offset_c;      // 添加初始偏移值
      move_touch_sx=pState.x;
      move_touch_f=2;                           // 记忆发生触摸
    }
    if(pState.Pressed==1 && move_touch_f>1){
      move_touch_x=pState.x;
      move_touch_c=move_touch_x-move_touch_sx;      //当前触摸滑动的移动值
      
      //确认是否为 滑动 行为
      if(abs(move_touch_c)>MOVE_TRIGGER_DISTANCE){
        /*行为:滑动 */
        if(pState.y>VIEW_ICON_Y && pState.y<icon_bar_y)     //需要在指定区域滑动
        {            
          clean_all_icon_flag();                        //清除所有的标记
          if(win_refresh&0x2){
            WM_SendMessageNoPara(icon_bar, MSG_WIN_INVAILD);  
            win_refresh&=0x1;                           //清除这个刷新标记
          }

          move_touch_f=3;                               //触发触摸移动标志
          scr_offset_c=move_touch_x-move_touch_sxf;     //在初始偏移值基础上进行增减
          
          //滑动页面两侧极限位置限制
          if(scr_offset_c < (-(MAIN_PAGE_NUM-1)*VIEW_ICON_XSIZE)){
            scr_offset_c = -(MAIN_PAGE_NUM-1)*VIEW_ICON_XSIZE;
            move_touch_c=0;
          }
          if(scr_offset_c > 0){
            scr_offset_c = 0;
            move_touch_c=0;
          } 
        }
        else{       //超出滑动区域
          move_touch_c=0;
        }          
      }
      else
      {
        /*行为:点击图标*/
        //touch_click_f 
        // 0: 一次单击检测开始
        // 1: VIEW_ICON 选中
        // 2: ICON_BAR 选中
        // 3: 都没 选中
        if(move_touch_f==2 && page_stability_f==1 && touch_click_f==0 && double_click==0){          //触发点击行为,没有触发翻页
          touch_click_x =  pState.x;
          touch_click_y =  pState.y;
          
          // 确定 VIEW_ICON 哪个图标被选中
          for(i=0;i<MAIN_PAGE_NUM;i++){                   //页号
            for(t=0;t<_main_page[i].icon_num;t++) {       //图标号
              temp = _main_page[i].icon_list[t].icon_x + VIEW_ICON_X - c_page*VIEW_ICON_XSIZE;   //当前页的图标X起点
              temp1 = _main_page[i].icon_list[t].icon_y + VIEW_ICON_Y;                //当前页的图标Y起点
              if( i==c_page  
              && touch_click_f == 0
              && touch_click_x - temp < _main_page[i].icon_list[t].icon_xsize 
              && touch_click_x > temp 
              && touch_click_y- temp1 < _main_page[i].icon_list[t].icon_ysize 
              && touch_click_y > temp1  )
              {
                /*行为:双击 图标*/
                if(_main_page[i].icon_list[t].flag==1){        
                  double_click=1;                  
                  _main_page[i].icon_list[t].fun();                 //触发回调
                }
                _main_page[i].icon_list[t].flag=1;
                touch_click_f = 1;                                  // VIEW_ICON 中的图标触发选中  
                win_refresh|=0x1;                                   // 标记清除选中需要刷新一次
              }else
              {
                _main_page[i].icon_list[t].flag=0;                  //将 VIEW_ICON 没有选择的标志清除
              }
            }
          }
          
          // 确定 ICON_BAR 哪个图标被选中
          for(t=0;t<ICON_BAR_ICON_NUM_X;t++) {        //图标号
            temp=icon_bar_list[t].icon_x+ICON_BAR_X;
            temp1=icon_bar_list[t].icon_y+ICON_BAR_Y;
            if(touch_click_f == 0
            && touch_click_x-temp < icon_bar_list[t].icon_xsize 
            && touch_click_y-temp1 < icon_bar_list[t].icon_ysize 
            && touch_click_x > temp
            && touch_click_y > temp1 )
            {
              /*行为:双击 图标*/
              if(icon_bar_list[t].flag==1){             
                double_click=1;  
                icon_bar_list[t].fun();     //触发回调
              }
              icon_bar_list[t].flag=1;
              touch_click_f = 2;                      // ICON_BAR 中的图标触发选中  
              win_refresh|=0x2;                       // 标记清除选中需要刷新一次      
            }else
            {
              icon_bar_list[t].flag=0;                //将 ICON_BAR 没有选择的标志清除
            }
          }
          
          // 什么都没有点
          if(touch_click_f!=1 && touch_click_f!=2){   //表示什么都没有点击
            WM_InvalidateWindow(pMsg->hWin);
            WM_SendMessageNoPara(icon_bar, MSG_WIN_INVAILD);   //发送到icon_bar ,刷新页面
            touch_click_f=3;                          // 都没有点到
          }
        } 
      }
    }
    else    
    {    
      move_touch_c=0;
    }   
    
    //用于解锁后防止滑动屏幕
    if(pState.Pressed==0){   
      move_touch_f=1;          // 记忆没有发生触摸
      touch_click_f = 0;
    }

    /* 行为:更改页面目标值 */
    if(move_touch_f==3 && abs(move_touch_c)>VIEW_ICON_XSIZE/4 && page_stability_f==1){
      if(move_touch_c<0 && c_page < MAIN_PAGE_NUM-1)  //切换下一页
      {
        scr_offset_o=scr_offset_o-VIEW_ICON_XSIZE; 
        page_stability_f=0;
        c_page++;
      }else if(move_touch_c>0 && c_page>0){       //切换上一页
        scr_offset_o=scr_offset_o+VIEW_ICON_XSIZE; 
        page_stability_f=0;
        c_page--;
      }
    }

    /*行为:自动定位主页*/
    if( move_touch_f==1 && scr_offset_o>scr_offset_c ){
      if((scr_offset_o-scr_offset_c)<VIEW_ICON_POSITIONING_VALUE)
        scr_offset_c=scr_offset_o;      //防止无法准确到达scr_offset_o值
      else
        scr_offset_c=scr_offset_c+VIEW_ICON_POSITIONING_VALUE;
    }else if( move_touch_f==1 && scr_offset_o<scr_offset_c ){
      if((scr_offset_c-scr_offset_o)<VIEW_ICON_POSITIONING_VALUE)
        scr_offset_c=scr_offset_o;      //防止无法准确到达scr_offset_o值
      else
        scr_offset_c=scr_offset_c-VIEW_ICON_POSITIONING_VALUE;
    }
    //页面稳定
    if(scr_offset_o==scr_offset_c)page_stability_f=1;
    
//    xprintf("move_touch_f:%d\r\n",move_touch_f);
    break;
    
  case WM_DELETE:
    init_all_mainpage(); 
    
    // 删除所有的内存设备
    for(i=0;i<MAIN_PAGE_NUM;i++){                   //页号
      for(t=0;t<_main_page[i].icon_num;t++) {       //图标号
        GUI_MEMDEV_Delete(_main_page[i].icon_list[t].men_handle);
      }
    }
    break;
 
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

static void iconbar_cbDialog(WM_MESSAGE * pMsg) 
{
//  WM_HWIN hItem;
//  unsigned char i;
  unsigned char t;
  unsigned short temp;
#if(VIEW_DEBUG==1)
  long ram;
#endif  
  switch (pMsg->MsgId) {
  case WM_CREATE:   
    for(t=0;t<GUI_COUNTOF(icon_bar_list);t++) {       //图标号
      /*图标区域定位*/
      icon_bar_list[t].icon_xsize=(ICON_BAR_XSIZE-(ICON_BAR_ICON_NUM_X-1)*ICON_BAR_MIDDLE_INTERVAL-2*ICON_BAR_OUTSIDE_INTERVAL)/ICON_BAR_ICON_NUM_X;
      icon_bar_list[t].icon_ysize=(ICON_BAR_YSIZE-(ICON_BAR_ICON_NUM_Y+1)*ICON_BAR_Y_INTERVAL)/ICON_BAR_ICON_NUM_Y;
      temp=t%ICON_BAR_ICON_NUM_X;                  //所在行
      //图标区域的左上角起点X坐标
      icon_bar_list[t].icon_x=ICON_BAR_OUTSIDE_INTERVAL+ temp*ICON_BAR_MIDDLE_INTERVAL+temp*icon_bar_list[t].icon_xsize;

      temp=t/ICON_BAR_ICON_NUM_X;                //所在列
      icon_bar_list[t].icon_y=(temp+1)*ICON_BAR_Y_INTERVAL+temp*icon_bar_list[t].icon_ysize;
      //计算尺寸
      icon_bar_list[t].text_y=icon_bar_list[t].icon_y+
          icon_bar_list[t].icon_ysize-
          _main_page[0].pFont->YSize-ICON_BAR_TEXT_EDGE_SIZE;
      
      icon_bar_list[t].bitmap_xsize=icon_bar_list[t].icon_xsize;
      icon_bar_list[t].bitmap_ysize=icon_bar_list[t].text_y-icon_bar_list[t].icon_y;
      
      //文本区域的中心点起点X坐标,由icon_x计算
      icon_bar_list[t].text_c_x=(icon_bar_list[t].icon_x+icon_bar_list[t].bitmap_xsize/2);
      icon_bar_list[t].text_h_y=icon_bar_list[t].text_y+ICON_BAR_TEXT_EDGE_SIZE+ICON_BAR_TEXT_OFFSET;
      
      //绘制位图比例和选边
      if(icon_bar_list[t].bitmap_xsize>icon_bar_list[t].bitmap_ysize){
        //以Y尺寸绘图,y为短边
        temp=(icon_bar_list[t].bitmap_xsize - icon_bar_list[t].bitmap_ysize)/2;       //X方向多余部分,绘制正方形图标
        //位图区域的左上角起点X坐标,由icon_x计算
        icon_bar_list[t].bitmap_x=icon_bar_list[t].icon_x+temp;
        icon_bar_list[t].bitmap_y=icon_bar_list[t].icon_y;
        icon_bar_list[t].bitmap_rate=
          (float)icon_bar_list[t].bitmap_ysize/icon_bar_list[t].pBitmap->XSize;   //缩放图标比例
        icon_bar_list[t].bitmap_size=icon_bar_list[t].bitmap_ysize;
      }else{
        //以x尺寸绘图,x为短边
        temp=(icon_bar_list[t].bitmap_ysize - icon_bar_list[t].bitmap_xsize)/2;  
        //位图区域的左上角起点X坐标,由icon_x计算
        icon_bar_list[t].bitmap_x=icon_bar_list[t].icon_x;
        icon_bar_list[t].bitmap_y=icon_bar_list[t].icon_y+temp;
        icon_bar_list[t].bitmap_rate=
          (float)icon_bar_list[t].bitmap_xsize/icon_bar_list[t].pBitmap->XSize;   //缩放图标比例 
        icon_bar_list[t].bitmap_size=icon_bar_list[t].bitmap_xsize;
      }  
      
      /*创建内存设备*/    
      //内存设备区域的左上角起点X坐标  ,由icon_x计算    
      //这里使用的内存创建后没有主动释放
       icon_bar_list[t].men_handle=GUI_MEMDEV_CreateFixed(icon_bar_list[t].bitmap_x, icon_bar_list[t].bitmap_y,
      icon_bar_list[t].pBitmap->XSize, icon_bar_list[t].pBitmap->YSize,
      GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_16, GUICC_M565);
      //绘制位图
      GUI_MEMDEV_Select(icon_bar_list[t].men_handle);
      GUI_DrawBitmap(icon_bar_list[t].pBitmap, 
      icon_bar_list[t].bitmap_x,
      icon_bar_list[t].bitmap_y);   
    }

    //提示此时生成位图的正方形边长
    //对齐到位图区域中心,使用图片1的,所以要保证图标大小一致,否则其他图标位置错误
    t=0;
    icon_bar_bp_offset=-(icon_bar_list[t].pBitmap->XSize-icon_bar_list[t].bitmap_size)/2+1;
    
      xprintf("icon_bar bitmap_size:%d\r\n",icon_bar_list[t].bitmap_size);
//      ram=GUI_ALLOC_GetNumFreeBytes();      //获取GUI剩余内存空间
//      xprintf("icon_bar GUI_Free_ram is %d\r\n",ram);
      
    //重新指定LCD输出
    GUI_MEMDEV_Select(0);
#if(VIEW_DEBUG==1)
    ram=GUI_ALLOC_GetNumFreeBytes();      //获取GUI剩余内存空间
    xprintf("GUI_Free_ram is %d\r\n",ram);  
#endif   

    break;
  
  case WM_PAINT:
    GUI_SetBkColor(ICON_BAR_BK_COLOR);        
    GUI_Clear();
  
#if(VIEW_DEBUG==1)
    debug_icon_bar();
#endif
    //绘制图标区域
    for(t=0;t<ICON_BAR_ICON_NUM_X;t++) {       //图标号
      //绘制被选择背景
      if(icon_bar_list[t].flag==1){
        GUI_SetColor(ICON_SELECTED_COLOR);
        GUI_FillRect(icon_bar_list[t].icon_x-ICON_BAR_EDGE_SIZE,
        icon_bar_list[t].icon_y-ICON_BAR_EDGE_SIZE,
        icon_bar_list[t].icon_x+icon_bar_list[t].icon_xsize+ICON_BAR_EDGE_SIZE,
        icon_bar_list[t].icon_y+icon_bar_list[t].icon_ysize+ICON_BAR_EDGE_SIZE);
      }
      
      //绘制图标区域      
      GUI_MEMDEV_WriteAt(icon_bar_list[t].men_handle,
      icon_bar_list[t].bitmap_x+icon_bar_bp_offset
      ,icon_bar_list[t].bitmap_y+icon_bar_bp_offset+ICON_BAR_Y);
      
      //绘制文本区域
      GUI_SetColor(GUI_BLACK);
      GUI_SetTextMode(GUI_TM_TRANS);          //透明背景
      GUI_DispStringHCenterAt(icon_bar_list[t].pText,icon_bar_list[t].text_c_x, 
      icon_bar_list[t].text_h_y);
    }
//    xprintf("icon_bar_refresh\r\n");
    break;
    
  case MSG_WIN_INVAILD:
    WM_InvalidateWindow(pMsg->hWin);  
    break;
  
  case WM_DELETE:
    init_all_mainpage(); 
    
    // 删除所有的内存设备
    for(t=0;t<GUI_COUNTOF(icon_bar_list);t++) {       //图标号
        GUI_MEMDEV_Delete(icon_bar_list[t].men_handle);
    }
    break;
    
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

/*********************************************************************
*
*       Createwin_mainpage
*/
WM_HWIN Createwin_mainpage(void);
WM_HWIN Createwin_mainpage(void) {
  WM_HWIN win[WIN_MAX_NUM]={0};
  
  //初始化主屏幕参数
  init_all_mainpage();                  
  /*****创建VIEW ICON区域*****/
  win[0]=WM_CreateWindowAsChild(VIEW_ICON_X, VIEW_ICON_Y, VIEW_ICON_XSIZE, VIEW_ICON_YSIZE,
  WM_HBKWIN, WM_CF_SHOW, viewicon_cbDialog, 0);
  //创建VIEW ICON定时器
  WM_CreateTimer(win[0], TIMER_0, VIEW_ICON_REFRESH_RATE, 0);

//  /*****创建ICON BAR区域*****/
  win[1]=WM_CreateWindowAsChild(ICON_BAR_X, ICON_BAR_Y, ICON_BAR_XSIZE, ICON_BAR_YSIZE,
  WM_HBKWIN, WM_CF_SHOW, iconbar_cbDialog, 0);
  
  icon_view = win[0];
  icon_bar = win[1];
  switch_win(win,MIAN_PAGE_WIN_ID);
  return win[0];
}


#define TIPS_WIN_XSIZE    150
#define TIPS_WIN_YSIZE    120
#define TIPS_WIN_X        (LCD_xsize-TIPS_WIN_XSIZE)/2
#define TIPS_WIN_Y        ((LCD_ysize-TIPS_WIN_YSIZE)/2-STATUS_BAR_HEIGHT)

#define TIPS_BUTTON_XSIZE  50
#define TIPS_BUTTON_YSIZE  25    
#define TIPS_BUTTON_X  ((TIPS_WIN_XSIZE-TIPS_BUTTON_XSIZE)/2)
#define TIPS_BUTTON_Y  (int)(TIPS_WIN_YSIZE * 0.65f)
#define TIPS_BUTTON_FONT   GUI_FONT_8X12_ASCII

#define TIPS_TEXT_XSIZE  (TIPS_WIN_XSIZE-20)
#define TIPS_TEXT_YSIZE  (TIPS_WIN_YSIZE-TIPS_BUTTON_YSIZE-60)    //不要覆盖到按钮窗口
#define TIPS_TEXT_X  (TIPS_WIN_XSIZE-TIPS_TEXT_XSIZE)/2
#define TIPS_TEXT_Y  (int)(TIPS_WIN_YSIZE * 0.30f)
#define TIPS_TEXT_TEXT   GUI_FONT_8X12_ASCII

#if(VIEW_DEBUG==1)
static void debug_view_region(void)
{
  //绘制窗口区域   
  GUI_SetColor(GUI_RED);        
  GUI_DrawRect(0,0,
    0+TIPS_WIN_XSIZE-1, 
    0+TIPS_WIN_YSIZE-1);
  
  //绘制文本区域   
  GUI_SetColor(GUI_WHITE);        
  GUI_DrawRect(TIPS_TEXT_X, TIPS_TEXT_Y, 
    TIPS_TEXT_X+TIPS_TEXT_XSIZE, 
    TIPS_TEXT_Y+TIPS_TEXT_YSIZE);

  //绘制按钮区域  
  GUI_SetColor(GUI_BLACK);       
  GUI_DrawRect(TIPS_BUTTON_X, TIPS_BUTTON_Y, 
   TIPS_BUTTON_X+TIPS_BUTTON_XSIZE, 
   TIPS_BUTTON_Y+TIPS_BUTTON_YSIZE); 
}
#endif

//创建提示窗口
static void Tips_cbDialog(WM_MESSAGE * pMsg) {
#if(VIEW_DEBUG==0)
  WM_HWIN hItem;
#endif
  int     NCode;
  int     Id;
//  long ram;

  switch (pMsg->MsgId) {
  case WM_CREATE:
    //显示框架
#if(VIEW_DEBUG==0)
    hItem=FRAMEWIN_CreateEx(0,0,TIPS_WIN_XSIZE,TIPS_WIN_YSIZE,pMsg->hWin,
    WM_CF_SHOW,0,ID_FRAMEWIN_0,"Tips",0);

    hItem=TEXT_CreateEx(TIPS_TEXT_X, TIPS_TEXT_Y,TIPS_TEXT_XSIZE, TIPS_TEXT_YSIZE,
    pMsg->hWin,WM_CF_SHOW,
    TEXT_CF_HCENTER|TEXT_CF_TOP, ID_TEXT_0, "Please set callback function");
    TEXT_SetWrapMode(hItem,GUI_WRAPMODE_WORD);
    WM_SetStayOnTop(hItem,1);                 //文本窗口始终在最上面

    hItem = BUTTON_CreateEx(TIPS_BUTTON_X,TIPS_BUTTON_Y,TIPS_BUTTON_XSIZE,TIPS_BUTTON_YSIZE,pMsg->hWin,WM_CF_SHOW,0,ID_BUTTON_0);
    WM_SetFocus(hItem);
    WM_SetStayOnTop(hItem,1);                 //按钮窗口始终在最上面
    BUTTON_SetFont(hItem, TIPS_BUTTON_FONT);
    BUTTON_SetText(hItem, "OK");
#endif
#if(VIEW_DEBUG==1)
    debug_view_region();
#endif
//    ram=GUI_ALLOC_GetNumFreeBytes();        //获取GUI剩余内存空间
//    xprintf("GUI_Free_ram is %d\r\n",ram);      
    break;
  
  case WM_NOTIFY_PARENT:
    Id    = WM_GetId(pMsg->hWinSrc);
    NCode = pMsg->Data.v;
    switch(Id) {
    case ID_BUTTON_0: // Notifications sent by 'Button'
      switch(NCode) {
      case WM_NOTIFICATION_CLICKED:
        WM_DeleteWindow(pMsg->hWin);
        break;
      case WM_NOTIFICATION_RELEASED:
        break;
      }
      break;
    }
    break;
    
  case WM_PAINT:
#if(VIEW_DEBUG==1)
    debug_view_region();
#endif
   break;
  
  case WM_DELETE:
    init_mainpage(); 
    if(_hLastFrame[0]!=0){
      WM_CreateTimer(icon_view, TIMER_0, VIEW_ICON_REFRESH_RATE, 0);
    }
    break;
  
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

WM_HWIN CreateTips(void) {

  icon_tips=WM_CreateWindowAsChild(TIPS_WIN_X, TIPS_WIN_Y, TIPS_WIN_XSIZE, TIPS_WIN_YSIZE,
  icon_view, WM_CF_SHOW|WM_CF_HASTRANS, Tips_cbDialog, 0);
  
  return icon_tips;
}
/*************************** End of file ****************************/

解锁页代码

/*********************************************************************
*                                                                    *
*                SEGGER Microcontroller GmbH & Co. KG                *
*        Solutions for real time microcontroller applications        *
*                                                                    *
**********************************************************************
*                                                                    *
* C-file generated by:                                               *
*                                                                    *
*        GUI_Builder for emWin version 5.32                          *
*        Compiled Oct  8 2015, 11:59:02                              *
*        (c) 2015 Segger Microcontroller GmbH & Co. KG               *
*                                                                    *
**********************************************************************
*                                                                    *
*        Internet: www.segger.com  Support: support@segger.com       *
*                                                                    *
**********************************************************************
*/

// USER START (Optionally insert additional includes)
// USER END

#include "DIALOG.h"
#include "SCROLLBAR.h"
#include "SCROLLBAR_Private.h"
#include "GUI_app/gui_thread.h"
#include "config.h"

/*********************************************************************
*
*       user config
*
**********************************************************************
*/
//锁定画面尺寸定义
#define LOCK_SCREEN_X         0
#define LOCK_SCREEN_Y         STATUS_BAR_HEIGHT
#define LOCK_SCREEN_XSIZE     (LCD_xsize-LOCK_SCREEN_X)
#define LOCK_SCREEN_YSIZE     (LCD_ysize-LOCK_SCREEN_Y)
//在状态栏的基础上偏移
#define LOCK_BAR_Y0_RATE      0.75f   //解锁条在LCD屏幕的比例位置
#define LOCK_BAR_Y0     (int)(LCD_ysize*LOCK_BAR_Y0_RATE-STATUS_BAR_HEIGHT)    //解锁条的Y方向起点,始终保证在
  
#define TEXT_BAR_Y0     50             //文本框的左上角起点,相对于LOCK_SCREEN为0
#define TEXT_BAR_YSIZE  40
#define SMILE_ICON_Y0   (LOCK_SCREEN_YSIZE)/2     //笑脸图标的中心点Y方向
//锁定界面参数
#define VALUE_NO_TRIGGER  -1      //滑条按钮没有触发下的返回减少的值
#define LOCK_BAR_REFRESH_RATE 30  //解锁条刷新率
#define TIME_REFRESH_RATE 1000    //时间显示刷新率
//解锁条外观调整
#define LOCK_BAR_LIMIT  15        //解锁条超出限制,由于不要左右按钮,需要起点和终点超出界限
#define LOCK_BAR_WIDTH  40        //解锁条的宽度,上下高度
#define SLIDE_STRIP_VALUE 40      //滑条最大值,决定滑块大小
#define LOCK_BAR_OSIZE      1     //解锁条外框尺寸
#define LOCK_BAR_ISIZE      1     //解锁条内框尺寸
#define LOCK_BAR_RSIZE      3     //解锁条中所有圆角尺寸
#define SLIDE_OSIZE           3   //滑块在解锁条中的间距
#define DY_SLIDE_WIDTH        20   //动态滑条宽度
#define DY_SLIDE_OSIZE        3   //动态滑条尺寸
#define DY_SLIDE_SPEED        1   //动态速度

//时间外观调整
#define TIME_Y_OFFSET         100  //时间的垂直位置,越大越往上

#define VIEW_DEBUG            0
/*********************************************************************
*
*       variables
*
**********************************************************************
*/
static float dy_slider_value=0;           //动态滑块的移动值

extern WM_HWIN _hLastFrame[WIN_MAX_NUM];;	
extern GUI_CONST_STORAGE GUI_BITMAP bmwallpaper_ios15_1;        //失真的IOS壁纸
extern GUI_CONST_STORAGE GUI_BITMAP bmwallpaper_ios15_2;        //全彩的IOS壁纸
extern GUI_CONST_STORAGE GUI_BITMAP bmwallpaper_smile;          //失真的笑脸壁纸
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_unlock_arrow;
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_smile;
extern GUI_CONST_STORAGE GUI_FONT GUI_Fontfont_songti_38_bold_ascii_unicode;

extern RTC_TimeTypeDef RTC_TimeStruct;
extern RTC_DateTypeDef RTC_DateStruct;

extern void init_mainpage(void);
WM_HWIN Createlockwin(void);
WM_HWIN Createwin_mainpage(void);
WM_HWIN lock_handle;

GUI_MEMDEV_Handle icon_arrow_handle;
/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define ID_WINDOW_0       (GUI_ID_USER + 0x00)
#define ID_SCROLLBAR_0    (GUI_ID_USER + 0x01)
#define ID_TEXT_0         (GUI_ID_USER + 0x02)

#define TIMER_0           0
#define TIMER_1           1
// USER START (Optionally insert additional defines)
// USER END

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

#if(VIEW_DEBUG==0)
static signed short but_lcd_xoffset;
static signed short but_lcd_yoffset;
static int SCROLLBAR_0_DrawSkin(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo) {
  static int SCROLLBAR0_state=0;
  static int UNLOCK_BAR_x0=0,UNLOCK_BAR_y0=0,UNLOCK_BAR_x1=0,UNLOCK_BAR_y1=0;
  static unsigned char init=0;
  
  SCROLLBAR_SKINFLEX_INFO * pSkinInfo;
  pSkinInfo = (SCROLLBAR_SKINFLEX_INFO *)pDrawItemInfo->p;
  char text[]="    slide to unlock";
  GUI_RECT pRect;
  int offset;
  int temp;
  
  switch (pDrawItemInfo->Cmd) {
    case WIDGET_ITEM_CREATE:            //创建控件后立即发送
      return SCROLLBAR_DrawSkinFlex(pDrawItemInfo);
    case WIDGET_ITEM_DRAW_BUTTON_L:     //皮肤设置函数将绘制左侧按钮
      if( but_lcd_yoffset==0){
//        offset=pDrawItemInfo->x1-pDrawItemInfo->x0;
        temp=WM_GetWindowOrgX(pDrawItemInfo->hWin);
        but_lcd_xoffset=temp+LOCK_BAR_OSIZE+LOCK_BAR_ISIZE+SLIDE_OSIZE-2;
        but_lcd_yoffset=WM_GetWindowOrgY(pDrawItemInfo->hWin)+LOCK_BAR_OSIZE+LOCK_BAR_ISIZE+SLIDE_OSIZE-5;
//        xprintf("xoffset:%d yoffset:%d \r\n",but_lcd_xoffset,but_lcd_yoffset);
      }
      //不绘制
      return 0;
    case WIDGET_ITEM_DRAW_BUTTON_R:       //皮肤设置函数将绘制右侧按钮
      //不绘制
      return 0;
    case WIDGET_ITEM_DRAW_OVERLAP:      //皮肤设置函数将绘制重叠区域。
      return SCROLLBAR_DrawSkinFlex(pDrawItemInfo);
    
    case WIDGET_ITEM_DRAW_SHAFT_L:      //皮肤设置函数将绘制轴的左侧部分
//      xprintf("SHAFT_L x0:%d y0:%d x1:%d y1:%d \r\n",pDrawItemInfo->x0,pDrawItemInfo->y0,pDrawItemInfo->x1,pDrawItemInfo->y1);
      //绘制外框,外框使用圆角矩形,填充后,下面又覆盖中间区域
      UNLOCK_BAR_x0=pDrawItemInfo->x0;
      UNLOCK_BAR_y0=pDrawItemInfo->y0;
      if(UNLOCK_BAR_x1){
        GUI_SetColor(GUI_GRAY);     //指定外框颜色
        //绘制外框区域
        GUI_FillRoundedRect(UNLOCK_BAR_x0,UNLOCK_BAR_y0,UNLOCK_BAR_x1,UNLOCK_BAR_y1,LOCK_BAR_RSIZE);
        
        //绘制内框,虽然为填充,后面覆盖掉
        offset=LOCK_BAR_OSIZE;
        GUI_DrawGradientRoundedV(UNLOCK_BAR_x0+offset,      //根据外框尺寸偏移
            UNLOCK_BAR_y0+offset,
            UNLOCK_BAR_x1-offset,
            UNLOCK_BAR_y1-offset,
            LOCK_BAR_RSIZE,GUI_DARKGRAY,GUI_LIGHTGRAY);                     //滑条底部渐变为白色
        
        //绘制滑条
        offset=LOCK_BAR_OSIZE+LOCK_BAR_ISIZE;
        GUI_DrawGradientRoundedV(UNLOCK_BAR_x0+offset,
            UNLOCK_BAR_y0+offset,
            UNLOCK_BAR_x1-offset,                 
            UNLOCK_BAR_y1-offset,                 
            LOCK_BAR_RSIZE,GUI_BLACK,GUI_DARKGRAY);
   
        //绘制动态滑条  
        offset=LOCK_BAR_OSIZE+LOCK_BAR_ISIZE+DY_SLIDE_OSIZE;
        pRect.x0=dy_slider_value+UNLOCK_BAR_x0+offset;
        pRect.x1=pRect.x0+DY_SLIDE_WIDTH;
        pRect.y0=UNLOCK_BAR_y0+offset;
        pRect.y1=UNLOCK_BAR_y1-offset;
        if(dy_slider_value<=DY_SLIDE_WIDTH && init==0){         //头部逐渐出现
          pRect.x0=UNLOCK_BAR_x0+offset;
          pRect.x1=UNLOCK_BAR_x0+offset+dy_slider_value;
          if(dy_slider_value==DY_SLIDE_WIDTH){
            init=1;                 //头部出现效果完成
            dy_slider_value=0;      //正常显示开始
          }
        }
        if((pRect.x1)>=UNLOCK_BAR_x1-offset){                   //尾部逐渐消失
          pRect.x1=UNLOCK_BAR_x1-offset;
          if(pRect.x0>=pRect.x1){
            init=0;
            dy_slider_value=0;
          }  
        }   
        // 绘制动态滑条,使用透明效果
        GUI_DrawGradientRoundedH(pRect.x0,pRect.y0,pRect.x1,pRect.y1,                 
        LOCK_BAR_RSIZE,GUI_MAKE_COLOR((0xaauL << 24) | GUI_DARKGRAY),GUI_MAKE_COLOR((0xaauL << 24) | GUI_WHITE));     //制作混合色   
        
        //显示字体
        pRect.x0=UNLOCK_BAR_x0;
        pRect.y0=UNLOCK_BAR_y0;
        pRect.x1=UNLOCK_BAR_x1;
        pRect.y1=UNLOCK_BAR_y1;
        GUI_SetColor(GUI_GRAY);                           //指定外框颜色
        GUI_SetFont(GUI_FONT_8X16_ASCII);
        GUI_SetTextMode(GUI_TM_TRANS|GUI_TM_XOR);        //设置为显示透明文本
        GUI_DispStringInRectEx(text,&pRect,GUI_TA_VCENTER|GUI_TA_HCENTER,sizeof(text),GUI_ROTATE_0); 
      }
      return 0;
    
    case WIDGET_ITEM_DRAW_SHAFT_R:      //皮肤设置函数将绘制轴的右侧部分。
      UNLOCK_BAR_x1=pDrawItemInfo->x1;
      UNLOCK_BAR_y1=pDrawItemInfo->y1;
      return 0;
    
    case WIDGET_ITEM_DRAW_THUMB:          //皮肤设置函数将绘制缩略图
//      xprintf("THUMB x0:%d y0:%d x1:%d y1:%d \r\n",pDrawItemInfo->x0,pDrawItemInfo->y0,pDrawItemInfo->x1,pDrawItemInfo->y1);
      if(SCROLLBAR0_state!=pSkinInfo->State){           //保存中间按钮状态到用户数据
        SCROLLBAR0_state=pSkinInfo->State;
        SCROLLBAR_SetUserData(pDrawItemInfo->hWin,&SCROLLBAR0_state,sizeof(SCROLLBAR0_state));
      }
      //绘制滑块
      GUI_DrawGradientRoundedV(pDrawItemInfo->x0+SLIDE_OSIZE,
          pDrawItemInfo->y0+SLIDE_OSIZE,
          pDrawItemInfo->x1-SLIDE_OSIZE,
          pDrawItemInfo->y1-SLIDE_OSIZE,
          LOCK_BAR_RSIZE,GUI_WHITE,GUI_LIGHTGRAY);                     //滑条底部渐变为白色    

      //绘制箭头
//      GUI_DrawBitmapEx(&bmicon_unlock_arrow, pDrawItemInfo->x0+(pDrawItemInfo->x1-pDrawItemInfo->x0)/2+2, 
//      (pDrawItemInfo->y1-pDrawItemInfo->y0)/2,bmicon_unlock_arrow.XSize/2,bmicon_unlock_arrow.YSize/2,500,500);
      GUI_MEMDEV_WriteAt(icon_arrow_handle,
      but_lcd_xoffset + ((pDrawItemInfo->x1-pDrawItemInfo->x0)-bmicon_unlock_arrow.XSize)/2+pDrawItemInfo->x0,
      but_lcd_yoffset + ((pDrawItemInfo->y1-pDrawItemInfo->y0)-bmicon_unlock_arrow.YSize)/2+pDrawItemInfo->y0);   
      return 0;
      
    case WIDGET_ITEM_GET_BUTTONSIZE:
      return (pSkinInfo->IsVertical) ?
      pDrawItemInfo->x1 - pDrawItemInfo->x0 + 1 :
      pDrawItemInfo->y1 - pDrawItemInfo->y0 + 1;
      
    default:                            //所有其他类型将以默认皮肤执行
      return SCROLLBAR_DrawSkinFlex(pDrawItemInfo);
  }
}
#endif
/*********************************************************************
*
*       _cbDialog
*/
#if(VIEW_DEBUG==1)
static void debug_view_region(void)
{
  //绘制窗口区域  
  GUI_SetColor(GUI_RED);        
  GUI_FillCircle(2,2,2);
  
  GUI_SetColor(GUI_RED);        
  GUI_DrawRect(LOCK_SCREEN_X-LOCK_BAR_LIMIT, LOCK_BAR_Y0,LOCK_SCREEN_X-LOCK_BAR_LIMIT+LOCK_SCREEN_XSIZE+LOCK_BAR_LIMIT*2,
    LOCK_BAR_Y0+(int)LOCK_SCREEN_YSIZE*0.15f);
  
  //绘制文本区域   
  GUI_SetColor(GUI_WHITE);        
  GUI_DrawRect(LOCK_SCREEN_X, TEXT_BAR_Y0, 
    LOCK_SCREEN_X+LOCK_SCREEN_XSIZE, 
    TEXT_BAR_Y0+TEXT_BAR_YSIZE);
}
#endif

static void _cbDialog(WM_MESSAGE * pMsg) {
  WM_HWIN hItem;
  int SCROLLBAR0_state=0;
  int SCROLLBAR0_value=0;
  char time_id;
  char tbuf[40];

  // USER START (Optionally insert additional variables)
  // USER END
  switch (pMsg->MsgId) {
  case WM_CREATE : 
#if(VIEW_DEBUG==0)
    //创建解锁条
    hItem=SCROLLBAR_CreateUser(LOCK_SCREEN_X-LOCK_BAR_LIMIT, LOCK_BAR_Y0,LOCK_SCREEN_XSIZE+LOCK_BAR_LIMIT*2,(int)LOCK_SCREEN_YSIZE*0.15f,
        pMsg->hWin,WM_CF_SHOW, SCROLLBAR_CF_FOCUSSABLE ,ID_SCROLLBAR_0, sizeof(SCROLLBAR0_state));
    SCROLLBAR_SetNumItems(hItem, SLIDE_STRIP_VALUE);
    SCROLLBAR_SetWidth(hItem,LOCK_BAR_WIDTH);
    SCROLLBAR_SetSkin(hItem,SCROLLBAR_0_DrawSkin);        //设置控件的皮肤回调
    WM_SetFocus(hItem);
   
    //创建文本框,显示时间
    sprintf((char*)tbuf,"%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes); 
    hItem=TEXT_CreateEx(LOCK_SCREEN_X, TEXT_BAR_Y0,LOCK_SCREEN_XSIZE, TEXT_BAR_YSIZE,
      pMsg->hWin,WM_CF_SHOW,TEXT_CF_HCENTER|TEXT_CF_TOP, ID_TEXT_0,tbuf);
    TEXT_SetFont(hItem,&GUI_Fontfont_songti_38_bold_ascii_unicode);
    TEXT_SetBkColor(hItem, GUI_INVALID_COLOR);            //使用背景颜色,透明字体
    
    /*创建内存设备*/    
    //内存设备区域的左上角起点X坐标  ,由icon_x计算        
    icon_arrow_handle=GUI_MEMDEV_CreateFixed(100,100,
    bmicon_unlock_arrow.XSize,bmicon_unlock_arrow.YSize,
    GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_16, GUICC_M565);
    //绘制位图
    GUI_MEMDEV_Select(icon_arrow_handle);
    GUI_DrawBitmap(&bmicon_unlock_arrow, 100,100);     
    
    //重新指定LCD输出
    GUI_MEMDEV_Select(0);
#endif    
    break; 

  case WM_PAINT:
    //绘制图标区域
    GUI_SetBkColor(0x00FFC880);         //自定义调色
    GUI_Clear();
    GUI_DrawBitmap(&bmicon_smile, 
    LOCK_SCREEN_XSIZE/2-bmicon_smile.XSize/2, 
    SMILE_ICON_Y0 - bmicon_smile.YSize/2);        
#if(VIEW_DEBUG==1)
    debug_view_region();
#endif 
  break;
 
  case WM_TIMER:
    time_id=WM_GetTimerId(pMsg->Data.v);
    switch(time_id){
      case TIMER_0:           //解锁条的刷新率
        WM_RestartTimer(pMsg->Data.v, LOCK_BAR_REFRESH_RATE);
        //高刷新率刷新解锁条
        //如果滑条按钮没有被按,自动回退
        hItem=WM_GetDialogItem(pMsg->hWin, ID_SCROLLBAR_0);
        WM_InvalidateWindow(hItem);                                                   //单独刷新解锁条
        SCROLLBAR_GetUserData(hItem,&SCROLLBAR0_state,sizeof(SCROLLBAR0_state));      //可以使用全局变量
        if(!(SCROLLBAR0_state & PRESSED_STATE_THUMB)){
          SCROLLBAR_AddValue(hItem,VALUE_NO_TRIGGER);     //中间按钮返回
        }
        dy_slider_value=dy_slider_value+DY_SLIDE_SPEED;
        SCROLLBAR0_value=SCROLLBAR_GetValue(hItem);
        //xprintf("SCROLLBAR0_value:%d\r\n",SCROLLBAR0_value);
        if(SCROLLBAR0_value==(SLIDE_STRIP_VALUE-10)){       //解锁屏幕
          detete_last_win();
          Createwin_mainpage();
        }
        break;
        
      case TIMER_1:                 //时间的刷新率
        sprintf((char*)tbuf,"%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes); 
        hItem=WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
        TEXT_SetText(hItem,tbuf);
        WM_RestartTimer(pMsg->Data.v, TIME_REFRESH_RATE);
        break;
    }
    break; 
    
  case WM_DELETE:
    GUI_MEMDEV_Delete(icon_arrow_handle);
    break;
  
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       Createunlockwin
*/
WM_HWIN Createlockwin(void) {
  WM_HWIN win[WIN_MAX_NUM]={0};
  win[0]=WM_CreateWindowAsChild(LOCK_SCREEN_X, LOCK_SCREEN_Y, LOCK_SCREEN_XSIZE, LOCK_SCREEN_YSIZE,
  WM_HBKWIN, WM_CF_SHOW, _cbDialog, 0);
  lock_handle=win[0];
  
  WM_CreateTimer(win[0], TIMER_0, LOCK_BAR_REFRESH_RATE, 0);
  WM_CreateTimer(win[0], TIMER_1, TIME_REFRESH_RATE, 0);
  switch_win(win,LOCK_WIN_ID);
  return win[0];
}

// USER START (Optionally insert additional public code)
// USER END

/*************************** End of file ****************************/

GUI线程代码 gui_thread.c

#include "GUI_app/gui_thread.h"
#include "stm32f4xx.h"
#include "GUI.h"
#include "WM.h"
#include "serial.h"
#include "LCD/lcd.h"

/*********************************************************************************************
* GUI全局配置变量
*********************************************************************************************/

WM_HWIN _hLastFrame[WIN_MAX_NUM]={0};											//当前所在窗口的句柄,全局
unsigned char Last_win_id;								//当前所在窗口的ID,全局
GUI_MEMDEV_Handle    hMempic;
GUI_PID_STATE pid_state;
unsigned short LCD_xsize;
unsigned short LCD_ysize;

extern GUI_CONST_STORAGE GUI_BITMAP bmIOS15_1;
extern struct graphic_device g_dev;
extern WM_HWIN Createlockwin(void);
extern WM_HWIN Createwin_mainpage(void);
extern WM_HWIN CreateFramewin(void);
extern WM_HWIN Createstatus_bar(void);
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_smile;

/*********************************************************************************************
* 声明
*********************************************************************************************/
#if(USE_GUI_EXAMPLE==2)
static void touch_app_1(void);
static void gui_app_1(void);
static void gui_app_2(void);
#endif
#if(USE_GUI_EXAMPLE==1)
static void gui_alloc_GetNumFreeBytes(void);
#endif

void switch_win(WM_HWIN* win,unsigned char id)
{
  memcpy(_hLastFrame,win,sizeof(WM_HWIN)*WIN_MAX_NUM);
  Last_win_id=id;
}

void detete_last_win(void)
{
  char i;
  WM_HWIN temp;
  for(i=0;i<WIN_MAX_NUM;i++){
    if(_hLastFrame[i]!=0){
      temp=_hLastFrame[i];
      _hLastFrame[i]=0;           //在父窗口删除前,先清理掉标志位。防止硬件错误。
      WM_DeleteWindow(temp);
    } 
  }
}      
/*********************************************************************************************
* 名称:emwin_init()
* 功能:emWin初始化
* 参数:无
* 返回:无
* 修改:
* 注释:
*********************************************************************************************/
static void emwin_init(void)
{                                 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);           // 开启CRC时钟
  GUI_Init();                                                   // emWin初始化
  WM_SetCreateFlags(WM_CF_MEMDEV);                              // 窗口启用内存设备
  GUI_UC_SetEncodeUTF8();                                       // 使用UTF-8编码
  GUI_EnableAlpha(1);                                           // 开启透明效果
//  WM_MULTIBUF_Enable(1);                                        // 开启多缓存
  WM_MOTION_Enable(1);                                          // 窗口移动支持
}

static void emwin_init_parameter(void)
{
  LCD_xsize=LCD_GetXSize();
  LCD_ysize=LCD_GetYSize(); 
}
/*********************************************************************************************
* 函 数 名: _cbBkWindow
* 功能说明: 桌面窗口回调函数
* 形    参:pMsg  参数指针
* 返 回 值: 无
*********************************************************************************************/
static void _cbBkWindow(WM_MESSAGE* pMsg)
{

  switch (pMsg->MsgId)
  {
    case WM_PAINT:
      GUI_SetBkColor(GUI_WHITE);         //自定义调色
      GUI_Clear();
    break;
    
    case MSG_LOCK:
      detete_last_win();
      Createlockwin();
      break;
    
    default:
      WM_DefaultProc(pMsg);
  }
}

/*********************************************************************************************
* 名称:gui_thread_entry()
* 功能:GUI线程入口函数
* 参数:*parameter -> 入口参数(暂无)
* 返回:无
* 修改:
* 注释:
*********************************************************************************************/
void gui_thread_Task(void *parameter)
{
  (void)parameter;
  unsigned int time=0;

  emwin_init();
  emwin_init_parameter();
  WM_SetCallback(WM_HBKWIN, &_cbBkWindow);    //设置桌面窗口的回调函数 
  
  Createstatus_bar();
//  Createlockwin();
  Createwin_mainpage();
  while(1)
  {
#if(USE_GUI_EXAMPLE==1)
    gui_alloc_GetNumFreeBytes();      // 获取GUI VM管理器的剩余内存        
//    gui_app_1();                            // 测试DEMO
//    touch_app_1();                          // 测试DEMO
#endif
    GUI_TOUCH_Exec();                         // 触摸刷新
    GUI_Delay(GUI_TASK_DELAY);                            // GUI刷新并延时
    
    // 触发锁屏
    if(Last_win_id!=LOCK_WIN_ID){
      time++;
      if(time*GUI_TASK_DELAY>=(unsigned int)LOCK_DELAY*1000){
        WM_SendMessageNoPara(WM_HBKWIN,MSG_LOCK);
        time=0;
      }
      // 重置计时
      if(time%20==0){       //降低消耗
        GUI_TOUCH_GetState(&pid_state); 
      }
      if(pid_state.Pressed){              
        time=0;
        pid_state.Pressed=0;
      }  
    }
  }  
//  vTaskDelete(NULL);
}

#if(USE_GUI_EXAMPLE==1)
// 获取GUI当前的剩余内存
static void gui_alloc_GetNumFreeBytes(void)
{
    uint32_t ram;
    static uint32_t times;
    times++;
    if(times%1000==0){
      ram=GUI_ALLOC_GetNumFreeBytes();      //获取GUI剩余内存空间
      xprintf("ram is %d\r\n",ram);
    }
}
#endif
#if(USE_GUI_EXAMPLE==2)
//测试验证读点函数
static void gui_app_2(void)
{
  GUI_SetColor(GUI_YELLOW);
  GUI_SetDefaultFont(&GUI_Font8x16);
  GUI_SetFont(&GUI_Font8x16);
  GUI_SetBkColor(GUI_BLUE);
  GUI_Clear();
  GUI_SetPenSize(10);
  GUI_SetColor(GUI_RED);
  GUI_DrawLine(20, 10, 180, 90);        //某个指定起点到某个指定终点之间的线,前面是点1的XY
  GUI_DrawLine(20, 90, 180, 10);
  GUI_SetBkColor(GUI_BLACK);
  GUI_SetColor(GUI_WHITE);
  GUI_SetTextMode(GUI_TM_NORMAL);       //设置为显示正常文本
  GUI_DispStringHCenterAt("GUI_TM_NORMAL", 100, 10);
  GUI_SetTextMode(GUI_TM_REV);          //设置为显示反转文本,就是字体和背景颜色反转颜色
  GUI_DispStringHCenterAt("GUI_TM_REV", 100, 26);
  GUI_SetTextMode(GUI_TM_TRANS);        //设置为显示透明文本
  GUI_DispStringHCenterAt("GUI_TM_TRANS", 100, 42);
  GUI_SetTextMode(GUI_TM_XOR);          //设置为反相显示的文本,会存在读点颜色
  GUI_DispStringHCenterAt("GUI_TM_XOR", 100, 58);
  GUI_SetTextMode(GUI_TM_TRANS | GUI_TM_REV);   //反转文本和透明背景
  GUI_DispStringHCenterAt("GUI_TM_TRANS | GUI_TM_REV", 100, 74);
}

//验证
static void gui_app_1(void)
{
  static const GUI_COLOR color[3][2] = {
  {0x00FFFF, 0x0000FF},                                         // 黄色 -> 红色
  {0xFFFF00, 0x00FF00},                                         // 青色 -> 绿色
  {0xFF00FF, 0xFF0000},                                         // 紫色 -> 蓝色
  };
  static short x = 0, y = 0;
  static unsigned char num = 0;
  if(x >= g_dev.lcd_dev->width)                                                // 制造位移变色效果
  {
    x = -60;            //X复位
    y += 20;            //Y方向下移
    if(y >= g_dev.lcd_dev->height)
    {
      num++;            //变化颜色
      if(num >= 3)
        num = 0;
      y = 0;            //Y复位
    }
  }
  // 绘制用水平颜色梯度填充的矩形
  GUI_DrawGradientH(x, y, x+60, y+20, color[num][0], color[num][1]);
  x++;
}

//验证emwin是否正常回调触摸刷新
static void touch_app_1(void)
{
  int x_value=GUI_TOUCH_GetxPhys();
  int y_value=GUI_TOUCH_GetyPhys();
  xprintf("x:%d,y:%d\r\n",x_value,y_value);
}
#endif

gui_thread.h

#ifndef __GUI_THREAD_H_
#define __GUI_THREAD_H_
#include "GUI.h"
#include "WM.h"

// 窗口消息定义
#define MSG_SWITCH            (WM_USER + 1)
#define MSG_MAIN_PAGE_SWITCH  (WM_USER + 2)
#define MSG_WIN_INVAILD       (WM_USER + 3)
#define MSG_LOCK              (WM_USER + 4)

// 通知父窗口消息定义
#define NOTIFICATION_UNLOCK (WM_NOTIFICATION_USER+1)

// 窗口ID
#define LOCK_WIN_ID         1
#define MIAN_PAGE_WIN_ID    2

#define WIN_MAX_NUM       5    //页面支持的最大窗口数量

// 外部引用声明
extern WM_HWIN _hLastFrame[WIN_MAX_NUM];										//当前所在窗口的句柄,全局
extern unsigned char Last_win_id;								//当前所在窗口的ID,全局
extern unsigned short LCD_xsize;
extern unsigned short LCD_ysize;

// 函数声明
void gui_thread_Task(void *parameter);
void lock(void);              //创建解锁画面
void switch_win(WM_HWIN* win,unsigned char id);    //切换窗口需要引用
void detete_last_win(void);
#endif //__GUI_THREAD_H_

config.h

#ifndef __CONFIG_H__
#define __CONFIG_H__
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
#include "stdio.h"
#include "string.h"
/* Hardware and starter kit includes. */
#include "stm32f4xx.h"
#include "stm32f4xx_conf.h"
/*************全局config文件*************/

/*************ESP32配置*************/
//#define CAR_MACADDR     "40:22:d8:eb:49:bc"        	//设置小车的目标地址
#define CAR_MACADDR     ""        	//设置小车的目标地址

/*************STemWin532*************/
#define PKG_STEMWIN_MEM_SIZE    120									//STemWin532使用的动态内存大小,内存设备需要较大的RAM
#define GUI_NUMBYTES  (PKG_STEMWIN_MEM_SIZE * 1024)
/* Define the average block size */
#define GUI_BLOCKSIZE 0x80                          //块大小

/* 电阻触摸屏的AD定义 校准使用 */
#define TOUCH_AD_LEFT       170
#define TOUCH_AD_RIGHT      3850
#define TOUCH_AD_TOP        265
#define TOUCH_AD_BOTTOM     3950

/* GUI线程 */
#define GUI_TASK_DELAY      5      //GUI主线程延时,单位ms
#define LOCK_DELAY          120       //屏幕没有触发后时间锁定,单位s
#define USE_GUI_EXAMPLE     0       //GUI开启示例

#define STATUS_BAR_HEIGHT   15      //单位像素 

/*************微秒级函数*************/
void hw_us_delay(unsigned int us);    //微秒级延时
unsigned int xtime(void);             //获取系统的运行时间us

/*************中断优先级配置*************/
#define USART1_INT_PRIORITY       7
#define USART3_INT_PRIORITY       7
#define RTC_ALARM_INT_PRIORITY    10
#define CPU_USAGE_TIMER_PRIORITY  6

/*************CLI示例命令*************/
#define CLI_USE_EXAMPLE           0

/*************CPU使用率统计*************/
#define CPU_USAGE_USE_TIM         0
/*************定时器使用*************/
#if(CPU_USAGE_USE_TIM==1)
#define CPU_USAGE_TIMER           TIM6
#define CPU_USAGE_TIMER_RCC       RCC_APB1Periph_TIM6
#define CPU_USAGE_TIMER_IRQ       TIM6_DAC_IRQn
#endif
#endif

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STemwin 实现滑动切换主页 滑动翻页 滑动解锁功能 的相关文章

  • 嵌入式Linux——kmsg:分析/proc/kmsg文件以及写自己的/proc/mymsg

    简介 xff1a 本文主要分析 proc kmsg文件的形成过程以及使用cat proc kmsg查看log buf中的信息时所要经历的代码 并结合上面的分析写自己的 proc mymsg和myprintk Linux内核 xff1a li
  • 嵌入式Linux——学习经历

    简介 xff1a 本文主要介绍我学习嵌入式的经历 并结合自身的经验希望可以对大家有所帮助 视频及教材 xff1a 郭天祥相关视频及教材 xff0c 天狼星相关视频及教材 xff0c 野火迷你相关视频及教材以及韦东山100ask官网所介绍的视
  • 指针简介(3)—— 指针函数与函数指针

    声明 xff1a 本文是阅读周立功老师的程序设计与数据结构后所写 xff0c 很多内容其实是书中的内容 xff0c 所以如果您想了解更多这方面的知识 xff0c 您可以阅读这本书 在前面一节我们简单介绍了指针 数组 指针数组以及数组指针 而
  • Docker常用操作命令

    成功安装Docker之后 启动Docker 如果遇到启动问题请参考 https blog csdn net w1316022737 article details 83692701 下来简单介绍Docker容器常用操作命令 安装操作MySQ
  • DIY 自己的路由器系统

    sudo apt get install subversion build essential libncurses5 dev zlib1g dev gawk git ccache gettext libssl dev xsltproc z
  • (ROS)解决gazebo闪退和tk窗口不显示问题

    问题1 xff1a 运行gazebo的时候 xff0c gazebo窗口闪退 解决办法 xff1a 1 删除gazebo xff0c 重新安装适合的版本然后再重新运行 或者 2 关闭加速3D图形 xff08 需要关闭虚拟机 rostopic
  • 【常见的优化算法介绍】

    常见的优化算法介绍 1 批量梯度下降算法 xff08 batch gradient descent BGD xff09 每次迭代都需要把所有样本都送入 xff0c 这样的好处是每次迭代都顾及了全部的样本 xff0c 做的是全局最优化 但是有
  • 树莓派无显示屏 ssh 连接的方法

    一般来说 xff0c 树莓派买回来很少配置显示屏 xff0c 通常只通过ssh远程登陆来控制树莓派 而树莓派通过ssh连接有三种方法 一 通过网线将树莓派连接到路由器上 这个方法成功率极高 xff0c 我一般都是采用这种方法 1 允许ssh
  • AIRSIM 中文使用手册-2021/4/6

    AIRSIM 中文使用手册 截至2021 4 6 前言1 HomeHome日志变更 2 获取AIRSIM下载二进制文件在Windows上构建在Linux上构建Linux上的DockerAzure上的AirSim开发环境自定义虚幻环境AirS
  • 最新研究:AI已可诊断50种眼疾,1.2秒内确认神经系统疾病

    本文由人工智能观察编译 译者 xff1a Sandy 近年来 xff0c 人工智能技术与医疗健康领域的融合不断加深 xff0c 且在科技巨头与资本巨头积极布局的努力下 xff0c 智能医疗正在不断取得新的突破 而根据 自然医学 xff08
  • 如何将Set转换为Array?

    本文翻译自 xff1a How to convert Set to Array Set seems like a nice way to create Arrays with guaranteed unique elements but i
  • 小米2013校园招聘笔试题

    题目 xff1a 一个数组里 xff0c 除了三个数是唯一出现的 xff0c 其余的都出现偶数个 xff0c 找出这三个数中的任一个 比如数组元素为 1 2 4 5 6 4 2 xff0c 只有1 5 6这三个数字是唯一出现的 xff0c
  • NVIDIA Jetson NX 模组初始化(刷机+扩容)

    项目场景 xff1a 老师让我学习使用NVIDIA Jetson NX做项目开发 于是自己研究一下 由于第一次接触 前期踩坑用了两周时间 特此记录 1 刷机 使用的是NVIDIA Jetson NX 模组 xff0c 网上买大约4 5k x
  • centos+docker设置网易163镜像加速

    镜像加速 鉴于国内网络问题 xff0c 后续拉取 Docker 镜像十分缓慢 xff0c 我们可以需要配置加速器来解决 xff0c 我使用的是网易的镜像地址 xff1a http hub mirror c 163 com 新版的 Docke
  • WSL(ubuntu2204)xfce4安装中文环境和fcitx5框架及中文输入法

    安装中文语言包 sudo apt install language pack zh hans 配置中文显示 首先运行如下命令配置 locale sudo vi etc locale gen 找到 zh CN UTF 8 UTF 8 并取消注
  • detectron2: An object named ‘XXXX‘ was already registered in ‘META_ARCH‘ registry

    根据该作者 https blog csdn net qq 20793791 article details 107924375 所述的方法 xff0c 我又想到了 看我的目录文件是否是 python package xff0c 突然发现虽然
  • ubuntu20.04中python2和python3切换

    Ubuntu 20 04 LTS已经移除Python2 xff0c 默认安装python3 xff0c 但是很多时候还是会经常用到python2 7版本 xff0c 这里首先单独安装python2 7 xff0c 然后配置python2和p
  • ubuntu18.04 pycorrector安装

    今天尝试对语音识别转录后的文字进行纠错 xff0c 然后就试了一下pycorrector xff0c 在安装pycorrector的时候遇见了下面的问题 xff1a base pip install pycorrector Looking
  • libxcb-xinerama.so.0: cannot open shared object file: No such file or directory

    今天在ubutnu 18 04上装了mayavi 但是写代码可视化点云的时候出现了下面的情况 xff1a QLibraryPrivate loadPlugin failed on 34 home eric anaconda3 envs po
  • 生产者/消费者模式(转载)

    简介 在实际的软件开发过程中 xff0c 经常会碰到如下场景 xff1a 某个模块负责产生数据 xff0c 这些数据由另一个模块来负责处理 xff08 此处的模块是广义的 xff0c 可以是类 函数 线程 进程等 xff09 产生数据的模块

随机推荐

  • 【飞控学习】APM和PX4飞控源码下载及安装

    对于无人机开发的专业人员来说 xff0c APM和PX4是现今市面上最强大的2个开源无人机飞控 学习和查看他们2者的源码 xff0c 将会提高我们对整个无人机的姿态解算和控制的深入理解 现在我们就来下载2者的源码和安装查看2者源码的软件 1
  • Skye无人机换遥控接收机遇到的坑

    Skye的接收机是可以直接用天地飞对码的 xff0c 如果要更换接收机的话需要支持sbus协议或者要有个转码器 xff0c 要更换接收机的话要特别注意 xff0c skye主板上集成了一个反相器 xff01 如果用单片机自己做转码器的话直接
  • opencv算法移植到嵌入式平台(1): opencv工程打包成库

    1 将要用到的opencv 相关的库打包 xff0c 利用你要移植的平台第三方编译器进行交叉编译 xff0c 因为如果你利用其它编译器即使编译通过了 xff0c 在另外的工程调用时也会提示错误 xff0c 一般会报错误 xff1a unde
  • 值得你关注的Android6.0上的重要变化(一)

    伴随着众多新特性和新功能 xff0c Android6 0 xff08 API level 23 xff09 在系统和API上都有着诸多的改变 本文着重介绍几个关键变化 xff0c 以帮助你理解这些改变对你的APP产生的影响 一 运行时权限
  • 编译开源LibreOffice的Android版本——开源Office文档查看器

    项目近期需要用到文档查看器 xff0c 现有的WPS之类确实比较好用 xff0c 无奈还需要对应用做些处理 xff0c 只好寻找开源的实现 开源的文档查看器主要两种方式 xff0c 一种是完整的Android版本实现 xff0c 直接拿来即
  • Linux下利用信号的异步串口中断响应

    先悔过一下 因为一个月前就在学习这个 xff0c 当时解决的差不多了 xff0c 想着抽个空再记录这些 xff0c 没想到这么短的时间就已经忘得 差不多了 xff0c 真是不好 xff0c 应该趁热打铁 废话不多说了 xff0c 这里主要介
  • 值得你关注的Android8.0(Android O)上的重要变化

    刚适配完Android7 0还没多久 xff0c 就看到Google官方推出的Android8 0 xff08 Android O xff09 的开发者预览版新闻 xff0c 我的心情你可以好好想想 对于上层应用开发者的我来说 xff0c
  • Android应用流量统计——NetworkStatsManager使用

    在没有Root的情况下 xff0c Android应用流量统计在6 0之前一直没有太好的办法 xff0c 官方虽然提供了TrafficStats xff0c 但其主要功能是设备启动以来流量的统计信息 xff0c 和时间信息无法很好的配合 最
  • Java处理http协议相关初步(二)——httpserver

    这里的HttpServer xff0c 并不是哪里专门下载的类库了 xff0c 而是在JDK1 6中自带的 xff0c 在com sun net httpserver包中 xff0c 提供了简单的较高层次意义上的Http ServerAPI
  • Android源码下载与编译之emulator与adb

    最近碰到一个问题 xff0c 就是Android的emulator只能打开16个 xff0c 在网上找到文章有说adb连接数量是16个的 xff0c 但是没说这个avd也只能16个 xff08 当然是在一台电脑上 xff09 于是 xff0
  • 自动化刷EOS资金盘(类Fomo3D)游戏

    7月底在以太坊的Fomo3D游戏异常火爆 xff0c 两三天后 xff0c 在EOS主网上 xff0c 国内各种仿品相继上线 xff0c 留心观察 xff0c 这些游戏里都有着自动化交易的身影 本文为你分析如何实现一个简单的EOS自动化交易
  • 毕业后就是程序员——我的阿里、金山、中华、腾讯、360、网易面试总结(三)

    接着上篇 xff0c 这篇侧重于具体的笔试 面试的问题 xff0c 至于是哪个公司的就不去追究了 xff0c 但一定是经常问到的 xff0c 而且我嵌入式系统工程师和移动开发工程师都参与了 xff0c 问题要区别看待 xff0c 那么自然就
  • 你投资的那些EOS“侧链”都还好么?

    EOS侧链BOS的启动声势浩大 xff0c 引得一众EOS超级节点与公司参与支持 xff0c 也招来币圈大佬老猫的质疑 xff0c 直言 熊市 xff0c 我劝你善良 xff1b 近几日 xff0c 曾被称作是EOS上首条侧链的FIBOS开
  • 销毁3417万枚EOS与被刺激的EOS价格——理解增发与销毁机制

    eosio saving帐号销毁的3417万枚EOS与REX锁住的6000多万枚EOS xff0c 都刺激不了EOS价格 xff0c 甚至仍有下跌的趋势 xff0c 而几天后一觉醒来 xff0c 不管BTC还是EOS都在疯涨 xff0c 过
  • Error executing aapt: Return code -1073741819

    总会有让人喷血的事情勾起写博客的欲望 xff0c 希望能坚持 折腾了两天的是个小问题 xff0c 就是标题上的Error executing aapt Return code 1073741819 解决的方法也很简单参考1中所述 xff0c
  • EOS的危险信号——记主网上线一周年后

    市值已经跌落到第八 xff0c 除了期待即将推出的社交应用 Voice 能给 EOS 注入新的活力外 xff0c 我已经很难找到 EOS 上的新热点 xff0c 而一些危险的信号 xff0c 可能对 EOS 的发展带来负面的影响 xff0c
  • 五轴机械臂实现视觉抓取--realsense深度相机和五自由度机械臂

    前言 xff1a 要实现视觉抓取 xff0c 首先需要实现机械臂的驱动 xff0c 深度相机的目标识别 xff0c 能够反馈位置 1 实现机械臂在ROS层的控制 2 基于深度相机目标物体的空间坐标反馈 xff0c 需要知道摄像头中物体的像素
  • solvepnp三维位姿估算

    一 前言 关于PNP问题就是指通过世界中的N个特征点与图像成像中的N个像点 xff0c 计算出其投影关系 xff0c 从而获得相机或物体位姿的问题 opencv提供的solvepnp函数就是用来解决pnp问题 利用该函数可以实现测算相机 物
  • emwin自定义颜色

    颜色管理中已经帮助我们定义了这些颜色 xff0c 但是我们通常会使用自定义的颜色 xff0c 怎么怎么设置值呢 xff1f 通常情况下使用的是BGR颜色 就是蓝色和红色是相反的 GUI SetBkColor 0x00FFaa80 自定义调色
  • STemwin 实现滑动切换主页 滑动翻页 滑动解锁功能

    STM32上实现类似iPhone的解锁和滑屏功能 xff0c emwin这个库官方的文档中控件没有一样的 xff0c 但是有一个上下滑动的 xff0c 基本上能够完成大致上的功能 xff0c 但是如果想使用emwin实现类似的效果的话 xf