上一講雞啄米為大家簡單分析了MFC應用程序框架,這一講是關于MFC消息映射機制的內容。

       前面已經說過,Windows應用程序是消息驅動的。在MFC軟件開發中,界面操作或者線程之間通信都會經常用到消息,通過對消息的處理實現相應的操作。比較典型的過程是,用戶操作窗口,然后有消息產生,送給窗口的消息處理函數處理,對用戶的操作做出響應。

       什么是消息

       窗口消息一般由三個部分組成:1.一個無符號整數,是消息值;(2)消息附帶的WPARAM類型的參數;(3)消息附帶的LPARAM類型的參數。其實我們一般所說的消息是狹義上的消息值,也就是一個無符號整數,經常被定義為宏。

       什么是消息映射機制

       MFC使用一種消息映射機制來處理消息,在應用程序框架中的表現就是一個消息與消息處理函數一一對應的消息映射表,以及消息處理函數的聲明和實現等代碼。當窗口接收到消息時,會到消息映射表中查找該消息對應的消息處理函數,然后由消息處理函數進行相應的處理。SDK編程時需要在窗口過程中一一判斷消息值進行相應的處理,相比之下MFC的消息映射機制要方便好用的多。

       Windows消息分類

       先講下Windows消息的分類。Windows消息分為系統消息和用戶自定義消息。Windows系統消息有三種:

       1.標準Windows消息。除WM_COMMAND外以WM_開頭的消息是標準消息。例如,WM_CREATE、WM_CLOSE。

       2.命令消息。消息名為WM_COMMAND,消息中附帶了標識符ID來區分是來自哪個菜單、工具欄按鈕或加速鍵的消息。

       3.通知消息。通知消息一般由列表框等子窗口發送給父窗口,消息名也是WM_COMMAND,其中附帶了控件通知碼來區分控件。

       CWnd的派生類都可以接收到標準Windows消息、通知消息和命令消息。命令消息還可以由文檔類等接收。

       用戶自定義消息是實際上就是用戶定義一個作為消息,此宏的值應該大于等于WM_USER,然后此宏就可以跟系統消息一樣使用,窗口類中可以定義它的處理函數。

       消息映射表

       除了一些沒有基類的類或CObject的直接派生類外,其他的類都可以自動生成消息映射表。下面的講解都以前面例程HelloWorld的CMainFrame為例。消息映射表如下:

C++代碼
  1. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)   
  2.     ON_WM_CREATE()   
  3.     ON_COMMAND(ID_VIEW_CUSTOMIZE, &CMainFrame::OnViewCustomize)   
  4.     ON_REGISTERED_MESSAGE(AFX_WM_CREATETOOLBAR, &CMainFrame::OnToolbarCreateNew)   
  5.     ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)   
  6.     ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)   
  7.     ON_WM_SETTINGCHANGE()   
  8. END_MESSAGE_MAP()  

       在BEGIN_MESSAG_MAP和END_MESSAGE_MAP之間的內容成為消息映射入口項。消息映射除了在CMainFrame的實現文件中添加消息映射表外,在類的定義文件MainFrm.h中還會添加一個宏調用:

       DECLARE_MESSAGE_MAP()

       一般這個宏調用寫在類定義的結尾處。

VS2010/MFC編程入門之五(MFC消息映射機制概述)

       添加消息處理函數

       如何添加消息處理函數呢?不管是自動還是手動添加都有三個步驟:

       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中實現此函數。

       雞啄米本節對MFC消息映射機制只是做了比較簡單的講解,讓大家對它有一定的認識,編程入門者不必強求完全掌握。在以后的教程中會經常涉及到消息的使用,大家會逐漸熟悉MFC的消息映射機制。

 

除非特別注明,雞啄米文章均為原創
轉載請標明本文地址:http://www.9385095.live/software/147.html
2012年3月20日
作者:雞啄米 分類:軟件開發 瀏覽: 評論:13