消息處理(三)

1、自定義命令ide

爲了使用自定義命令,通常要通過以下幾個步驟:函數

(1)自定義命令IDthis

      命令ID是WORD型的。雖然能夠自由設定其值,可是不能和應用程序中其餘命令ID衝突。spa

      在資源文件中新建一個命令,例如#define ID_LOADTOIE 8888操作系統

(2)添加自定義消息映射項指針

BEGIN_MESSAGE_MAP(CMsgDialog,CDialog)
     ON_COMMAND(ID_LOADTOIE,LoadToIE)
END_MESSAGE_MAP()

(3)發送自定義命令
處理命令消息WM_COMMAND的窗口過程形式以下:code

LRESULT CALLBACK WindowProc(
    HWND hWnd,        //窗口句柄
    WM_COMMAND,       //命令的消息標誌固定爲WM_COMMAND
    WPARAM wParam,   //通知代碼(菜單、組合鍵命令)或標誌(控件通知)       LPRARAM lParam,  //控件句柄
);

      wParam分紅高低位兩部分。若是爲控件命令,則其高位部分爲控件的通知代碼;若是爲加速鍵命令,則其高位部分爲1;若是爲菜單命令,其高位部分爲0。wParam的低位部分表示控件、菜單或加速鍵的ID。
      對於控件命令,lParam表示控件句柄;不然lParam置爲NULL。orm

MAKEWPARAM宏能夠將兩個WORD拼成一個WPARAM參數:對象

WPARAM MAKEWPARAM(
    WORD wLow,       //低位
     WORD wHigh,      //高位
);

發送自定義命令以下:blog

(4)處理自定義命令

命令處理成員的名字是任意的,但其簽名是固定的。

Example:

.h

void LoadToIE();

.cpp

BEGIN_MESSAGE_MAP(CMsgStudyDlg, CDialog)
    //{{AFX_MSG_MAP(CMsgStudyDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_COMMAND_RANGE(IDC_BUTTON1,IDC_BUTTON4,OnButton)
    ON_COMMAND_EX(ID_HELP,OnHelp)
    ON_COMMAND(ID_LOADTOIE,LoadToIE)
END_MESSAGE_MAP()


UINT DownLoadURLThreadFunc(LPVOID obj)
{
    ASSERT(obj);
    CMsgStudyDlg * dlg = (CMsgStudyDlg *)obj;

    dlg->PostMessage(WM_COMMAND,MAKEWPARAM(ID_LOADTOIE,0),NULL);

    return 1;
}
void CMsgStudyDlg::OnButton(UINT nID)
{
    CWinThread * pThread;
    switch(nID)
    {
    case IDC_BUTTON1:
        AfxMessageBox("This is BUTTON1");
        pThread = AfxBeginThread(DownLoadURLThreadFunc,this);
        break;
    case IDC_BUTTON2:
        AfxMessageBox("This is BUTTON2");
        break;
    case IDC_BUTTON3:
        AfxMessageBox("This is BUTTON3");
        break;
    case IDC_BUTTON4:
        AfxMessageBox("This is BUTTON4");
        break;
    default:
        break;
    }
}

BOOL CMsgStudyDlg::OnHelp(UINT nID)
{
    AfxMessageBox("This is CMsgStudyDlg");
    //返回FALSE,容許沿着處理鏈繼續處理
    return FALSE;
}

void CMsgStudyDlg::LoadToIE()
{
    AfxMessageBox("OK");
}
View Code

2、自定義窗口消息
操做系統保留必定範圍的窗口消息標記做爲自定義消息,自定義窗口消息的消息標誌都大於WM_USER。

一旦有了消息標誌,就能夠用目標窗口對象的SendMessage或PostMessage發送(或投遞)消息,以請求目標窗口的窗口過程對該消息進行處理。

目標窗口爲了將自定義窗口消息和消息處理成員關聯起來,要用到ON_MESSAGE消息映射宏:

#define ON_MESSAGE(message,memberFxn)\
{message,0,0,0,AfxSig_lwl,\
  (AFX_PMSG)(AFX_PMSGW)static_cast<LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM,LPARAM)>(memberFxn))},

