How the Framework Searches Message Maps(譯自MSDN)

  1. /*
  2.     本文翻譯自MSDN的How the Framework Searches Message Maps章節
  3.     對於接收到的消息,編程框架會通過消息映射表查找合適的消息處理函數。只要
  4.     你寫了針對指定消息的消息映射入口和相應的消息處理函數,編程框架會自動地
  5.     調用你寫的消息處理函數去處理相應的消息。
  6.     1:哪兒能找到消息映射
  7.     當你通過應用程序嚮導創建了一個新的框架程序,應用程序嚮導會爲每一個它爲你
  8.     創建的命令目標類添加消息映射。這些類包括你派生的程序實體,文檔,視圖,
  9.     框架窗口等。針對一些特定的消息和預定義的命令,嚮導已爲其添加了消息映射
  10.     入口,針對你可能添加的消息處理函數,嚮導也準備就緒只待你添加。
  11.     一個類的消息映射保存在這個類的CPP文件中,典型的消息映射看起來如下: 
  12. */
  13. BEGIN_MESSAGE_MAP(CMyView, CFormView)
  14.     ON_WM_MOUSEACTIVATE()
  15.     ON_COMMAND(ID_EDIT_CUT, &CMyView::OnEditCut)
  16.     ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, &CMyView::OnUpdateEditCut)
  17.     ON_BN_CLICKED(IDC_MYBUTTON, &CMyView::OnBnClickedMybutton)
  18.     ON_WM_CREATE()
  19. END_MESSAGE_MAP()
  20. /*
  21.     消息映射由一系列的宏構成,BEGIN_MESSAGE_MAP和END_MESSAGE_MAP是消息映射
  22.     的開頭和結尾。其它的宏如ON_COMMAND,填充了消息映射的內容。
  23.     
  24.     注意消息映射中不會有分號出現。
  25. */
  26. /*
  27.     2:派生的消息映射
  28.     在消息處理的過程中,檢查自身的消息映射表並不是消息映射的全部。如果在自身
  29.     的消息映射表中找不到合適的消息入口會如何?
  30.         CObject
  31.         CCmdTarget
  32.         CWnd
  33.         CView
  34.         CMyView
  35.     上圖是類CMyView的繼承關係。一個CMyView對象只是一個單獨的對象,但它卻具有
  36.     其基類的所有特性。所以當一個類無法在其自身的消息映射表中找到合適的消息
  37.     入口時,編程框架會到其直接基類的消息映射表中繼續查找。
  38.     宏BEGIN_MESSAGE_MAP指定了兩個類名作爲參數:
  39. */
  40. BEGIN_MESSAGE_MAP(CMyView, CFormView)
  41. /*
  42.     第一個參數指定了一個類名,表示當前的消息映射的所屬類,第二個參數是當前
  43.     類的直接基類,這樣就建立了一種聯繫,即編程框架可以到一個類的基類裏繼續
  44.     查找合適的消息入口。
  45.     基類的消息處理函數會被其派生類繼承下來,這和虛函數是一個道理。
  46.     如果在任何一個基類裏都無法找到合適的消息入口,那麼消息會被執行默認的處理。
  47.     如果消息是命令類型的,編程框架會到下一個命令目標中路由消息;如果是標準
  48.     的消息,消息會被傳遞到默認的窗口過程去處理。
  49.     爲了加速消息及其入口的匹配速度,編程框架會對最近進行了匹配項進行緩存,
  50.     當再次查找同一個消息的消息入口時,速度就會很快。比如對於找不到合適消息
  51.     入口的消息,這樣子做就會很有意義。消息映射在空間效率上比虛函數高很多。
  52.     3:處理函數與消息的一對多關係
  53.     有時我們想把一些相似的消息或通知使用完全相同的方式進行處理,這種情況下,
  54.     就可以將一個範圍內的消息或命令,通知等映射到同一個消息處理函數。消息映射
  55.     允許我們指定一個範圍內的消息:
  56.         
  57.         你可以將一組命令ID映射到
  58.             命令處理函數
  59.             命令更新處理函數
  60.         你可以將一組控件ID發出的控件消息映射到同一處理函數
  61.         A:寫一個消息映射入口 
  62.         */
  63.         ON_COMMAND_RANGE(ID_MYCMD_ONE, ID_MYCMD_TEN, &OnDoSomething)
  64.         /*
  65.             消息映射入口由以下幾部分構成:
  66.             
  67.             a: 指定範圍的消息映射宏:
  68.             
  69.             ON_COMMAND_RANGE
  70.             ON_UPDATE_COMMAND_UI_RANGE
  71.             ON_CONTROL_RANGE
  72.             b: 宏的參數:
  73.             前兩個宏使用三個參數:
  74.                 起始的命令ID
  75.                 終止的命令ID
  76.                 消息處理函數的名稱
  77.             起始和終止間的命令ID必須是連續的。
  78.             第三個宏,在具有前面所述的三個參數的前提下,在前面還要求一個參數,
  79.             即其第一個參數是一個控件通知消息,後三個參數和前述一致。
  80.         
  81.         B:聲明消息處理函數
  82.         */
  83.             public:
  84.                 afx_msg void OnDoSomething(UINT nID);
  85.             /*
  86.             針對單一命令的消息處理函數通常沒有參數。但命令更新處理函數是個
  87.             例外。針對一個範圍的消息處理函數需要附加一個參數,一個UINT類型
  88.             的nID,這個參數指定了一個範圍內的命令ID內,用戶選擇的具體是哪一個。
  89.             例:
  90.             */
  91.             ON_COMMAND_RANGE(ID_VIEW_ZOOM25, ID_VIEW_ZOOM300, &OnZoom)
  92.             public:
  93.                 afx_msg void OnZoom(UINT nID);
  94.             /*
  95.                 nID將會是[ID_VIEW_ZOOM25,ID_VIEW_ZOOM300]中的一個。編程框架
  96.                 爲會我們自動傳入。
  97.             */
  98.             /*
  99.                 指定範圍的命令更新消息的使用方式也是類似的,只不過其處理函數
  100.                 不需要一個UINT類型的參數,而是一個CCmdUI*類型的參數,其內
  101.                 包括了nID。
  102.             */
  103.             /*
  104.                 指定範圍的控件通知消息的使用例子如下:
  105.             */
  106.     ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON1, IDC_BUTTON10, OnButtonClicked)    
  107.     void CRangesView::OnButtonClicked( UINT nID )
  108.     {
  109.         int nButton = nID - IDC_BUTTON1;
  110.         ASSERT( nButton >= 0 && nButton < 10 );
  111.         // ...
  112.     }
  113.     /*
  114.         對於單一的控件通知消息而言,其處理函數不需要參數,但對於指定範圍的
  115.         控件通知消息而言,類似於指定範圍的命令ID,其處理函數也需要一個UINT
  116.         類型的變量,用於標識具體是哪一個控件發出的通知。
  117.     */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章