本章节为大家讲解按钮控件自定义回调函数,通过其回调函数就可以实现各种按钮效果。

初学者重要提示

1、很多时候,我们希望设计出不同效果的按钮出来,比如做一个音乐播放器界面将快进,快退,暂停,开始等都通过按钮来实现,这个时候时候按钮的自定义回调函数就派上用场了。

希望初学者掌握这个重要的知识点。不仅仅是按钮控件,后面要讲解到的其它控件都是可以设置自定义回调函数。

2、按钮控件的所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数位置:


下图是英文版手册里面API函数的位置:

按钮控件自定义回调函数的实现方法

按钮控件的本质也是窗口,所以也是有回调函数的,只是被封装了,用户看不到,不像我们使用窗口或者框架窗口的时候还需要专门的设置回调函数。

实现自定义回调函数的关键就是函数WM_SetCallback,通过这个函数就可以重定向按钮的回调函数,从而也就可以实现各种效果的按钮。
下面我们通过一个实例给大家介绍如何实现按钮控件的自定义回调函数。
完整代码在例子V6-563_STemWin实验_Button按钮控通过自定义回调函数实现各种按钮效果(模拟器)里面:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "DIALOG.h"
static GUI_CONST_STORAGE unsigned long _acpic1[] ={
 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000,
                0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
                0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000,
};

GUI_CONST_STORAGE GUI_BITMAP bmpic1 = {
  64, // xSize
  64, // ySize
  256, // BytesPerLine
  32, // BitsPerPixel
  (unsignedchar *)_acpic1,  // Pointer to picture data
  NULL,  // Pointer to palette
 GUI_DRAW_BMP8888
}

#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
#define ID_BUTTON_0   (GUI_ID_USER + 0x01)
#define ID_BUTTON_1   (GUI_ID_USER + 0x02)
static const GUI_WIDGET_CREATE_INFO_aDialogCreate[] =
{
  {FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 800, 480,0, 0x64, 0 },
  {BUTTON_CreateIndirect,  "",                 ID_BUTTON_0,30, 30, 64, 64, 0, 0x0, 0 },
  {BUTTON_CreateIndirect,  "",                 ID_BUTTON_1,30, 120, 120, 40, 0, 0x0, 0 },
};
static void _cbButton(WM_MESSAGE * pMsg) //--------------3{        WM_HWIN  hWin;      hWin  = pMsg->hWin;
         switch(pMsg->MsgId)
         {
                 caseWM_PAINT:
                          if(BUTTON_IsPressed(hWin))
                          {
                                   GUI_SetBkColor(GUI_WHITE);
                                   GUI_Clear();
                                   GUI_SetAlpha(0xb0);
                                   GUI_DrawBitmap(&bmpic1,0,0);
                                   GUI_SetAlpha(0);       
                          }
                          else
                          {
                                   GUI_DrawBitmap(&bmpic1,0, 0);          
                          }
                          break;

                 default:
                          BUTTON_Callback(pMsg);
         }
}
static void _cbButton1(WM_MESSAGE * pMsg)  //--------------(6)
{
         WM_HWIN  hWin;
         GUI_RECTRect;
         hWin  = pMsg->hWin;
         switch(pMsg->MsgId)
         {
                 caseWM_PAINT:
                          WM_GetClientRect(&Rect);
                          if(BUTTON_IsPressed(hWin))
                          {
                                   GUI_SetColor(GUI_DARKGRAY);
                                   GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
                                   GUI_SetBkColor(GUI_DARKGRAY);
                                   GUI_SetColor(GUI_WHITE);
                          }
                          else
                          {
                                   GUI_SetColor(GUI_LIGHTBLUE);
                                   GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
                                   GUI_SetBkColor(GUI_LIGHTBLUE);
                                   GUI_SetColor(GUI_WHITE);  
                          }

                          GUI_SetFont(&GUI_Font16_ASCII);
                          GUI_DispStringInRect("LED1",&Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
                          break;

                 default:
                          BUTTON_Callback(pMsg);
         }
}
static void _cbDialog(WM_MESSAGE * pMsg)
{
         WM_HWINhItem;
         int         NCode;
         int         Id;
         switch(pMsg->MsgId)
         {
                 caseWM_INIT_DIALOG:
                          //
                          //初始化框架窗口
                          //
                          hItem= pMsg->hWin;
                          FRAMEWIN_SetFont(hItem,GUI_FONT_32B_ASCII);
                          FRAMEWIN_SetTextAlign(hItem,GUI_TA_HCENTER | GUI_TA_VCENTER);
                          FRAMEWIN_SetText(hItem,"armfly");

                          //
                          //初始化按钮控件
                          //
                          hItem= WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
                          WM_SetHasTrans(hItem);                         //--------------(1)
                          WM_SetCallback(hItem,_cbButton);  //--------------(2)
                          //
                          //初始化按钮控件
                          //
                          hItem= WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
                          WM_SetHasTrans(hItem);                         //--------------(4)
                          WM_SetCallback(hItem,_cbButton1); //--------------(5)
                          break;
                 caseWM_NOTIFY_PARENT:
                          Id        = WM_GetId(pMsg->hWinSrc);
                          NCode= pMsg->Data.v;
                          switch(Id)
                          {
                                   caseID_BUTTON_0:
                                           switch(NCode)
                                           {
                                                        caseWM_NOTIFICATION_CLICKED:
                                                                 break;
                                                        caseWM_NOTIFICATION_RELEASED:
                                                                 break;
                                           }
                                           break;
                          }
                          break;
                 default:
                 WM_DefaultProc(pMsg);
                 break;
         }
}
/*
*********************************************************************************************************
*       函 数名: CreateFramewin
*       功能说明: 创建对话框        
*       形       参:无
*       返 回值: 返回对话框句柄
*********************************************************************************************************
*/
WM_HWIN CreateFramewin(void) {
  WM_HWINhWin;
  hWin =GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog,WM_HBKWIN, 0, 0);
  returnhWin;
}
void MainTask(void)
{

         GUI_Init();

         WM_SetCreateFlags(WM_CF_MEMDEV);

         CreateFramewin();
         while(1)
         {
                 GUI_Delay(10);
         }
}