該宏規定了處理自定義窗口消息的成員必須知足AfxSig_lwl規定的簽名:LRESULT(WPARAM,LPARAM),參數WPARAM和LPARAM包含了跟自定義消息相關的特定數據。

(1)定義消息標記

#define WM_MYMSG (WM_USER + 100)

      若是僅在對話框內部使用自定義窗口消息,只須要在對話框的實現文件(.cpp)中添加自定義窗口消息的定義;若是在應用程序範圍內使用自定義窗口消息,須要把自定義消息的定義放到Resource.h中。

(2)修改消息映射表

在對話框的消息映射表中加入一個ON_MESSAGE映射項:

BEGIN_MESSAGE_MAP(CMsgStudyDlg,CDialog)
   //...
   //使用自定義消息
  ON_MESSAGE(WM_MYMSG,OnMyMessage)
END_MESSAGE_MAP()

(3)添加自定義消息的成員函數

.h     //頭文件中的聲明
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

.cpp   //實現文件中的實現
LRESULT CMsgStudyDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
    return 0L;
}

自定義消息的處理函數首先從消息參數中獲取了消息參數(存放在LPARAM中)。消息處理函數知道消息參數爲什麼種類型,並將消息參數造型設定爲約定的類型。
(4)引起自定義消息

this->SendMessage(WM_MYMSG,0,(LPARAM)(&dt));
或
this->PostMessage(WM_MYMSG,0,(LPARAM)(&dt));

      注意:SendMessage的消息參數指針&dt既能夠引用在堆棧上分配的對象,又能夠引用在C++運行堆上分配的對象;PostMessage的消息參數指針&dt只能引用在C++運行堆上分配的對象。由於SendMessage函數等待消息響應完成後才返回,而PostMessage函數不須要等待消息響應,因此在堆棧上分配的對象,在函數返回後,會當即被自動銷燬,C++運行堆上的對象必須手動銷燬。
Example:

.h

// Implementation
protected:
    HICON m_hIcon;

    // Generated message map functions
    //{{AFX_MSG(CMsgStudyDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnButton(UINT nID);
    afx_msg BOOL OnHelp(UINT nID);
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    void LoadToIE();

.cpp

#define WM_MYMSG (WM_USER + 100)

BEGIN_MESSAGE_MAP(CMsgStudyDlg, CDialog)
    //{{AFX_MSG_MAP(CMsgStudyDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_COMMAND_RANGE(IDC_BUTTON1,IDC_BUTTON4,OnButton)
    ON_COMMAND_EX(ID_HELP,OnHelp)
    ON_COMMAND(ID_LOADTOIE,LoadToIE)
    ON_MESSAGE(WM_MYMSG,OnMyMessage)
END_MESSAGE_MAP()



void CMsgStudyDlg::OnButton(UINT nID)
{
    CWinThread * pThread;
    CTime dt;
    CTime * pTime = NULL;
    switch(nID)
    {
    case IDC_BUTTON1:
        AfxMessageBox("This is BUTTON1");
        pThread = AfxBeginThread(DownLoadURLThreadFunc,this);
        break;
    case IDC_BUTTON2:
        AfxMessageBox("This is BUTTON2");
        dt = dt.GetCurrentTime();
        //設置消息參數
        this->SendMessage(WM_MYMSG,0,(LPARAM)&dt);
        break;
    case IDC_BUTTON3:
        AfxMessageBox("This is BUTTON3");
        dt = dt.GetCurrentTime();
        pTime = new CTime(dt);
        this->PostMessage(WM_MYMSG,1,(LPARAM)pTime);
        break;
    case IDC_BUTTON4:
        AfxMessageBox("This is BUTTON4");
        break;
    default:
        break;
    }
}



LRESULT CMsgStudyDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
    CTime * pTime = (CTime *)lParam;
    CString m_strTime;
    m_strTime.Format("發出消息的時間是:%d時: %d分",pTime->GetHour(),pTime->GetMinute());
    AfxMessageBox(m_strTime);
    if(wParam == 1)
    {
        delete pTime;
    }
    return 0L;
}
View Code

