1. 程式人生 > 其它 >【第3版emWin教程】第42章 emWin6.x視窗管理器之回撥訊息型別

【第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