这个例子在对话框上创建了2个按钮控件,每个按钮都重新设置了回调函数,实现了两种不同的按钮效果,一个是图标按钮,另一个是扁平化效果的按钮。

  1. 通过函数WM_SetHasTrans设置ID为ID_BUTTON_0的按钮控件的透明效果,调用了这个函数有什么用呢?
    通过这个函数就可以将按钮回调函数中WM_PAINT消息没有重绘到的区域显示为完全透明,比如我们在按钮控件回调函数的WM_PAINT消息里面绘制了一个填充的圆圈,那么按钮控件所在区域的圆圈以外部分就是完全透明的。

  2. 通过函数WM_SetCallback重新设置ID为ID_BUTTON_0的按钮控件的回调函数。

  3. 通过此回调函数就可以设置各种效果的按钮了,这里是将按钮设置成一个图标。

这个回调函数只有两个消息,一个是WM_PAINT,一个是默认的default,也就是说除了WM_PAINT消息以外,
其它所有消息还是使用按钮控件默认的回调处理机制BUTTON_Callback来实现。
这个问题解释清楚了,剩下就是WM_PAINT消息里面实现的功能了,
这个消息里面实现了按钮按下和未按下两种状态的显示效果,通过函数BUTTON_IsPressed来区分这两种状态,返回1就是按下了,返回0就是未按下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
if (BUTTON_IsPressed(hWin))
{
         GUI_SetBkColor(GUI_WHITE);
         GUI_Clear();

         GUI_SetAlpha(0xb0);
         GUI_DrawBitmap(&bmpic1,0,0);

         GUI_SetAlpha(0);         
}
else
{
         GUI_DrawBitmap(&bmpic1,0, 0);        
}

