【第3版emWin教程】第42章 emWin6.x窗口管理器之回调消息类型

教程不断更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

第42章       emWin6.x窗口管理器之回调消息类型

本章节为大家讲解emWin窗口管理器的消息类型。如果说窗口管理器是emWin的核心,那么消息机制就是窗口管理的核心,这部分知识非常的重要,后面章节后面章节学习控件,对话框都是以消息为基础的,初学者务必要掌握。

学习本章节前一定要优先学习第41章的窗口管理器基础知识。

42.1  初学者重要提示

42.2 消息机制简介

42.3 消息结构

42.4 消息类型

42.5 系统类型消息实例

42.6 指针输入设备(PID)类型消息实例

42.7 通知代码类型消息实例

42.8 总结

 

42.1 初学者重要提示

1、  尽管本章节非常重要,但是初学者也不必担心,通过本章节对窗口管理器的消息类型有个初步的认识,随着后面章节的学习,慢慢就会融会贯通,因为后面每个章节基本都要用到消息机制了。

2、  窗口管理器中消息类型相关知识在emWin手册中都有讲解,下图是中文版讲解位置

 

 

下图是英文版手册讲解位置:

 

 

42.2 消息机制简介

消息机制是emWin的核心,简单的理解就是这样:比如操作一个触控界面,上面有按钮,滚动条,编辑框等控件,当用户去触摸某个控件时都会触发窗口管理器去处理这些消息,并跳转到窗口回调函数的相应消息里面,这些消息里面就是需要添加的功能。比如我们想点击按钮后实现LED翻转,我们就可以在按钮所在窗口回调函数的按钮消息中加入LED翻转功能就可以实现这种效果了。具体消息是如何传输的,用户不需要去管,只需在回调函数相应的消息里面加入功能就可以了。从这个角度来看,消息机制还是比较容易掌握的。

对于初学者来说,明白了这点就可以了,通过后面实际的例子来进一步加强认识。另外,要实现消息机制就得有消息结构变量用来指示消息类型和一些其它相关的功能,下面讲解这部分知识。

42.3 消息结构

回调函数被调用时,它会收到以其pMsg参数指定的消息。此消息实际上是一个WM_MESSAGE数据结构,其元素定义如下。

 

42.4 消息类型

emWin支持的消息类型主要分为以下三类(emWin5.x支持的类型)

系统定义的消息类型:

 

指针输入设备(PID)消息类型:

 

通知代码类型:

 

用户定义消息类型:

 

42.5 系统类型消息实例

下面我们通过一个具体的实例来讲解系统消息类型,这里我们通过前面章节讲的GUIBuilder创建一个如下的对话框,并对其做了简单的修改,方便作为实例进行说明(关于对话框的内容会在后面的教程跟大家详细讲解,这里重点看系统类消息)。

显示效果如下(分辨率为480*272):

 

 

创建立以后生成的代码如下(重点看系统消息部分,可以直接将代码复制到模拟器或者开发板上面运行)

#include "DIALOG.h"


/*
*********************************************************************************************************
*                                         宏定义
*********************************************************************************************************
*/
#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
#define ID_BUTTON_0 (GUI_ID_USER + 0x01)
#define ID_SCROLLBAR_0 (GUI_ID_USER + 0x02)
#define ID_SLIDER_0 (GUI_ID_USER + 0x03)


/*
*********************************************************************************************************
*                           GUI_WIDGET_CREATE_INFO类型数组
*********************************************************************************************************
*/
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 480, 272, 0, 0x64, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 130, 28, 147, 35, 0, 0x0, 0 },
  { SCROLLBAR_CreateIndirect, "Scrollbar", ID_SCROLLBAR_0, 129, 74, 147, 28, 0, 0x0, 0 },
  { SLIDER_CreateIndirect, "Slider", ID_SLIDER_0, 133, 118, 137, 25, 0, 0x0, 0 },
};

