在MFC軟件開發中,界面操作或者線程之間通信都會經常用到消息,通過對消息的處理實現相應的操作。
比較典型的過程是,用戶操作窗口,然后有消息產生,送給窗口的消息處理函數處理,對用戶的操作做出響應。
一、什么是消息?
窗口消息一般由三個部分組成:1、一個無符號整數,是消息值;2、消息附帶的WPARAM類型的參數;3、消
息附帶的LPARAM類型的參數。其實,我們一般所說的消息是俠義上的消息值,也就是一個無符號整數,經常被定義為宏。
二、什么是消息映射機制?
MFC使用一種消息映射機制來處理消息,在應用程序框架中的表現就是一個消息與消息處理函數一一對應的消息映射
表,以及消息處理函數的聲明和實現等代碼。當窗口接收到消息時,會到消息映射表中查找該消息對應的消息處理函數,
然后由消息處理函數進行相應的處理。
三、Windows消息分類
Windows消息分為系統消息和用戶自定義消息。Windows系統消息有三種:
1、標准Windows消息。除WM_COMMAND以外WM_開頭的消息是標准消息。例如,WM_CREATE、WM_CLOSE。
2、命令消息。消息名為WM_COMMAND,消息中附帶了標識符ID來區分是來自哪個菜單、工具欄按鈕或加速鍵的消息。
3、通知消息。通知消息一般由列表框等子窗口發送給父窗口,消息名稱也是WM_COMMAND,其中附帶了控件通知碼
來區分控件。
CWnd的派生類都可以接收到標准Windows消息、通知消息和命令消息。命令消息還可以由文檔類等接收。
用戶自定義消息實際上就是用戶定義一個宏作為消息,此宏的值應該大於等於WM_USER,然后此宏就可以跟系統消息
一樣使用,窗口類中可以定義它的處理函數。
四、消息映射表
除了一些沒有基類的類或CObject的直接派生類外,其他的類都可以自動生成消息映射表。下面的講解都以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_MESSAGE_MAG和END_MESSAGE_MAP之間的內容成為消息映射入口項。消息映射除了在CMainFrame的實線文件中
添加消息映射表外,在類的定義文件MainFrame.h中還會添加一個宏調用:
DECLARE_MESSAGE_MAP()
一般這個宏調用寫在類定義的結尾處。
五、添加消息處理函數
不管是自動添加還是手動添加都有三個步驟:
1、在類定義中加入消息處理函數的函數聲明,注意要以afx_msg打頭。例如MainFrame.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_WINDWOS_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 struct 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中實現此函數。
本節對MFC消息映射機制只是做了比較簡單的講解,讓大家對它有一定的認識,編程入門這不必強求完全掌握。在以后的教程中會經常涉及
到消息的使用,大家會逐漸熟悉MFC的消息映射機制。