通过上面的代码就实现了按钮未按下时显示的是一个图标,按下时是一个有透明效果的图标。

  1. 通过函数WM_SetHasTrans设置ID为ID_BUTTON_1的按钮控件的透明效果。
  2. 通过函数WM_SetCallback重新设置ID为ID_BUTTON_1的按钮控件的回调函数。
  3. 通过此回调函数就可以设置各种效果的按钮了,这里是将按钮设置成圆角矩形。这里我们重点看WM_PAINT消息,其它跟第3条讲解的是一样的。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    WM_GetClientRect(&Rect);
    if (BUTTON_IsPressed(hWin))
    {
    
         GUI_SetColor(GUI_DARKGRAY);
    
         GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
    
         GUI_SetBkColor(GUI_DARKGRAY);
         GUI_SetColor(GUI_WHITE);
    }
    else
    {
         GUI_SetColor(GUI_LIGHTBLUE);
    
         GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
    
         GUI_SetBkColor(GUI_LIGHTBLUE);
         GUI_SetColor(GUI_WHITE);  
    }
    GUI_SetFont(&GUI_Font16_ASCII);
    GUI_DispStringInRect("LED1", &Rect,GUI_TA_HCENTER | GUI_TA_VCENTER);
    
    <p>
      通过上面的代码就实现了按钮未按下和按下时两种不同的按钮颜色。实际显示效果如下,分辨率800*480:<br /> 
      
      
      
      
      
        
          
          
        
      
      
      ![](/images/2022/01/image-1641522697762.png" alt="file" /></figure><br /> 通过学习这个实例,建议大家尝试设置各种其它的按钮显示效果。
    </p>
    

官方WIDGET_ButtonRound.c实例讲解

这个DEMO在模拟器中的位置:

主要功能介绍:

这个例子演示了按钮自定义回调函数的实现,通过其回调函数实现了一个圆形的按钮,由于是官方做的例子,所以细节的处理上更专业些。学习这个例子前务必先学习前面47.2小节的讲解。

程序代码如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include
#include
#include "WM.h"
#include "FRAMEWIN.h"
#include "BUTTON.h"
//
// Recommended memory to run thesample with adequate performance
//
#define RECOMMENDED_MEMORY (1024L * 5)
static int _Color;
static int _Font;
static int _Pressed;
static const GUI_WIDGET_CREATE_INFO_aDialogCreate[] = {
  {FRAMEWIN_CreateIndirect, "Round button sample", 0,       50, 60, 200, 120, FRAMEWIN_CF_MOVEABLE },
  {BUTTON_CreateIndirect,  "Button",  GUI_ID_BUTTON0,   100,  10, 80,  80 },
  { BUTTON_CreateIndirect,   "Callback", GUI_ID_BUTTON1,      10, 10,  60,  20 },
  {BUTTON_CreateIndirect,  "Font",        GUI_ID_BUTTON2,     10,  30, 60,  20 },
  {BUTTON_CreateIndirect,  "Color",   GUI_ID_BUTTON3,     10,  50, 60,  20 },
  {BUTTON_CreateIndirect,  "Cancel",  GUI_ID_CANCEL,       10,  70, 60,  20 }
};
static void _OnPaint(BUTTON_Handle hObj) { //--------------(1)
  int Index;
  charac[50];
  GUI_RECTRect;
  Index =(WIDGET_GetState(hObj) & BUTTON_STATE_PRESSED) ? 1 : 0; //--------------(2)
 WM_GetClientRect(&Rect);
  //
 // Draw filled ellipse with button background color
 //
 GUI_SetColor(BUTTON_GetBkColor(hObj, Index));
  GUI_FillEllipse(Rect.x1/ 2, Rect.y1 / 2, Rect.x1 / 2, Rect.y1 / 2);
 //
 // Draw black shape
 //
 GUI_SetColor(GUI_BLACK);
 GUI_DrawEllipse(Rect.x1 / 2, Rect.y1 / 2, Rect.x1 / 2, Rect.y1 / 2);
  //
 // Draw button text with widget attributes
 //
 GUI_SetColor(BUTTON_GetTextColor(hObj, Index));
 GUI_SetBkColor(BUTTON_GetBkColor(hObj, Index));
 GUI_SetFont(BUTTON_GetFont(hObj));
 BUTTON_GetText(hObj, ac, sizeof(ac));
  if(_Pressed) {                                                         //--------------(3)
        strcpy(ac+ strlen(ac), "\npressed");
  }
 GUI_DispStringInRect(ac, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
}
static void _cbButton(WM_MESSAGE * pMsg) {  //--------------(4)
  switch(pMsg-&gt;MsgId) {
        caseWM_PAINT:                                                 //--------------(5)
         _OnPaint(pMsg-&gt;hWin);
          break;
        default:                                                                //--------------(6)
         BUTTON_Callback(pMsg); // The original callback
          break;
  }
  if(pMsg-&gt;MsgId == WM_TOUCH) {                 //--------------(7)
        if(BUTTON_IsPressed(pMsg-&gt;hWin)) {
          if(!_Pressed) {
           _Pressed = 1;
          }
        } else {
         _Pressed = 0;
        }
  }
}
static void _cbDialog(WM_MESSAGE * pMsg) {
  int                  NCode;
  int                  Id;
 WM_HWIN           hDlg;
 BUTTON_Handle hButton;
  hDlg =pMsg-&gt;hWin;
  switch(pMsg-&gt;MsgId) {
        caseWM_PAINT:
         WM_DefaultProc(pMsg); // Handle dialog items       //--------------(8)
          //
         // After drawing the dialog items add some user drawn items to thewindow
         //
         GUI_SetPenSize(10);
         GUI_SetColor(GUI_GREEN);
         GUI_DrawLine( 95,  5, 185, 95);
         GUI_SetColor(GUI_RED);
         GUI_DrawLine( 95, 95, 185,  5);
          break;
        caseWM_INIT_DIALOG:
         hButton = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0);
         WM_SetHasTrans(hButton);                        // Settransparency flag for button   //--------------(9)
          break;
        caseWM_KEY:
          switch(((WM_KEY_INFO *)(pMsg-&gt;Data.p))-&gt;Key) {
                caseGUI_KEY_ESCAPE:
                 GUI_EndDialog(hDlg, 1);
                 break;
                caseGUI_KEY_ENTER:
                 GUI_EndDialog(hDlg, 0);
                 break;
          }
          break;
        caseWM_NOTIFY_PARENT:
         Id     =WM_GetId(pMsg-&gt;hWinSrc);          // Id of widget
          NCode= pMsg-&gt;Data.v;                                // Notification code
          switch(NCode) {
                caseWM_NOTIFICATION_RELEASED:         // React only if released //--------------(10)
                 hButton = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0);
                  if(Id == GUI_ID_BUTTON1) {           // Toggle callback //--------------(11)
                   if (WM_GetCallback(hButton) == _cbButton) {
                         WM_SetCallback(hButton, BUTTON_Callback);
                   } else {
                         WM_SetCallback(hButton, _cbButton);
                   }
                   WM_InvalidateWindow(hButton);
                  }
                  if(Id == GUI_ID_BUTTON2) {           // Toggle font //--------------(12)
                   if (_Font) {
                         BUTTON_SetFont(hButton, &GUI_Font13_1);
                   } else {
                         BUTTON_SetFont(hButton, &GUI_Font8x16);
                   }
                   _Font ^= 1;
                  }
                  if(Id == GUI_ID_BUTTON3) {           // Toggle color //--------------(13)
                   if (_Color) {
                         BUTTON_SetBkColor(hButton, 0, 0xaaaaaa);
                         BUTTON_SetBkColor(hButton, 1, GUI_WHITE);
                         BUTTON_SetTextColor(hButton, 0, GUI_BLACK);
                         BUTTON_SetTextColor(hButton, 1, GUI_BLACK);
                   } else {
                          BUTTON_SetBkColor(hButton, 0, GUI_BLUE);
                         BUTTON_SetBkColor(hButton, 1, GUI_RED);
                         BUTTON_SetTextColor(hButton, 0, GUI_WHITE);
                         BUTTON_SetTextColor(hButton, 1, GUI_YELLOW);
                   }
                   _Color ^= 1;
                  }
                  if(Id == GUI_ID_OK) {                     // OK Button //--------------(14)
                   GUI_EndDialog(hDlg, 0);
                  }
                  if(Id == GUI_ID_CANCEL) {             // Cancel Button //--------------(15)
                   GUI_EndDialog(hDlg, 1);
                  }
                 break;
          }
          break;
        default:
         WM_DefaultProc(pMsg);
  }
}
void MainTask(void) {
 GUI_Init();
  //
 // Check if recommended memory for the sample is available
 //
  if(GUI_ALLOC_GetNumFreeBytes() &lt; RECOMMENDED_MEMORY) {
   GUI_ErrorOut("Not enough memory available.");
        return;
  }
  //
 // Use memory devices for all windows
 //
  #ifGUI_SUPPORT_MEMDEV
   WM_SetCreateFlags(WM_CF_MEMDEV);
   WM_EnableMemdev(WM_HBKWIN);
  #endif
 WM_SetDesktopColor(GUI_GREEN);
  while(1) {
        _Font =_Color = 0;
   GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate),&_cbDialog, 0, 0, 0);
   GUI_Delay(1000);
  }
}
  1. 按钮自定义回调函数中WM_PAINT消息的处理。
  2. 通过函数(WIDGET_GetState(hObj) & BUTTON_STATE_PRESSED) ? 1: 0返回当前按钮是按下还是未按下,按下的话,返回数值1,未按下返回数值0。根据这个返回值,在WM_PIANT消息里面绘制按钮按下和未按下两种状态的显示效果。
  3. 根据变量_Pressed的数值设置是否显示字符,如果变量数值非0表示按钮被按下,显示字符Button pressed,如果未按下,仅显示字符Button。变量_Pressed数值的改变是在按钮回调函数_cbButton里面修改的。其实这里直接使用第2条中函数(WIDGET_GetState(hObj) &BUTTON_STATE_PRESSED) ? 1 : 0的返回值就可以的,官方这里设计的稍有些啰嗦了。
  4. 按钮自定义的回调函数。
  5. 按钮自定义回调函数中WM_PAINT消息的处理。
  6. 按钮回调函数中,除了WM_PIANT消息,其它消息的处理继续使用系统默认的函数BUTTON_Callback(pMsg)来实现。
  7. 如果按钮被按下,回调函数首先收到的就是这个WM_TOUCH消息,然后才是WM_PAINT消息的处理,这样的话,就可以通过这个消息配合函数BUTTON_IsPressed(pMsg->hWin)来设置变量_Pressed,赋值为1表示按下,赋值为0表示未按下。
  8. 函数WM_DefaultProc(pMsg)放在这里比较巧妙,先调用这个函数的话,系统就会按照默认配置先重绘对话框,然后用户在这个基础上再绘制自己需要的内容。
  9. 通过函数WM_SetHasTrans设置ID为GUI_ID_BUTTON0的按钮控件的透明效果。
  10. 按钮释放后的消息处理。
  11. 按钮ID为GUI_ID_BUTTON1的按钮释放消息处理,这里实现对ID为GUI_ID_BUTTON0按钮的回调函数切换。
  12. 按钮ID为GUI_ID_BUTTON2的按钮释放消息处理,这里实现对ID为GUI_ID_BUTTON0按钮显示字体的切换。
  13. 按钮ID为GUI_ID_BUTTON3的按钮释放消息处理,这里实现对ID为GUI_ID_BUTTON0按钮显示文本的背景色和前景色的切换。
  14. 按钮ID为GUI_ID_OK的按钮释放消息处理,此按钮在本程序未用到,因为没有创建ID为GUI_ID_OK的按钮。
  15. 按钮ID为GUI_ID_CANCEL的按钮释放消息处理,这里实现关闭阻塞式对话框。如果关闭了,1秒后会重新创建这个对话框,如此循环。

