我們知道命令訊息就是由功能表列,工具列或加速鍵(我們一般叫做快速鍵)產生的訊息.
前面有講過標準訊息就由其對應的CWnd類的子類處理就OK,子類不處理就回溯回父類.不用轉給其他類處理.但命令訊息不同,只要是繼承自CCmdTarget的類都可以處理,也就是說前面提到的5個核心的類(CWinApp,CSingleDocTemplate,CFrameWnd,CView,CDocument)都可以處理它.
那一個命令訊息發出來到底誰去處理呢 ?
首先你猜想著要是不是上面5個類都有對應的宏去映射下就都可以處理.也就是5個類同時處理? 顯然不是這樣.一次只讓一個類去處理的.於是就會給這5個類排下優先次序.先看前面有對應的訊息映射宏不,有的話就讓該類來處理,排名靠後的類就不管他們了.反正就這樣依次檢查.
訊息路由的次序
這裡以SDI項目(single document inerface)為例來說下.假如點下功能表列中的File-->Open發出一個訊息,看下這訊息是怎麼被處理的.
假如繼承自CWinApp,CFrameWnd,CView,CDocument的4個類中都寫上宏
ON_COMMAND(ID_FILE_OPEN, OnOpen);
定義了函數afx_msg void OnFileOpen();
這樣一來說明這4個類都有能力來處理命令訊息了,但有能力處理未必就真讓它處理.就像你覺得自己有能力當個啥領導了,但大領導未必就真讓你當,最是把你作為候選人而已.
首先我們知道那些菜單,工具列都是由CFrameWnd建立的.但實際上最先不是由它來處理.(實際上準確的講是這4個類的子類來處理,為了討論方便就說父類的名字好了)
1.先是由CView來處理,你Debug的時候會看到執行到CView的OnFileOpen函數.執行完這函數後其他類中相同的OnFileOpen不會被執行到.
2.如果CView沒有處理則由CDocument來處理.你可以把CView中的宏ON_COMMAND(ID_FILE_OPEN, OnOpen)注釋掉.這樣debug下就發現會執行CDocument中的函數OnFileOpen了
3.如果CDocument也沒有處理則由CFrameWnd來處理.同樣你把CDocument的宏ON_COMMAND(ID_FILE_OPEN, OnOpen)注釋掉.這樣debug下就發現會執行CFrameWnd中的函數OnFileOpen了
4.如果CDocument也沒處理則由CWinApp來處理.你把CFrameWnd的宏ON_COMMAND(ID_FILE_OPEN, OnOpen)注釋掉.這樣debug下就發現會執行CWinApp中的函數OnFileOpen了
所以路由的順序是1.CView -- > 2.CDocument --->3.CFrameWnd -->3.CWinApp
當然如果是MDI項目的話順序就不太一樣.是下面這樣
1.CView --> 2.CDocument -->3.CMDIChildWnd--> 4.CWinApp -->5.CMDIFrameWnd
(注:貌似有些書上講是CWinApp最後一個,但實際上測試的時候發現不是.你反正自己在VS中debug測下就知道了)