MFC中的消息處理

[轉自:http://blog.csdn.net/gxj1680/archive/2009/03/17/3998923.aspx]

窗口消息概述:  
  所有的窗口消息的基本形式都是一樣的,有3個部分:(1).一個無符號整數,包含消息的實際內容.(2)WPARAM,一個4字節整數.(3)LPARAM,一個4字節參數.無符號數是實際消息.  
  含MFC在內的任何WINDOWS程序的核心都是消息泵.消息泵是一個循環,它取出消息並將消息送給恰當的窗口消息處理函數.下面是個消息泵的示例:  
  while(GetMessage(&msg,NULL,NULL,NULL)){  
  TranslateMessage(&msg)   ;  
  DispatchMessage(&msg)   ;  
  }  
  return   msg.wParam   ;  
  程序會在開始運行時調用RegisterClass()並使用一個WNDCLASS結構來註冊至少一個窗口類.每當該類的一個窗口窗口中有消息時,WINDOWS都會調用WNDCLASS中的lpfnWndProc所指定的函數.  
  典型的SDK程序中消息處理函數是個龐大且難於維護的switch語句.C++中可用虛函數處理每個消息,但是,這種方法將帶因虛表而產生過多的開銷,且不易適應消息的增減.  
   
  ----------------------------  
  CCmdTarget和消息映射表----MFC的消息處理結構的兩個基本組成部分  
   
   
  ----------------------------  
  消息映射表數據結構  
   
  struct   AFX_MSGMAP_ENTRY   {//消息映射表實際入口.  
  UINT   nMessage;//實際消息  
  UINT   nCode;//控件代碼或通知代碼  
  UINT   nID;//控件ID  
  UINT   nLastID;//控件最大ID  
  UINT   nSig;//消息處理函數的簽名  
  AFX_PMSG   pfn;//消息處理函數  
  };  
  struct   AFX_MSGMAP   {   //實際的消息映射表.  
  const   AFX_MSGMAP*   pBaseMap;//基類的消息映射表.  
  const   AFX_MSGMAP_ENTRY*   lpEntries   ;//消息表入口數組指針.  
  }  
   
  消息映射宏:  
  #define   DECLARE_MESSAGE_MAP()   /  
  private:   /  
  static   const   AFX_MSGMAP_ENTRY   _messageEntries[];   /  
  protected:   /  
  static   AFX_DATA   const   AFX_MSGMAP   messageMap;   /  
  virtual   const   AFX_MSGMAP*   GetMessageMap()   const;   /  
   
  #define   BEGIN_MESSAGE_MAP(theClass,   baseClass)   /  
  const   AFX_MSGMAP*   theClass::GetMessageMap()   const   /  
  {   return   &theClass::messageMap;   }   /  
  AFX_COMDAT   AFX_DATADEF   const   AFX_MSGMAP   theClass::messageMap   =   /  
  {   &baseClass::messageMap,   &theClass::_messageEntries[0]   };   /  
  AFX_COMDAT   const   AFX_MSGMAP_ENTRY   theClass::_messageEntries[]   =   /  
  {   /  
   
  #define   END_MESSAGE_MAP()   /  
  {0,   0,   0,   0,   AfxSig_end,   (AFX_PMSG)0   }   /  
  };    
   
  常用消息表入口宏:  
  ON_WM_XXXX:預定義的窗口消息  
  ON_COMMAND:命令  
  ON_UPDATE_COMMAND_UI:更新命令  
  ON_XXXX:控件通知  
  ON_MESSAGE:用戶自定義的消息  
  ON_REGISTERED_MESSAGE:註冊的窗口消息  
  ON_COMMAND_RANGE:指定ID範圍的命令  
  ON_UPDATE_COMMAND_UI_RANGE:指定ID範圍的更新命令  
  ON_CONTROL_RANGE:指定ID範圍的控件  
  ON_NOTIFY:通知消息  
  ON_NOTIFY_RANGE:指定ID範圍的通知消息  
  ...  
  實現示例:  
  #define   ON_COMMAND(id,   memberFxn)   /  
  {   WM_COMMAND,   CN_COMMAND,   (WORD)id,   (WORD)id,   AfxSig_vv,   (AFX_PMSG)&memberFxn   },  
  //   ON_COMMAND(id,   OnFoo)   is   the   same   as  
  //       ON_CONTROL(0,   id,   OnFoo)   or   ON_BN_CLICKED(0,   id,   OnFoo)  
   
  ------------------------------  
  消息映射表的使用  
   
  消息映射表能處理兩種消息:一般的窗口消息(如鼠標消息)和命令消息(如菜單消息).  
   
  窗口和AfxWndProc建立關聯的過程  
  MFC中以DefWindowProc爲消息處理函數進行註冊.當新的CWnd派生類創建時(CreateEx中),::CreateAWindowEx 之前會調用AfxHookWindowCreate()設置HOOK:_AfxCbtFilterHook(),以處理窗口的激活,創建,銷燬等消息._AfxCbtFilterHook等到HCBT_CREATEWND消息到來時調用_AfxStandardSubClass(),由它調用 SetWindowLong()將AfxWndProc()放入窗口,由AfxWndProc()處理實際的消息.----MFC不直接註冊 AfxWndProc作爲消息處理函數以支持3D控件,此時要保證處理過程按以下順序調用:AfxWndProc,3D控件的WndProc,默認的 DefWindowProc.  
   
  AfxWndProc消息處理過程  
  1.AfxWndProc處理消息時首先判斷是否是WM_QUERYAFXWNDPROC,是就返回1,表示使用MFC的消息映射系統.  
  2.調用AfxCallWndProc.AfxCallWndProc在WM_INITDIALOG消息中將調用 _AfxHandleInitDialog使對話框居中.AfxCallWndProc還將在線程狀態中對消息對得保存,並最後調用窗口對象的窗口過程: 虛函數WindowProc();  
  3.CWnd::WindowProc調用CWnd::OnWndMsg(),如返回FALSE,則再調用CWnd::DefWindowProc();  
  4.CWnd::OnWndMsg()對應於SDK程序中的switch語句.首先它過濾特殊的消息 WM_COMMAN,WM_NOTIFY,WM_ACTIVATE,WM_SETCURSOR並調用框架類對應的特殊處理函數.其它消息進入消息映射表中去查找處理函數.  
   
  5.WM_COMMAND的處理.  
      1).第一站:虛函數CWnd::OnCommand();消息是框架類產生的,故調用框架類的OnCommand()實現.OnCommand檢查表示控件的LPARAM參數,控件產生的消息會在LPARAM中包含控件窗口,對控件通知消息會調用特寫處理過程.如消息是爲某個控件產生的,會 OnCommand在將消息直接發送給該控件後返回;否則,它保證產生命令的用戶界面元素沒有被禁用,然後將調用OnCmdMsg.  
      2).CFrame::OnCmdMsg().它按以下順序查找在消息映射表中查找處理函數:活動視圖,活動視圖的文檔,主窗口,應用程序.找到後就調用DispatchCmdMsg以執行所找到的處理函數,沒找到時調用DefWindowProc.  
      3).static   BOOL   DispatchCmdMsg():根據函數簽名(消息表入口項中的nSig變量)執行不同操作.一般菜單命令的簽名是AfxSig_xx,會直接調用處理函數,其它簽名可能要預先分解消息參數LPARAM,WPARAM;  
   
      到達框架窗口的命令路由:AfxWndProc--AfxCallWndProc--CWnd::WindowProc-- CFrameWnd::OnCommand--CWnd::OnCommand--CFrameWnd::OnCmdMsg-- CCmdTarget::OnCmdMsg--DispatchCmdMsg--CMainFrame類命令處理AfxWndProc-- AfxCallWndProc--CWnd::WindowProc--CFrameWnd::OnCommand-- CWnd::OnCommand--CFrameWnd::OnCmdMsg--CCmdTarget::OnCmdMsg-- DispatchCmdMsg--CMainFrame類命令處理函數  
      到達文檔的命令路由:AfxWndProc--AfxCallWndProc--CWnd::WindowProc-- CFrameWnd::OnCommand--CWnd::OnCommand--CFrameWnd::OnCmdMsg-- CView::OnCmdMsg--CDocument::OnCmdMsg--CCmdTarget::OnCmdMsg-- DispatchCmdMsg--文檔類命令處理函數  
      到達視圖的命令路由:AfxWndProc--AfxCallWndProc--CWnd::WindowProc-- CFrameWnd::OnCommand--CWnd::OnCommand--CFrameWnd::OnCmdMsg-- CView::OnCmdMsg--CCmdTarget::OnCmdMsg--DispatchCmdMsg--視圖類命令處理函數  
      到達應用程序類的命令路由:AfxWndProc--AfxCallWndProc--CWnd::WindowProc-- CFrameWnd::OnCommand--CWnd::OnCommand--CFrameWnd::OnCmdMsg-- CCmdTarget::OnCmdMsg--DispatchCmdMsg--應用程序類命令處理函數  
      到達對話框類的命令路由:AfxWndProc--AfxCallWndProc--CWnd::WindowProc-- CWnd::OnCommand--CWnd::OnCmdMsg--CDialog::OnCmdMsg--DispatchCmdMsg--對話框類命令處理函數  
   
  6.處理一般窗口消息:AfxWndProc--AfxCallWndProc--AfxCallWndProc--CWnd::WindowProc--CWnd::OnWndMsg--AfxFindMessageEntry--實際處理函數  
  7.調用成員函數.  
  函數簽名的定義:  
  union   MessageMapFunctions   {  
      Afx_PMSG   pfn   ;//一般成員函數指針.  
   
      BOOL   (AFX_MSG_CALL   CWnd::*pfn_bD)(CDC*);  
      BOOL   (AFX_MSG_CALL   CWnd::*pfn_bb(BOOL);  
      .......  
      };  
      在OnWndMsg中會將此聯合中的pfn設爲消息處理函數的地址:mmf.pfn=lpEntry->pfn,同時,查找合適的簽名,從WPARAM,LPARAM中取出必要的參數,使用與簽名一致的原型調用處理函數.  
  8.其它類型的消息.  
      1).WM_NOTIFY.  
      CWnd::ONWndMsg()用CWnd::OnNotify()來進行處理.OnNotify調用OnChildNotify()將消息送給控件.  
      2).消息反射.  
      可用消息反射宏來實現,以便控件自己處理特定的消息.  
      3).WM_ACTIVATE.  
      OnWndMsg()中調用_AfxHandleActivate()檢查最高層是否是WM_ACTIVATE,是則向最高層窗口發送WM_ACTIVATETOPLEVEL消息.  
      4).WM_SETCURSOR.  
      在_AfxHandleSetCursor()中處理.有鼠標按下時會激活最後一個活動窗口.  
   
  ---------------------------------  
  PreTranslateMessage----消息預處理  
   
  共兩個入口:CWinApp::PreTranslateMessage,CWnd::PreTranslateMessage.  
  在消息由TranslateMessage()和DispatchMessage()處理前,CWinApp::Run()調用 CWinApp::PreTranslateMessage,然後,CWinApp::PreTranslateMessage會從消息結構中對指定的目標窗口及應用程序的主窗口調用每個窗口的CWnd::Translatemessage().  
  預處理過程返回TRUE,則消息不再進行後繼處理.  

 另一篇:

MFC程序的消息處理順序

 

1.AfxWndProc()      該函數負責接收消息,找到消息所屬的CWnd對象,然後調用AfxCallWndProc

 

 

聞香止步 淘寶 拍拍 有啊 易趣店 收集
常年經營木雕系列產品:
海南黃花梨、越南黃花梨、草花梨、小葉紫檀、黑檀、香榧木、綠檀木、黃楊木 擺件;
紫檀、綠檀木、黃楊木、桃木、漆藝髮簪 
木梳 樟木壁掛 佛珠 車飾

收藏送禮佳品,也可聯繫訂做

淘寶店:http://shop36570193.taobao.com
拍拍店:http://421840135.paipai.com/

聯繫方式:
QQ   421840135
旺旺 xiaobaitucsl
郵件 [email protected]

朋友,有空來看看,喜歡的朋友請收藏

  2.AfxCallWndProc()  該函數負責保存消息(保存的內容主要是消息標識符和消息參數)供應用程序以後使用,然後調用WindowProc()函數

  3.WindowProc()      該函數負責發送消息到OnWndMsg()函數,如果未被處理,則調用DefWindowProc()函數

  4.OnWndMsg()        該函數的功能首先按字節對消息進行排序,對於WM_COMMAND消息,調用OnCommand()消息響應函數,對於WM_NOTIFY消息調用 OnNotify()消息響應函數。任何被遺漏的消息將是一個窗口消息。OnWndMsg()函數搜索類的消息映像,以找到一個能處理任何窗口消息的處理函數。如果OnWndMsg()函數不能找到這樣的處理函數的話,則把消息返回到WindowProc()函數,由它將消息發送給 DefWindowProc()函數

  5.OnCommand()       該函數查看這是不是一個控件通知(lParam參數不爲NULL,如果lParam參數爲空的話,說明該消息不是控件通知),如果它是,OnCommand()函數會試圖將消息映射到製造通知的控件;如果他不是一個控件通知(或者如果控件拒絕映射的消息)OnCommand()就會調用OnCmdMsg()函數

  6.OnCmdMsg()        根據接收消息的類,OnCmdMsg()函數將在一個稱爲命令傳遞(Command Routing)的過程中潛在的傳遞命令消息和控件通知。例如:如果擁有該窗口的類是一個框架類,則命令和通知消息也被傳遞到視圖和文檔類,併爲該類尋找一個消息處理函數
  MFC應用程序創建窗口的過程

  1.PreCreateWindow()   該函數是一個重載函數,在窗口被創建前,可以在該重載函數中改變創建參數(可以設置窗口風格等等)

  2.PreSubclassWindow() 這也是一個重載函數,允許首先子分類一個窗口

  3.OnGetMinMaxInfo()   該函數爲消息響應函數,響應的是WM_GETMINMAXINFO消息,允許設置窗口的最大或者最小尺寸

  4.OnNcCreate()        該函數也是一個消息響應函數,響應WM_NCCREATE消息,發送消息以告訴窗口的客戶區即將被創建

  5.OnNcCalcSize()      該函數也是消息響應函數,響應WM_NCCALCSIZE消息,作用是允許改變窗口客戶區大小

  6.OnCreate()          該函數也是一個消息響應函數,響應WM_CREATE消息,發送消息告訴一個窗口已經被創建

  7.OnSize()            該函數也是一個消息響應函數,響應WM_SIZE消息,發送該消息以告訴該窗口大小已經發生變化

  8.OnMove()            消息響應函數,響應WM_MOVE消息,發送此消息說明窗口在移動

  9.OnChildNotify()     該函數爲重載函數,作爲部分消息映射被調用,告訴父窗口即將被告知一個窗口剛剛被創建

  MFC應用程序關閉窗口的順序(非模態窗口)

  1.OnClose()       消息響應函數,響應窗口的WM_CLOSE消息,當關閉按鈕被單擊的時候發送此消息

  2.OnDestroy()     消息響應函數,響應窗口的WM_DESTROY消息,當一個窗口將被銷燬時,發送此消息

  3.OnNcDestroy()   消息響應函數,響應窗口的WM_NCDESTROY消息,當一個窗口被銷燬後發送此消息

  4.PostNcDestroy() 重載函數,作爲處理OnNcDestroy()函數的最後動作,被CWnd調用
  MFC應用程序中打開模式對話框的函數調用順序

  1.DoModal()             重載函數,重載DoModal()成員函數

  2.PreSubclassWindow()   重載函數,允許首先子分類一個窗口

  3.OnCreate()            消息響應函數,響應WM_CREATE消息,發送此消息以告訴一個窗口已經被創建

  4.OnSize()              消息響應函數,響應WM_SIZE消息,發送此消息以告訴窗口大小發生變化

  5.OnMove()              消息響應函數,響應WM_MOVE消息,發送此消息,以告訴窗口正在移動

  6.OnSetFont()           消息響應函數,響應WM_SETFONT消息,發送此消息,以允許改變對話框中控件的字體

  7.OnInitDialog()        消息響應函數,響應WM_INITDIALOG消息,發送此消息以允許初始化對話框中的控件,或者是創建新控件

  8.OnShowWindow()        消息響應函數,響應WM_SHOWWINDOW消息,該函數被ShowWindow()函數調用

  9.OnCtlColor()          消息響應函數,響應WM_CTLCOLOR消息,被父窗口發送已改變對話框或對話框上面控件的顏色

  10. OnChildNotify()     重載函數,作爲WM_CTLCOLOR消息的結果發送
  MFC應用程序中關閉模式對話框的順序

  1.OnClose()        消息響應函數,響應WM_CLOSE消息,當"關閉"按鈕被單擊的時候,該函數被調用

  2.OnKillFocus()    消息響應函數,響應WM_KILLFOCUS消息,當一個窗口即將失去鍵盤輸入焦點以前被髮送

  3.OnDestroy()      消息響應函數,響應WM_DESTROY消息,當一個窗口即將被銷燬時,被髮送

  4.OnNcDestroy()    消息響應函數,響應WM_NCDESTROY消息,當一個窗口被銷燬以後被髮送

  5.PostNcDestroy()  重載函數,作爲處理OnNcDestroy()函數的最後動作被CWnd調用
  打開無模式對話框的順序

  1.PreSubclassWindow()    重載函數,允許用戶首先子分類一個窗口

  2.OnCreate()             消息響應函數,響應WM_CREATE消息,發送此消息以告訴一個窗口已經被創建

  3.OnSize()               消息響應函數,響應WM_SIZE消息,發送此消息以告訴窗口大小發生變化

  4.OnMove()               消息響應函數,響應WM_MOVE消息,發送此消息以告訴窗口正在移動

  5.OnSetFont()            消息響應函數,響應WM_SETFONT消息,發送此消息以允許改變對話框中控件的字體
  以上這些的執行都是按給定的順序執行!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章