显示效果如下:

实验例程说明(RTOS)配套例子:

V6-561_STemWin实验_Button按钮控通过自定义回调函数实现各种按钮效果(RTOS)

实验目的:

  1. 本实验主要学习通过按钮自定义回调函数实现各种按钮效果。这里实现了两种按钮效果,一个是图标按钮,另一个是扁平化效果的按钮。

  2. emWin功能的实现在MainTask.c文件里面。
    ## 实验内容:

  3. K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。

  4. K2按键按下,实现截图功能,将图片以BMP格式保存到SD卡中。

  5. 各个任务实现的功能如下:
    App Task Start 任务:实现按键和触摸扫描。
    App Task MspPro任务 :实现截图功能,将图片以BMP格式保存到SD卡中。
    App Task UserIF 任务:按键消息处理。
    App Task COM 任务:暂未使用。
    App Task GUI 任务:GUI任务。
    μCOS-III任务调试信息(按K1按键,串口打印):

## STemWin界面显示效果:

800*480分辨率界面效果。

STemWin动态内存配置:

GUIConf.c文件中的配置如下:

1
2
3
4
5
6
#define EX_SRAM  1
#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*8)
#else
#define GUI_NUMBYTES  (100*1024)
#endif

通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

#define EX_SRAM 1 表示使用外部SDRAM作为emWin动态内存,大小8MB。
#define EX_SRAM 0 表示使用内部SRAM作为emWin动态内存,大小100KB。
默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

STemWin底层接口配置:

LCDConf_Lin_Template.c文件中共12项emWin配置:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#define emWin_Optimize   0
#define XSIZE_PHYS         800
#define YSIZE_PHYS         480
#define NUM_BUFFERS       3
#define NUM_VSCREENS         1
#define BK_COLOR                GUI_DARKBLUE
#undef GUI_NUM_LAYERS
#define GUI_NUM_LAYERS      1
#define LCD_LAYER0_FRAME_BUFFER  EXT_SDRAM_ADDR
#define LCD_LAYER1_FRAME_BUFFER  (LCD_LAYER0_FRAME_BUFFER + XSIZE_PHYS *YSIZE_PHYS * 4 * NUM_VSCREENS *
NUM_BUFFERS)
#define_CM_ARGB8888       1
#define _CM_RGB888              2
#define _CM_RGB565              3
#define _CM_ARGB1555          4
#define _CM_ARGB4444          5
#define _CM_L8                      6
#define _CM_AL44                  7
#define _CM_AL88                  8
#define COLOR_MODE_0          _CM_RGB565
#define XSIZE_0                XSIZE_PHYS
#define YSIZE_0                YSIZE_PHYS
#define COLOR_MODE_1          _CM_RGB565
#define XSIZE_1                XSIZE_PHYS
#define YSIZE_1                YSIZE_PHYS
#if  (COLOR_MODE_0 == _CM_ARGB8888)
  #defineCOLOR_CONVERSION_0 GUICC_M8888I
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_32
#elif (COLOR_MODE_0 == _CM_RGB888)
  #defineCOLOR_CONVERSION_0 GUICC_M888
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_24
#elif (COLOR_MODE_0 == _CM_RGB565)
  #defineCOLOR_CONVERSION_0 GUICC_M565
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#elif (COLOR_MODE_0 == _CM_ARGB1555)
  #defineCOLOR_CONVERSION_0 GUICC_M1555I
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#elif (COLOR_MODE_0 == _CM_ARGB4444)
  #defineCOLOR_CONVERSION_0 GUICC_M4444I
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#elif (COLOR_MODE_0 == _CM_L8)
  #defineCOLOR_CONVERSION_0 GUICC_8666
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_8
#elif (COLOR_MODE_0 == _CM_AL44)
  #define COLOR_CONVERSION_0GUICC_1616I
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_8
#elif (COLOR_MODE_0 == _CM_AL88)
  #defineCOLOR_CONVERSION_0 GUICC_88666I
  #defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#else
  #errorIllegal color mode 0!
#endif
#if (GUI_NUM_LAYERS &gt; 1)
#if  (COLOR_MODE_1 == _CM_ARGB8888)
  #defineCOLOR_CONVERSION_1 GUICC_M8888I
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_32
#elif (COLOR_MODE_1 == _CM_RGB888)
  #defineCOLOR_CONVERSION_1 GUICC_M888
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_24
#elif (COLOR_MODE_1 == _CM_RGB565)
  #defineCOLOR_CONVERSION_1 GUICC_M565
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#elif (COLOR_MODE_1 == _CM_ARGB1555)
  #defineCOLOR_CONVERSION_1 GUICC_M1555I
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#elif (COLOR_MODE_1 == _CM_ARGB4444)
  #defineCOLOR_CONVERSION_1 GUICC_M4444I
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#elif (COLOR_MODE_1 == _CM_L8)
  #defineCOLOR_CONVERSION_1 GUICC_8666
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_8
#elif (COLOR_MODE_1 == _CM_AL44)
  #defineCOLOR_CONVERSION_1 GUICC_1616I
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_8
#elif (COLOR_MODE_1 == _CM_AL88)
  #defineCOLOR_CONVERSION_1 GUICC_88666I
  #defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#else
  #error Illegalcolor mode 1!