自定義窗口消息的總結:

(1)使用自定義消息請求窗口進行某種特殊的操做。

(2)自定義消息的消息標誌必須大於WM_USER。

(3)能夠利用消息參數攜帶數據,注意消息參數的內存管理,保證既不發生內存泄露,又能使消息參數有效。

3、登記消息

      自定義消息是局部範圍的,同一應用程序中的消息窗口很容易利用自定義消息進行通訊,可是若是要在兩個進程之間通訊,自定義消息就無能爲力了,須要使用登記(或註冊)消息。

(1)爲了使用登記消息,首先要得到一個登記消息標記,該消息標記在整個系統內是惟一的。經過調用系統API RegisterWindowMessage,能夠得到一個登記消息標記:

UINT RegisterWindowMessage(
  LPCTSTR lpString    //消息字符串
);

(2)在消息映射表中手工添加ON_REGISTERED_MESSAGE消息映射宏,添加登記消息的處理函數

#define ON_REGISTERED_MESSAGE(nMessageVariable,memberFxn)\
{0xC000,0,0,0,(UINT_PTR)(UINT *)(&nMessageVariable),\
(AFX_PMSG)(AFX_PWMSG)(static_cast<LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM,LPARAM)>(memberFxn))},

(3)處理登記消息的成員函數

其定義代表處理登記消息的成員函數具備以下簽名:LRESULT(WPARAM wParam,LPARAM lParam)

Example:

.h

    // Generated message map functions
    //{{AFX_MSG(CMsgStudyDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnButton(UINT nID);
    afx_msg BOOL OnHelp(UINT nID);
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
    afx_msg LRESULT OnMyRegisteredMsg(WPARAM wParam,LPARAM lParam);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()


.cpp


//1.
static UINT NEAR WM_MYREGISTEREDMSG = RegisterWindowMessage("WM_MYREGISTEREDMSG");


//2.
BEGIN_MESSAGE_MAP(CMsgStudyDlg, CDialog)
    //{{AFX_MSG_MAP(CMsgStudyDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_COMMAND_RANGE(IDC_BUTTON1,IDC_BUTTON4,OnButton)
    ON_COMMAND_EX(ID_HELP,OnHelp)
    ON_COMMAND(ID_LOADTOIE,LoadToIE)
    ON_MESSAGE(WM_MYMSG,OnMyMessage)
    ON_REGISTERED_MESSAGE(WM_MYREGISTEREDMSG,OnMyRegisteredMsg)
END_MESSAGE_MAP()

//3.
void CMsgStudyDlg::OnButton(UINT nID)
{
    CWinThread * pThread;
    CTime dt;
    CTime * pTime = NULL;
    CWnd * pWnd = NULL;
    TCHAR className[256];
    CString title;
    switch(nID)
    {
    case IDC_BUTTON1:
        AfxMessageBox("This is BUTTON1");
        pThread = AfxBeginThread(DownLoadURLThreadFunc,this);
        break;
    case IDC_BUTTON2:
        AfxMessageBox("This is BUTTON2");
        dt = dt.GetCurrentTime();
        //設置消息參數
        this->SendMessage(WM_MYMSG,0,(LPARAM)&dt);
        break;
    case IDC_BUTTON3:
        AfxMessageBox("This is BUTTON3");
        dt = dt.GetCurrentTime();
        pTime = new CTime(dt);
        this->PostMessage(WM_MYMSG,1,(LPARAM)pTime);
        break;
    case IDC_BUTTON4:
        AfxMessageBox("This is BUTTON4");
        this->GetWindowText(title);
        ::GetClassName(this->m_hWnd,className,255);
        pWnd = this->FindWindow(className,title);
        ASSERT(pWnd);
        pWnd->SendMessage(WM_MYREGISTEREDMSG);
        break;
    default:
        break;
    }
}


//4.
LRESULT CMsgStudyDlg::OnMyRegisteredMsg(WPARAM wParam,LPARAM lParam)
{
    AfxMessageBox("收到自定義的登記消息");
    return 0L;
}
View Code
相關文章
相關標籤/搜索