這一講是關於MFC消息映射機制的內容。 編程
前面已經說過,Windows應用程序是消息驅動的。在MFC軟件開發中,界面操做或者線程之間通訊都會常常用到消息,經過對消息的處理實現相應的操做。比較典型的過程是,用戶操做窗口,而後有消息產生,送給窗口的消息處理函數處理,對用戶的操做作出響應。 框架
什麼是消息 函數
窗口消息通常由三個部分組成:1.一個無符號整數,是消息值;(2)消息附帶的WPARAM類型的參數;(3)消息附帶的LPARAM類型的參數。其實咱們通常所說的消息是狹義上的消息值,也就是一個無符號整數,常常被定義爲宏。 工具
什麼是消息映射機制 線程
MFC使用一種消息映射機制來處理消息,在應用程序框架中的表現就是一個消息與消息處理函數一一對應的消息映射表,以及消息處理函數的聲明和實現等代碼。當窗口接收到消息時,會到消息映射表中查找該消息對應的消息處理函數,而後由消息處理函數進行相應的處理。SDK編程時須要在窗口過程當中一一判斷消息值進行相應的處理,相比之下MFC的消息映射機制要方便好用的多。 code
Windows消息分類 開發
先講下Windows消息的分類。Windows消息分爲系統消息和用戶自定義消息。Windows系統消息有三種: 文檔
1.標準Windows消息。除WM_COMMAND外以WM_開頭的消息是標準消息。例如,WM_CREATE、WM_CLOSE。 原型
2.命令消息。消息名爲WM_COMMAND,消息中附帶了標識符ID來區分是來自哪一個菜單、工具欄按鈕或加速鍵的消息。 io
3.通知消息。通知消息通常由列表框等子窗口發送給父窗口,消息名也是WM_COMMAND,其中附帶了控件通知碼來區分控件。
CWnd的派生類均可以接收到標準Windows消息、通知消息和命令消息。命令消息還能夠由文檔類等接收。
用戶自定義消息是實際上就是用戶定義一個宏做爲消息,此宏的值應該大於等於WM_USER,而後此宏就能夠跟系統消息同樣使用,窗口類中能夠定義它的處理函數。
消息映射表
除了一些沒有基類的類或CObject的直接派生類外,其餘的類均可以自動生成消息映射表。下面的講解都之前面例程HelloWorld的CMainFrame爲例。消息映射表以下:
C++代碼
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
ON_WM_CREATE()
ON_COMMAND(ID_VIEW_CUSTOMIZE, &CMainFrame::OnViewCustomize)
ON_REGISTERED_MESSAGE(AFX_WM_CREATETOOLBAR, &CMainFrame::OnToolbarCreateNew)
ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
ON_WM_SETTINGCHANGE()
END_MESSAGE_MAP()
在BEGIN_MESSAG_MAP和END_MESSAGE_MAP之間的內容成爲消息映射入口項。消息映射除了在CMainFrame的實現文件中添加消息映射表外,在類的定義文件MainFrm.h中還會添加一個宏調用:
DECLARE_MESSAGE_MAP()
通常這個宏調用寫在類定義的結尾處。
添加消息處理函數
如何添加消息處理函數呢?無論是自動仍是手動添加都有三個步驟:
1.在類定義中加入消息處理函數的函數聲明,注意要以afx_msg打頭。例如MainFrm.h中WM_CREATE的消息處理函數的函數聲明:afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);。
2.在類的消息映射表中添加該消息的消息映射入口項。例如WM_CREATE的消息映射入口項:ON_WM_CREATE()。
3.在類實現中添加消息處理函數的函數實現。例如,MainFrm.cpp中WM_CREATE的消息處理函數的實現:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
}
經過以上三個步驟之後,WM_CREATE等消息就能夠在窗口類中被消息處理函數處理了。
各類Windows消息的消息處理函數
標準Windows消息的消息處理函數都與WM_CREATE消息相似。
命令消息的消息映射入口項形式如:ON_COMMAND(ID_VIEW_CUSTOMIZE, &CMainFrame::OnViewCustomize),消息爲ID_VIEW_CUSTOMIZE,消息處理函數爲OnViewCustomize。
若是想要使用某個處理函數批量處理某些命令消息,則能夠像CMainFrame消息映射表中的ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)同樣添加消息映射入口項,這樣值在ID_VIEW_APPLOOK_WIN_2000到ID_VIEW_APPLOOK_WINDOWS_7之間的菜單項等的命令消息都由CMainFrame的OnApplicationLook函數處理。函數原型爲afx_msg void OnApplicationLook(UINT id);,參數id爲用戶操做的菜單項等的ID。
在操做列表框等控件時每每會給父窗口發送WM_NOTIFY通知消息。WM_NOTIFY消息的wParam參數爲發送通知消息的控件的ID,lParam參數指向一個結構體,多是NMHDR結構體,也多是第一個元素爲NMHDR結構體變量的其餘結構體。NMHDR結構體的定義以下(僅做了解):
Typedef sturct tagNMHDR{
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
hwndFrom爲發送通知消息控件的句柄,idFrom爲控件ID,code爲要處理的通知消息的通知碼,例如NM_CLICK。
通知消息的消息映射入口項形式如:
ON_NOTIFY(wNotifyCode,id,memberFxn)
wNotifyCode爲要處理的通知消息通知碼,例如:NM_CLICK。id爲控件標識ID。MemberFxn爲此消息的處理函數。
通知消息的處理函數的原型爲:
afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result);
若是須要使用用戶自定義消息,首先要定義消息宏,如:#define WM_UPDATE_WND (WM_USER+1),再到消息映射表中添加消息映射入口項:ON_MESSAGE(WM_UPDATE_WND, &CMainFrame::OnUpdateWnd),而後在MainFrm.h中添加消息處理函數的函數聲明:afx_msg LRESULT OnUpdateWnd(WPARAM wParam, LPARAM lParam);,最後在MainFrm.cpp中實現此函數