#endif
#else
#undef XSIZE_0
#undef YSIZE_0
#define XSIZE_0        XSIZE_PHYS
#define YSIZE_0        YSIZE_PHYS
#endif
#ifndef  XSIZE_PHYS
  #errorPhysical X size of display is not defined!
#endif
#ifndef  YSIZE_PHYS
  #errorPhysical Y size of display is not defined!
#endif
#ifndef  NUM_VSCREENS
  #defineNUM_VSCREENS 1
#else
  #if(NUM_VSCREENS &lt;= 0)
        #errorAt least one screeen needs to be defined!
  #endif
#endif
#if (NUM_VSCREENS &gt; 1) && (NUM_BUFFERS&gt; 1)
  #errorVirtual screens and multiple buffers are not allowed!
#endif

对于这12个配置选项,注释说明已经比较详细。默认情况下,本教程配套的emWin例子都是用的三缓冲,RGB565格式,且仅使用单图层。

程序设计:

任务栈大小分配:

μCOS-III任务栈大小在os_cfg.h文件中配置:

1
2
3
4
5
#define  APP_CFG_TASK_START_STK_SIZE                                         512u
#define  APP_CFG_TASK_MsgPro_STK_SIZE                                       512u
#define  APP_CFG_TASK_COM_STK_SIZE                                         512u
#define  APP_CFG_TASK_USER_IF_STK_SIZE                                      512u
#define  APP_CFG_TASK_GUI_STK_SIZE                                              1024u

任务栈大小的单位是4字节,那么每个任务的栈大小如下:

   App Task Start   任务:2048字节。
       App Task MspPro任务 :2048字节。
       App Task UserIF  任务:2048字节。
       App Task COM   任务:2048字节。
   App Task GUI     任务:4096字节。

系统栈大小分配:

μCOS-III的系统栈大小在os_cfg_app.h文件中配置:

1
#define  OS_CFG_ISR_STK_SIZE                                          512u       

系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB。

μCOS-III初始化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int main(void)
{
   OS_ERR  err; 

   OSInit(&err); 

         OSTaskCreate((OS_TCB          *)&AppTaskStartTCB,                       
                                (CPU_CHAR        *)"App TaskStart", 
                                (OS_TASK_PTR   )AppTaskStart,         
                                (void                *)0,                                
                                (OS_PRIO          )APP_CFG_TASK_START_PRIO,
                                (CPU_STK         *)&AppTaskStartStk[0],      
                                (CPU_STK_SIZE )APP_CFG_TASK_START_STK_SIZE / 10,
                                (CPU_STK_SIZE )APP_CFG_TASK_START_STK_SIZE,      
                                (OS_MSG_QTY     )0,  
                                (OS_TICK           )0, 
                                (void                *)0,   
                                (OS_OPT        )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),

                                (OS_ERR        *)&err);

   OSStart(&err);                                                                                         

   (void)&err;

        return(0);
}

硬件外设初始化

硬件外设的初始化是在bsp.c文件实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void bsp_Init(void)
{

   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);

         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

         SystemCoreClockUpdate();   
         bsp_InitUart();           
         bsp_InitKey();             

         bsp_InitExtIO();          
         bsp_InitLed();        

         bsp_InitI2C();             
         bsp_InitSPIBus();        

         bsp_InitSFlash();         

         bsp_InitExtSDRAM();   
         bsp_DetectLcdType();  

         TOUCH_InitHard();      
         LCD_ConfigLTDC();       

         result =f_mount(&fs, "0:/", 0);      
}

五个μCOS-III任务的实现:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
static void  AppTaskStart (void *p_arg)
{
         OS_ERR       err;
         uint8_t  ucCount = 0;
         uint8_t  ucCount1 = 0;

   (void)p_arg; 

         CPU_Init(); 
         bsp_Init();          
         BSP_Tick_Init(); 

#if OS_CFG_STAT_TASK_EN &gt; 0u
        OSStatTaskCPUUsageInit(&err);  
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
   CPU_IntDisMeasMaxCurReset();
#endif

         AppTaskCreate();

         AppObjCreate();

        while(1)
        {

                 if(g_tTP.Enable== 1)
                 {
                          TOUCH_Scan();

                          ucCount++;
                          if(ucCount== 10)
                          {
                                   ucCount= 0;
                                   bsp_KeyScan();
                          }
                         OSTimeDly(1, OS_OPT_TIME_DLY, &err);                 
                 }

                 if(g_GT811.Enable== 1)
                 {
                          bsp_KeyScan();
                          ucCount1++;
                          if(ucCount1== 2)
                          {
                                   ucCount1= 0;
                                   GT811_OnePiontScan();
                          }
                         OSTimeDly(10, OS_OPT_TIME_DLY, &err);       
                 }

                 if(g_tFT5X06.Enable== 1)
                 {
                          bsp_KeyScan();
                          FT5X06_OnePiontScan();
                         OSTimeDly(10, OS_OPT_TIME_DLY, &err);
                 }
        }       
}
static void AppTaskMsgPro(void *p_arg)
{
         uint32_tulStart, ulEnd;
         OS_ERR       err;
         uint8_t           Pic_Name = 0;
         charbuf[20];
         (void)p_arg;

         while(1)
         {   

                 OSSemPend((OS_SEM*)&SEM_SYNCH,
                                         (OS_TICK )0,
                                         (OS_OPT )OS_OPT_PEND_BLOCKING,
                                         (CPU_TS )0,
                                         (OS_ERR *)&err);

                 if(err== OS_ERR_NONE)
                 {   
                          sprintf(buf,"0:/PicSave/%d.bmp",Pic_Name);

                          ulStart= OSTimeGet(&err);

                          OSSchedLock(&err);

                          result= f_mkdir("0:/PicSave");

                          result= f_open(&file,buf, FA_WRITE|FA_CREATE_ALWAYS);

                          GUI_BMP_Serialize(_WriteByte2File,&file);

                         result = f_close(&file);

                          OSSchedUnlock(&err);

                          ulEnd= OSTimeGet(&err);
                          ulEnd-= ulStart;

                          App_Printf("截图完成,耗时 = %dms\r\n", ulEnd);
                          Pic_Name++;         
                 }                                                                                                                                                                                                                                
         }  
}
static void AppTaskUserIF(void *p_arg)
{
         OS_ERR       err;
         uint8_t  ucKeyCode;

         (void)p_arg;                          

         while(1)
         {         
                 ucKeyCode= bsp_GetKey();

                 if(ucKeyCode != KEY_NONE)
                 {
                          switch(ucKeyCode)
                          {
                                   caseKEY_DOWN_K1:                     
                                           DispTaskInfo();              
                                           break;

                                   caseKEY_DOWN_K2:                     
                                           OSSemPost((OS_SEM*)&SEM_SYNCH,
                                                                  (OS_OPT )OS_OPT_POST_1,
                                                                  (OS_ERR *)&err); 
                                           break;

                                   default:                                      
                                           break;
                          }
                 }

                 OSTimeDly(20,OS_OPT_TIME_DLY, &err);
         }
}
static void AppTaskCOM(void *p_arg)
{
         OS_ERR  err;         

         (void)p_arg;

         while(1)
         {   
                 OSTimeDly(500, OS_OPT_TIME_DLY, &err);
         }                                                                                                                                                                                              
}
static void AppTaskGUI(void *p_arg)
{
   (void)p_arg;       

         while(1)
         {
                 MainTask();
         }
}

