How the Framework Calls a Handler(譯自MSDN)

  1. /*
  2.     編程框架調用消息響應函數的原理
  3.     1:消息的發送與接收
  4.     大多數的消息來源於用戶與程序的交互。命令消息來源於鼠標對菜單及工具欄的
  5.     點擊及快捷鍵的按下。當用戶改變窗口的大小或位置時,也會產生消息。另外,
  6.     當啓動或關閉程序及窗口得到或失去焦點時也會產生普通消息。控件通知消息產生
  7.     自己鼠標對控件的操作,比如對話框上的按鈕或列表框被點擊時。
  8.     類CWinApp的Run方法會從消息隊列中提取消息,然後再將它們發送到相關的窗口。
  9.     多數的命令消息會被髮送到程序的主窗口。類庫預先定義的WindowProc會得到這些
  10.     消息然後根據消息的不同類型採用不同的路由方式進行路由。
  11.     消息的接收細節:
  12.         消息的最初接收者必須是一個窗口對象。普通消息通常由窗口對象直接處理,
  13.         命令消息,通常來自於主窗口,會根據命令-目標鏈進行路由。
  14.         每一個能夠接收消息或命令的對象都具有自身的消息映射,這個映射可以將
  15.         消息或命令與其處理函數聯繫起來。
  16.         當一個命令目標對象接收到一個消息或者命令,它會檢查自身的消息映射,
  17.         如果它發現自身具有一個處理此消息或命令的處理函數,就是調用之。
  18.     2:非命令消息與其處理函數的關聯
  19.     不像命令消息,標準的Windows消息不會通過命令目標鏈進行路由,而是由接收此
  20.     消息的窗口直接處理。這個窗口可能是主窗口,也可能是多文檔子窗口,也可能
  21.     是標準控件或對話框或視圖等。
  22.     在運行時,每一個Windows窗口都與一個窗口對象(派生自CWnd)聯繫在一起,
  23.     這個窗口對象具有與自身相關聯的消息映射和處理函數羣。編程框架會通過這個
  24.     消息映射,像命令消息一樣,將消息與處理函數聯繫起來。
  25.     3: 命令路由
  26.     在與涉及到命令消息的工作中,程序員的責任公侷限於搭建一個消息映射以建立命令
  27.     與處理函數之間的聯繫。這個任務可以通過屬性窗口完成。有一點很重要,就是程序
  28.     員要寫命令處理函數體。
  29.     Windows標準消息通常發送給主窗口,但是命令消息在此基礎上還得被路由到其它
  30.     對象。編程框架以一個標準的序列在命令目標對象間路由命令消息,這些對象的一個
  31.     應該有與正在被路由的命令相對應的處理函數。每一個命令目標對象都會檢查自己
  32.     的消息映射表以決定自己可否處理當前命令。
  33.     不同的命令目標類會在不同的時間檢查自己的消息映射表,通常情況下,一個類會
  34.     先在一些特定的對象間路由命令以給這些對象優先的處理權,如果這些特定的對象
  35.     無法處理這個命令,這個類就會檢查自身的消息映射表。如果其自身也無法提供一個
  36.     處理函數,那麼它會在其它的更多的對象間路由這個命令。
  37.     命令路由的通常順序如下:
  38.         A:自己當前的處理活動狀態的子對象。
  39.         B:自己
  40.         C:其它
  41.     命令路由花費的代價並不高,相對於消息處理函數花費的代碼,路由是微不足道的。因爲
  42.     我們都知道,命令消息只有在用戶與UI對應交互時纔會產生。
  43.     例子:
  44.         CMDIFrameWnd                First:  Active CMDIChildWnd
  45.                                     Second: This frame window
  46.                                     Third:  Application(CWinApp Object)
  47.         Document frame window       First:  Active View
  48.         (CFrameWnd,CMDIChildWnd)    Second: This frame window
  49.                                     Third:  Application(CWinApp Object)
  50.         View                        First:  This view
  51.                                     Second: Document attached to the view
  52.         Document                    First:  This document
  53.                                     Second: Document template attached
  54.                                             to the document
  55.         Dialog Box                  First:  This dialog box
  56.                                     Second: Window that own this dialog
  57.                                     Third:  Application(CWinApp Object)
  58.         
  59.     4:命令路由的例子
  60.     用戶選擇了一個MDI程序下Edit菜單下的一項,則命令路由的過程如下:
  61.         A:主窗口首先接收到這條命令
  62.         B:MDI框架窗口給當前活動狀態的MDI子框架窗口一次處理的機會
  63.         C:MDI子框架窗口在檢查自己的消息映射表之前先給它所有的視圖一次處理的機會
  64.         D:視圖先檢查自己的消息映射表,如無合適處理函數,會將命令傳送給與其相關聯
  65.             的文檔。
  66.         E:文檔檢查自己的消息映射表且發現了一個合適的處理函數
  67.         最終在文檔中發現的處理函數會被調用,路由結束。
  68.     如果在E中文檔也沒有發現合適的處理函數,則文檔會在與其相關的文檔模板間進行路由,
  69.     然後命令會返回到視圖及框架窗口。最終框架窗口會檢查其自身的消息映射表,如果自身
  70.     還不具備合適的處理函數,那麼命令會被回送到MDI框架窗口或更上一層的CWinApp對象。
  71.     CWinApp對象是未被處理命令的最終目的地,即處理地點。要吧推測,應用程序對象本身
  72.     會對所有的命令有一個默認的處理。
  73.     5:處理函數OnCmdMsg
  74.     爲了繼續路由,每一個命令目標站都會調用下一個命令目標站的OnCmdMsg方法,這樣
  75.     依次的調用就可以保證路由不停地進行下去。命令目標站會通過OnCmdMsg檢查其自身
  76.     能否處理此命令,如果不能就將命令傳遞到下一個命令目標站。
  77.     每一個命令目標類都應該重載OnCmdMsg函數,這樣可以自定義下一個命令目標站。
  78.     類CCmdTarget對OnCmdMsg的默認實現是通過消息映射表爲接收到的命令查找合適的
  79.     處理函數,對於普通消息也是這樣子實現的。如果它找到了合適的處理函數,就是調用它。
  80.     6:重載標準的命令路由方式
  81.     只有在很少數的情況下,爲了滿足自己的需求,我們必須重載標準的路由方式。基本
  82.     方法就是重載一個類或幾個類的OnCmdMsg方法,按下面的方法:
  83.         A:在將在打破標準順序的類中添加一個非默認的對象
  84.         B:在這個新添加的對象或命令目標站中輪流爲其傳遞命令
  85.     如果在路由鏈中插入了新的對象,要確定這些對象所屬的類是命令目標類,即派生自
  86.     CCmdTarget。在你重載的OnCmdMsg中,要確保已調用了原版的OnCmdMsg。
  87. */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章