=================================================================================================
MFC將消息分為以下三種類型:
(1)標準消息:除WM_COMMAND之外,所有以WM_開頭的消息,從CWnd派生的類,都可以接收到這類消息。
(2)命令消息:來自菜單、加速鍵或工具欄按鈕的消息。這類消息都以WM_COMMAND呈現。在MFC中,通過菜單項的標識(ID)來區分不同的命令消息;在SDK中,通過消息的wParam參數識別。從CCmdTarget派生的類,都可以接收到這類消息。
(3)通告消息:由控件產生的消息,例如,按鈕的單擊,列表框的選擇等均產生此類消息,為的是向其父窗口(通常是對話框)通知事件的發生。這類消息也是以WM_COMMAND形式呈現。從CCmdTarget派生的類,都可以接收到這類消息。
某個窗口產生一個消息,該消息中的第一個參數就是與這個窗口有關的句柄,由于VC++系統在后臺維護了一個句柄和指針的映射關系,因此就可以從這個句柄找到對應的指針,然后將指針傳遞給基類,消息循環的最終結果都會歸結為調用基類(窗口類的基類也就是CWnd類)中的WindowProc函數,下面詳細的分析了MFC對消息的處理過程:
MFC對于各類消息都是先交由一個“Afx(即應用程序框架函數)”LRESULT CALLBACK AfxWndProc<for all CWnd's and derived classes>來處理;
然后再調用LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0)<Official way to send message to a CWnd>;
然后再調用LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)<main WindowProc implementation>;
然后再調用BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);在OnWndMsg函數中會針對不同的消息類型進行不同的處理,對于命令消息它會交由BOOL OnCommand(WPARAM wParam, LPARAM lParam)來處理;對于通告消息,會交由BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)來處理;需要說明的一點是不論是命令消息還是通告消息,最終都會調用OnCmdMsg函數。如果消息不是命令消息或通告消息,即為標準消息,則會最終到一個switch結構中去尋找,如果在OnWndMsg中未能響應消息,則交由默認的消息處理函數LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)<Default CWnd implementation>。
在OnWndMsg函數中的case結構中有很多類似于這樣的語句:lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);根據多態性,這里面的this指針往往都是指向基類的,例如CMainFrame或CXXXView類等的對象,這里面的mmf.pfn_is是一個指向函數的指針,因此執行這句話調用消息處理的入口就會遵循先到子類中查找是否存在這樣的消息處理函數,如果子類沒有,才會上溯到基類中去尋找。
=================================================================================================
自定義消息:#define UM_XXXX WM_USER+X;聲明消息響應函數原型afx_msg void OnXXXX();添加消息映射ON_MESSAGE(UM_XXXX,OnXXXX);編寫消息響應函數代碼;使用SendMessage或者PostMessage函數發送消息。
GetMessage會等待消息處理完畢后再取出下一條消息;PeekMessage只會窺視一下即將取出的下一條消息,而不會做任何與消息處理有關的工作。
CWnd::SendMessage會發送消息,并等待消息返回,在程序執行過程中使用該函數,就相當于把消息響應函數的函數體插放到當前程序體中;CWnd::PostMessage會發送消息,但是不會等待消息處理完成后才返回,這個函數會立刻返回,它只是在消息隊列的頭部放置了一個新的消息,至于這個消息多會兒被響應就是系統底層消息循環的事情了。
=================================================================================================
這里要提到的這個觀點太過于經典了,因此一定要好好領會,永遠不能忘記。
MFC的消息相應是通過將產生的消息放置到一個消息隊列中,然后由系統不停的從隊列的頭部取出消息進行響應和執行,由于消息響應在一個時刻只能響應一個消息,而不能同時響應若干個消息,因此只有等待當前的消息處理完成后才能夠進行下一個消息的響應,因此如果我們希望在響應完一個消息之后(也就是在程序中表現為執行完一個消息響應函數的函數體之后)再去做另外一件工作,那就可以在當前的消息響應函數中發送一個消息,在這個發送出去的消息的響應函數中去做那些工作就可以了。而這個發送的消息可以是我們自定義的消息。
=================================================================================================