emWin任务的具体实现(在MainTask.c文件里面):

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include"MainTask.h"
#include"includes.h"
static GUI_CONST_STORAGE unsigned long _acpic1[] ={
 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000,
           0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000,
           0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000,

};
GUI_CONST_STORAGE GUI_BITMAP bmpic1 = {
  64, // xSize
  64, // ySize
  256, // BytesPerLine
  32, // BitsPerPixel
  (unsignedchar *)_acpic1,  // Pointer to picture data
  NULL,  // Pointer to palette
 GUI_DRAW_BMP8888
}
#defineID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
#defineID_BUTTON_0   (GUI_ID_USER + 0x01)
#defineID_BUTTON_1   (GUI_ID_USER + 0x02)
static constGUI_WIDGET_CREATE_INFO _aDialogCreate[] =
{
  { FRAMEWIN_CreateIndirect,"Framewin", ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0 },
  { BUTTON_CreateIndirect,   "",               ID_BUTTON_0, 30, 30, 80, 80, 0, 0x0, 0},
  { BUTTON_CreateIndirect,   "",               ID_BUTTON_1, 30, 150, 120, 40, 0, 0x0,0 },
};
static void_cbButton(WM_MESSAGE * pMsg)
{
         WM_HWIN hWin;
         hWin = pMsg-&gt;hWin;
         switch (pMsg-&gt;MsgId)
         {
                 case WM_PAINT:
                          if (BUTTON_IsPressed(hWin))
                          {
                                   GUI_SetBkColor(GUI_WHITE);
                                   GUI_Clear();
                                   GUI_SetAlpha(0xb0);
                                   GUI_DrawBitmap(&bmpic1,8, 8);
                                   GUI_SetAlpha(0);       
                          }
                          else
                          {
                                   GUI_DrawBitmap(&bmpic1,8, 8);          
                          }
                          break;

                 default:
                          BUTTON_Callback(pMsg);
         }
}
static void_cbButton1(WM_MESSAGE * pMsg)
{
         WM_HWIN hWin;
         GUI_RECT Rect;
         hWin = pMsg-&gt;hWin;
         switch (pMsg-&gt;MsgId)
         {
                 case WM_PAINT:
                          WM_GetClientRect(&Rect);
                          if (BUTTON_IsPressed(hWin))
                          {
                                   GUI_SetColor(GUI_DARKGRAY);
                                   GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
                                   GUI_SetBkColor(GUI_DARKGRAY);
                                   GUI_SetColor(GUI_WHITE);
                          }
                          else
                          {
                                   GUI_SetColor(GUI_LIGHTBLUE);
                                   GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
                                   GUI_SetBkColor(GUI_LIGHTBLUE);
                                   GUI_SetColor(GUI_WHITE);  
                          }

                          GUI_SetFont(&GUI_Font16_ASCII);
                          GUI_DispStringInRect("LED1",&Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
                          break;

                 default:
                          BUTTON_Callback(pMsg);
         }
}
static void_cbDialog(WM_MESSAGE * pMsg)
{
         WM_HWIN hItem;
         int        NCode;
         int        Id;
         switch (pMsg-&gt;MsgId)
         {
                 case WM_INIT_DIALOG:
                          //
                          //初始化框架窗口
                          //
                          hItem = pMsg-&gt;hWin;
                          FRAMEWIN_SetFont(hItem,GUI_FONT_32B_ASCII);
                          FRAMEWIN_SetTextAlign(hItem,GUI_TA_HCENTER | GUI_TA_VCENTER);
                          FRAMEWIN_SetText(hItem,"armfly");

                          //
                          //初始化按钮控件
                          //
                          hItem =WM_GetDialogItem(pMsg-&gt;hWin, ID_BUTTON_0);
                          WM_SetHasTrans(hItem);
                          WM_SetCallback(hItem, _cbButton);
                          //
                          //初始化按钮控件
                          //
                          hItem =WM_GetDialogItem(pMsg-&gt;hWin, ID_BUTTON_1);
                          WM_SetHasTrans(hItem);
                          WM_SetCallback(hItem, _cbButton1);
                          break;
                 case WM_NOTIFY_PARENT:
                          Id        = WM_GetId(pMsg-&gt;hWinSrc);
                          NCode = pMsg-&gt;Data.v;
                          switch(Id)
                          {
                                   case ID_BUTTON_0:
                                           switch(NCode)
                                           {
                                                        caseWM_NOTIFICATION_CLICKED:
                                                                 break;
                                                        caseWM_NOTIFICATION_RELEASED:
                                                                 break;
                                           }
                                           break;
                          }
                          break;
                 default:
                 WM_DefaultProc(pMsg);
                 break;
         }
}
WM_HWINCreateFramewin(void)
{
         WM_HWIN hWin;
         hWin = GUI_CreateDialogBox(_aDialogCreate,GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
         return hWin;
}
voidMainTask(void)
{

         GUI_Init();

         WM_MULTIBUF_Enable(1);

        //TOUCH_Calibration();

         CreateFramewin();

         while(1)
         {
                 GUI_Delay(10);
         }
}

实验例程说明(裸机)配套例子:

V6-562_STemWin实验_Button按钮控通过自定义回调函数实现各种按钮效果(裸机)

实验目的:

  1. 本实验主要学习通过按钮自定义回调函数实现各种按钮效果。这里实现了两种按钮效果,一个是图标按钮,另一个是扁平化效果的按钮。
  2. emWin功能的实现在MainTask.c文件里面。
### STemWin界面显示效果:

800*480分辨率界面效果。

### STemWin动态内存配置:

GUIConf.c文件中的配置如下:
1
2
3
4
5
6
#define EX_SRAM  1
#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*8)
#else
#define GUI_NUMBYTES  (100*1024)
#endif
通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

# define EX_SRAM 1 表示使用外部SDRAM作为emWin动态内存,大小8MB。

# define EX_SRAM 0 表示使用内部SRAM作为emWin动态内存,大小100KB。

默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

### STemWin底层接口配置:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
LCDConf_Lin_Template.c文件中共12项emWin配置
#define emWin_Optimize   0
#define XSIZE_PHYS         800
#define YSIZE_PHYS         480
#define NUM_BUFFERS       3
#define NUM_VSCREENS         1
#define BK_COLOR                GUI_DARKBLUE
#undef GUI_NUM_LAYERS
#define GUI_NUM_LAYERS      1
#define LCD_LAYER0_FRAME_BUFFER  EXT_SDRAM_ADDR
#define LCD_LAYER1_FRAME_BUFFER  (LCD_LAYER0_FRAME_BUFFER + XSIZE_PHYS *YSIZE_PHYS * 4 * NUM_VSCREENS *
NUM_BUFFERS)
#define_CM_ARGB8888       1
#define _CM_RGB888              2
#define _CM_RGB565              3
#define _CM_ARGB1555          4
#define _CM_ARGB4444          5
#define _CM_L8                      6
#define _CM_AL44                  7
#define _CM_AL88                  8
#define COLOR_MODE_0          _CM_RGB565
#define XSIZE_0                XSIZE_PHYS
#define YSIZE_0                YSIZE_PHYS
#define COLOR_MODE_1          _CM_RGB565
#define XSIZE_1                XSIZE_PHYS
#define YSIZE_1                YSIZE_PHYS
#if  (COLOR_MODE_0 == _CM_ARGB8888)
#defineCOLOR_CONVERSION_0 GUICC_M8888I
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_32
#elif (COLOR_MODE_0 == _CM_RGB888)
#defineCOLOR_CONVERSION_0 GUICC_M888
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_24
#elif (COLOR_MODE_0 == _CM_RGB565)
#defineCOLOR_CONVERSION_0 GUICC_M565
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#elif (COLOR_MODE_0 == _CM_ARGB1555)
#defineCOLOR_CONVERSION_0 GUICC_M1555I
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#elif (COLOR_MODE_0 == _CM_ARGB4444)
#defineCOLOR_CONVERSION_0 GUICC_M4444I
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#elif (COLOR_MODE_0 == _CM_L8)
#defineCOLOR_CONVERSION_0 GUICC_8666
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_8
#elif (COLOR_MODE_0 == _CM_AL44)
#defineCOLOR_CONVERSION_0 GUICC_1616I
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_8
#elif (COLOR_MODE_0 == _CM_AL88)
#defineCOLOR_CONVERSION_0 GUICC_88666I
#defineDISPLAY_DRIVER_0   GUIDRV_LIN_16
#else
#errorIllegal color mode 0!
#endif
#if (GUI_NUM_LAYERS &gt; 1)
#if  (COLOR_MODE_1 == _CM_ARGB8888)
#defineCOLOR_CONVERSION_1 GUICC_M8888I
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_32
#elif (COLOR_MODE_1 == _CM_RGB888)
#defineCOLOR_CONVERSION_1 GUICC_M888
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_24
#elif (COLOR_MODE_1 == _CM_RGB565)
#defineCOLOR_CONVERSION_1 GUICC_M565
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#elif (COLOR_MODE_1 == _CM_ARGB1555)
#defineCOLOR_CONVERSION_1 GUICC_M1555I
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#elif (COLOR_MODE_1 == _CM_ARGB4444)
#defineCOLOR_CONVERSION_1 GUICC_M4444I
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#elif (COLOR_MODE_1 == _CM_L8)
#defineCOLOR_CONVERSION_1 GUICC_8666
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_8
#elif (COLOR_MODE_1 == _CM_AL44)
#defineCOLOR_CONVERSION_1 GUICC_1616I
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_8
#elif (COLOR_MODE_1 == _CM_AL88)
#defineCOLOR_CONVERSION_1 GUICC_88666I
#defineDISPLAY_DRIVER_1   GUIDRV_LIN_16
#else
#errorIllegal color mode 1!
#endif
#else
#undef XSIZE_0
#undef YSIZE_0
#define XSIZE_0        XSIZE_PHYS
#define YSIZE_0        YSIZE_PHYS
#endif
#ifndef   XSIZE_PHYS
#errorPhysical X size of display is not defined!
#endif
#ifndef  YSIZE_PHYS
#errorPhysical Y size of display is not defined!
#endif
#ifndef  NUM_VSCREENS
#defineNUM_VSCREENS 1
#else
#if(NUM_VSCREENS &lt;= 0)
    #errorAt least one screeen needs to be defined!
#endif
#endif
#if (NUM_VSCREENS &gt; 1) && (NUM_BUFFERS&gt; 1)
#errorVirtual screens and multiple buffers are not allowed!
#endif
对于这12个配置选项,注释说明已经比较详细。默认情况下,本教程配套的emWin例子都是用的三缓冲,RGB565格式,且仅使用单图层。

## 程序设计:

### 栈大小分配:

系统栈大小在startup\_stm32f429\_439xx.s文件中配置:  


栈大小的单位是字节,那么这里配置系统栈大小为8192字节。

### 主函数初始化:
1
2
3
4
5
6
7
int main (void)
{   

     bsp_Init();

     MainTask();
}
### 硬件外设初始化

硬件外设的初始化是在bsp.c文件实现:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void bsp_Init(void)
{

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);

     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

     SystemCoreClockUpdate();
     bsp_InitUart();
     bsp_InitKey();

     bsp_InitExtIO();
     bsp_InitLed();

     bsp_InitI2C();
     bsp_InitSPIBus();

     bsp_InitSFlash();

     bsp_InitExtSDRAM();
     bsp_DetectLcdType();

     TOUCH_InitHard();
     LCD_ConfigLTDC();

     result =f_mount(&fs, "0:/", 0);
}
emWin功能的具体实现(在MainTask.c文件里面):
1
2
3
4
5
6
7