/*
*********************************************************************************************************
*    函 数 名: _cbDialog
*    功能说明: 对话框回调函数        
*    形    参: pMsg  回调参数 
*    返 回 值: 无
*********************************************************************************************************
*/
static void _cbDialog(WM_MESSAGE * pMsg) 
{
    WM_HWIN hItem;
    int     NCode;
    int     Id;


    switch (pMsg->MsgId)    //--------------(1)
    {
        case WM_INIT_DIALOG:  //--------------(2)
            
            //
            // 初始化 'Framewin'
            //
            hItem = pMsg->hWin;
            FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
            FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
            FRAMEWIN_SetText(hItem, "armfly");
        
            //
            // 初始化 'Button'
            //
            hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
            BUTTON_SetFont(hItem, GUI_FONT_24B_ASCII);
            BUTTON_SetText(hItem, "armfly");
            break;

        case WM_PAINT:  //--------------(3)
             GUI_SetBkColor(GUI_BLUE);
            GUI_Clear();
             break;

        case WM_KEY:    //--------------(4)
            switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) 
            {
                case GUI_KEY_ESCAPE:
                    GUI_EndDialog(pMsg->hWin, 1);
                    break;

                case GUI_KEY_ENTER:
                    GUI_EndDialog(pMsg->hWin, 0);
                    break;
            }
            break;

        case WM_NOTIFY_PARENT:  //--------------(5)
            Id    = WM_GetId(pMsg->hWinSrc);
            NCode = pMsg->Data.v;
            switch(Id) 
            {
                case ID_BUTTON_0:
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:  
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:  
                            break;
                    }
                    break;
                
                case ID_SCROLLBAR_0: 
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                        
                        case WM_NOTIFICATION_VALUE_CHANGED:
                            break;
                    }
                    break;
                
                case ID_SLIDER_0:
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                        
                        case WM_NOTIFICATION_VALUE_CHANGED:
                            break;
                    }
                    break;
            }
            break;
            
        default:
            WM_DefaultProc(pMsg);
            break;
    }
}

/*
*********************************************************************************************************
*    函 数 名: CreateFramewin
*    功能说明: 创建对话框        
*    形    参: 无
*    返 回 值: 返回对话框句柄
*********************************************************************************************************
*/
WM_HWIN CreateFramewin(void) 
{
    WM_HWIN hWin;

    hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);

    return hWin;
}

/*
*********************************************************************************************************
*    函 数 名: MainTask
*    功能说明: GUI主函数
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/
void MainTask(void) 
{
    /* 初始emWin */
    GUI_Init();

    /* 创建对话框 */
    CreateFramewin();

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

重点看对话框回调函数_cbDialog中的内容:

1、通过switch (pMsg->MsgId) 区分各种系统消息类型。

2、WM_INIT_DIALOG消息:

对话框初始化消息,这里主要是初始化框架窗口的的标题和按钮控件。一般对话框上面的控件初始化,Window(窗口)或者FrameWin(框架窗口)的初始化都是在这个消息里面完成,同时用户也可以在这个消息里面创建新的窗口,控件等。

3、WM_PAINT消息:

重绘消息,这里实现背景色的重绘,背景色被设置为蓝色。文本显示API函数,数值显示API函数以及2D图形相关的API函数都可以在这个消息里面调用。

4、WM_KEY消息:

按键消息,当前聚焦的窗口才可以收到这个消息。这个消息主要通过外部实体按键来发送,本教程后面章专门讲解这方面的应用。另外,上面代码中Data.p指针指向WM_KEY_INFO结构的消息,WM_KEY_INFO的定义如下:

 

5、WM_NOTIFY_PARENT:

   告知父窗口,其子窗口中发生了某些改变。这些消息通常由控件发送到父窗口,让父窗口可以对事件作出反应。消息的Data.v值包含消息的通知代码。上面对话框上创建的按钮,滚动条,滑动条就是通过这个消息进行操作的。

通过这个实例先有一个感性的认识,随着后面章节的学习逐渐加强认识。

42.6 指针输入设备(PID)类型消息实例

基于上面42.5小节的例子,实现PID类型消息WM_MOUSEOVER,代码如下(可以直接将代码复制到模拟器或者开发板上面运行):

#include "DIALOG.h"



/*
*********************************************************************************************************
*                                         变量
*********************************************************************************************************
*/
static GUI_COLOR _acColor[3] = {GUI_BLUE,GUI_RED,GUI_YELLOW};   //--------------(1)
static unsigned char ucBackColor; 

/*
*********************************************************************************************************
*                                         宏定义
*********************************************************************************************************
*/
#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
#define ID_BUTTON_0 (GUI_ID_USER + 0x01)
#define ID_SCROLLBAR_0 (GUI_ID_USER + 0x02)
#define ID_SLIDER_0 (GUI_ID_USER + 0x03)


/*
*********************************************************************************************************
*                           GUI_WIDGET_CREATE_INFO类型数组
*********************************************************************************************************
*/
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 480, 272, 0, 0x64, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 130, 28, 147, 35, 0, 0x0, 0 },
  { SCROLLBAR_CreateIndirect, "Scrollbar", ID_SCROLLBAR_0, 129, 74, 147, 28, 0, 0x0, 0 },
  { SLIDER_CreateIndirect, "Slider", ID_SLIDER_0, 133, 118, 137, 25, 0, 0x0, 0 },
};

