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"); }
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; }
自定義窗口消息的總結:
(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; }