#include"MainTask.h"
#include"bsp.h"
static GUI_CONST_STORAGE unsigned long _acpic1[] ={
0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000,
       0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000,
       0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,0xFF000000, 0xFF000000,

};
GUI_CONST_STORAGE GUI_BITMAP bmpic1 = {
64, // xSize
64, // ySize
256, // BytesPerLine
32, // BitsPerPixel
(unsignedchar *)_acpic1, // Pointer to picture data
NULL, // Pointer to palette
GUI_DRAW_BMP8888
}

defineID_FRAMEWIN_0 (GUI_ID_USER + 0x00)

defineID_BUTTON_0 (GUI_ID_USER + 0x01)

defineID_BUTTON_1 (GUI_ID_USER + 0x02)

static constGUI_WIDGET_CREATE_INFO _aDialogCreate[] =
{
{ FRAMEWIN_CreateIndirect,“Framewin”, ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0 },
{ BUTTON_CreateIndirect, “”, ID_BUTTON_0, 30, 30, 80, 80, 0, 0x0, 0},
{ BUTTON_CreateIndirect, “”, ID_BUTTON_1, 30, 150, 120, 40, 0, 0x0,0 },
};
static void_cbButton(WM_MESSAGE * pMsg)
{
WM_HWIN hWin;
hWin = pMsg->hWin;
switch (pMsg->MsgId)
{
case WM_PAINT:
if (BUTTON_IsPressed(hWin))
{
GUI_SetBkColor(GUI_WHITE);
GUI_Clear();
GUI_SetAlpha(0xb0);
GUI_DrawBitmap(&bmpic1,8, 8);
GUI_SetAlpha(0);
}
else
{
GUI_DrawBitmap(&bmpic1,8, 8);
}
break;

             default:
                      BUTTON_Callback(pMsg);
     }

}
static void_cbButton1(WM_MESSAGE * pMsg)
{
WM_HWIN hWin;
GUI_RECT Rect;
hWin = pMsg->hWin;
switch (pMsg->MsgId)
{
case WM_PAINT:
WM_GetClientRect(&Rect);
if (BUTTON_IsPressed(hWin))
{
GUI_SetColor(GUI_DARKGRAY);
GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
GUI_SetBkColor(GUI_DARKGRAY);
GUI_SetColor(GUI_WHITE);
}
else
{
GUI_SetColor(GUI_LIGHTBLUE);
GUI_FillRoundedRect(Rect.x0,Rect.y0, Rect.x1, Rect.y1, 5);
GUI_SetBkColor(GUI_LIGHTBLUE);
GUI_SetColor(GUI_WHITE);
}

                      GUI_SetFont(&GUI_Font16_ASCII);
                      GUI_DispStringInRect("LED1",&Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
                      break;

             default:
                      BUTTON_Callback(pMsg);
     }

}
static void_cbDialog(WM_MESSAGE * pMsg)
{
WM_HWIN hItem;
int NCode;
int Id;
switch (pMsg->MsgId)
{
case WM_INIT_DIALOG:
//
//初始化框架窗口
//
hItem = pMsg->hWin;
FRAMEWIN_SetFont(hItem,GUI_FONT_32B_ASCII);
FRAMEWIN_SetTextAlign(hItem,GUI_TA_HCENTER | GUI_TA_VCENTER);
FRAMEWIN_SetText(hItem,“armfly”);

                      //
                      //初始化按钮控件
                      //
                      hItem =WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
                      WM_SetHasTrans(hItem);
                      WM_SetCallback(hItem, _cbButton);
                      //
                      //初始化按钮控件
                      //
                      hItem =WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
                      WM_SetHasTrans(hItem);
                      WM_SetCallback(hItem, _cbButton1);
                      break;
             case WM_NOTIFY_PARENT:
                      Id        = WM_GetId(pMsg->hWinSrc);
                      NCode = pMsg->Data.v;
                      switch(Id)
                      {
                               case ID_BUTTON_0:
                                       switch(NCode)
                                       {
                                                    caseWM_NOTIFICATION_CLICKED:
                                                             break;
                                                    caseWM_NOTIFICATION_RELEASED:
                                                             break;
                                       }
                                       break;
                      }
                      break;
             default:
             WM_DefaultProc(pMsg);
             break;
     }

}
WM_HWINCreateFramewin(void)
{
WM_HWIN hWin;
hWin = GUI_CreateDialogBox(_aDialogCreate,GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
return hWin;
}
voidMainTask(void)
{

     GUI_Init();

     WM_MULTIBUF_Enable(1);

    //TOUCH_Calibration();

     CreateFramewin();

     while(1)
     {
             GUI_Delay(10);
     }

}

# 总结

本章节主要为大家讲解了按钮控件自定义回调函数的实现方法,对于这种方法,望初学者一定要掌握,后面章节学习其它控件做自定义回调函数,方法是相同的。