/*
*********************************************************************************************************
*    函 数 名: _cbDialog
*    功能说明: 对话框回调函数        
*    形    参: pMsg  回调参数 
*    返 回 值: 无
*********************************************************************************************************
*/
static void _cbDialog(WM_MESSAGE * pMsg) 
{
    WM_HWIN hItem;
    int     NCode;
    int     Id;


    switch (pMsg->MsgId) 
    {
        case WM_INIT_DIALOG:
            
            //
            // 初始化 'Framewin'
            //
            hItem = pMsg->hWin;
            FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
            FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
            FRAMEWIN_SetText(hItem, "armfly");
        
            //
            // 初始化 'Button'
            //
            hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
            BUTTON_SetFont(hItem, GUI_FONT_24B_ASCII);
            BUTTON_SetText(hItem, "armfly");

            /* 默认背景色取GUI_BLUE,即蓝色 */
            ucBackColor = 0;  
            break;

        case WM_PAINT:
              GUI_SetBkColor(_acColor[ucBackColor]); //--------------(2)
            GUI_Clear();
              break;

        case WM_MOUSEOVER:       //--------------(3)
            ucBackColor++;
            if (ucBackColor == 3)
            {
                ucBackColor = 0;
            }
              WM_InvalidateWindow(pMsg->hWin);
            break;

        case WM_KEY:  
            switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) 
            {
                case GUI_KEY_ESCAPE:
                    GUI_EndDialog(pMsg->hWin, 1);
                    break;

                case GUI_KEY_ENTER:
                    GUI_EndDialog(pMsg->hWin, 0);
                    break;
            }
            break;

        case WM_NOTIFY_PARENT:
            Id    = WM_GetId(pMsg->hWinSrc);
            NCode = pMsg->Data.v;
            switch(Id) 
            {
                case ID_BUTTON_0:
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                    }
                    break;
                
                case ID_SCROLLBAR_0: 
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                        
                        case WM_NOTIFICATION_VALUE_CHANGED:
                            break;
                    }
                    break;
                
                case ID_SLIDER_0:
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                        
                        case WM_NOTIFICATION_VALUE_CHANGED:
                            break;
                    }
                    break;
            }
            break;
            
        default:
            WM_DefaultProc(pMsg);
            break;
    }
}

/*
*********************************************************************************************************
*    函 数 名: CreateFramewin
*    功能说明: 创建对话框        
*    形    参: 无
*    返 回 值: 返回对话框句柄
*********************************************************************************************************
*/
WM_HWIN CreateFramewin(void) 
{
    WM_HWIN hWin;

    hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);

    return hWin;
}

/*
*********************************************************************************************************
*    函 数 名: MainTask
*    功能说明: GUI主函数
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/
void MainTask(void) 
{
    /* 初始emWin */
    GUI_Init();

    /* 显示光标 */
    GUI_CURSOR_Show();

    /* 创建对话框 */
    CreateFramewin();

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

重点看对话框回调函数_cbDialog中指针输入设备类型消息WM_MOUSEOVER的实现:

  1. 定义一个数组,里面有三种颜色,定义一个变量,用于三种颜色的切换。
  2. 在WM_PAINT消息中实现重绘,主要用于实现对话框客户区的颜色重绘。背景颜色的初始值_acColor[ucBackColor],变量ucBackColor已经在WM_INIT_DIALOG消息里面进行了初始化,首次显示是蓝色。
  3. 这里加入了消息WM_MOUSEOVER,如果鼠标功能已经使能,当鼠标箭头接触到窗口时将触发窗口回调函数里面的这个消息。在这个消息里面切换对话框的背景色变量,然后调用函数WM_InvalidateWindow将对话框进行无效化,从而会触发窗口管理器去执行WM_PAINT消息,这样就实现了对话框背景色的变化。

实例的显示效果如下(分辨率480*272):

 

 

PID类型的其它消息,后面章节用到的时候再给大家讲解。

42.7 通知代码类型消息实例

基于上面42.5小节的例子,实现通知代码类型消息,通过操作按钮来实现对话框背景色的改变。代码如下(可以直接将代码复制到模拟器或者开发板上面运行):

#include "DIALOG.h"



/*
*********************************************************************************************************
*                                         变量
*********************************************************************************************************
*/
static GUI_COLOR _acColor[3] = {GUI_BLUE,GUI_RED,GUI_YELLOW};    //--------------(1)
static unsigned char ucBackColor; 

/*
*********************************************************************************************************
*                                         宏定义
*********************************************************************************************************
*/
#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
#define ID_BUTTON_0 (GUI_ID_USER + 0x01)
#define ID_SCROLLBAR_0 (GUI_ID_USER + 0x02)
#define ID_SLIDER_0 (GUI_ID_USER + 0x03)


/*
*********************************************************************************************************
*                           GUI_WIDGET_CREATE_INFO类型数组
*********************************************************************************************************
*/
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 480, 272, 0, 0x64, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 130, 28, 147, 35, 0, 0x0, 0 },
  { SCROLLBAR_CreateIndirect, "Scrollbar", ID_SCROLLBAR_0, 129, 74, 147, 28, 0, 0x0, 0 },
  { SLIDER_CreateIndirect, "Slider", ID_SLIDER_0, 133, 118, 137, 25, 0, 0x0, 0 },
};

/*
*********************************************************************************************************
*    函 数 名: _cbDialog
*    功能说明: 对话框回调函数        
*    形    参: pMsg  回调参数 
*    返 回 值: 无
*********************************************************************************************************
*/
static void _cbDialog(WM_MESSAGE * pMsg) 
{
    WM_HWIN hItem;
    int     NCode;
    int     Id;


    switch (pMsg->MsgId) 
    {
        case WM_INIT_DIALOG:
            
            //
            // 初始化 'Framewin'
            //
            hItem = pMsg->hWin;
            FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
            FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
            FRAMEWIN_SetText(hItem, "armfly");
        
            //
            // 初始化 'Button'
            //
            hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
            BUTTON_SetFont(hItem, GUI_FONT_24B_ASCII);
            BUTTON_SetText(hItem, "armfly");

            /* 默认背景色取GUI_BLUE,即蓝色 */
            ucBackColor = 0;
            break;

        case WM_PAINT:    //--------------(2)
             GUI_SetBkColor(_acColor[ucBackColor]);
            GUI_Clear();
             break;

        case WM_KEY:  
            switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) 
            {
                case GUI_KEY_ESCAPE:
                    GUI_EndDialog(pMsg->hWin, 1);
                    break;

                case GUI_KEY_ENTER:
                    GUI_EndDialog(pMsg->hWin, 0);
                    break;
            }
            break;

        case WM_NOTIFY_PARENT:
            Id    = WM_GetId(pMsg->hWinSrc);
            NCode = pMsg->Data.v;
            switch(Id) 
            {
                case ID_BUTTON_0:
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:     //--------------(3)
                            ucBackColor++;
                            if (ucBackColor == 3)
                            {
                                ucBackColor = 0;
                            }
                            WM_InvalidateWindow(pMsg->hWin);
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                    }
                    break;
                
                case ID_SCROLLBAR_0: 
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                        
                        case WM_NOTIFICATION_VALUE_CHANGED:
                            break;
                    }
                    break;
                
                case ID_SLIDER_0:
                    switch(NCode) 
                    {
                        case WM_NOTIFICATION_CLICKED:
                            break;
                        
                        case WM_NOTIFICATION_RELEASED:
                            break;
                        
                        case WM_NOTIFICATION_VALUE_CHANGED:
                            break;
                    }
                    break;
            }
            break;
            
        default:
            WM_DefaultProc(pMsg);
            break;
    }
}

/*
*********************************************************************************************************
*    函 数 名: CreateFramewin
*    功能说明: 创建对话框        
*    形    参: 无
*    返 回 值: 返回对话框句柄
*********************************************************************************************************
*/
WM_HWIN CreateFramewin(void) 
{
    WM_HWIN hWin;

    hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);

    return hWin;
}

/*
*********************************************************************************************************
*    函 数 名: MainTask
*    功能说明: GUI主函数
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/
void MainTask(void) 
{
    /* 初始emWin */
    GUI_Init();

    /* 创建对话框 */
    CreateFramewin();

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

重点看对话框回调函数_cbDialog中按钮的WM_NOTIFICATION_CLICKED消息实现:

  1. 定义一个数组,里面有三种颜色,定义一个变量,用于三种颜色的切换。
  2. 在WM_PAINT消息中实现重绘,主要用于实现对话框客户区的颜色重绘。背景颜色的初始值_acColor[ucBackColor],变量ucBackColor已经在WM_INIT_DIALOG消息里面进行了初始化,首次显示是蓝色。
  3. 用户点击了按钮后,在这个消息里面切换对话框的背景色变量,然后调用函数WM_InvalidateWindow将对话框进行无效化,从而会触发窗口管理器去执行WM_PAINT消息,这样就实现了对话框背景色的变化。

实例的显示效果如下(分辨率为480*272):

 

 

更多通知类消息会在后面控件类章节中进行讲解。

42.8 总结

本章节就跟大家讲这么多,只给大家举了部分消息类型的通信实例,后面还会通过更多例子来强化大家对这方面知识的理解。

微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
原文地址:https://www.cnblogs.com/armfly/p/15343963.html