本章將會對mfc的訊息對映和 命令傳遞機制做深入**。
mfc規定了訊息傳遞的路線,訊息會按照這個路線傳遞下去,找不到歸宿的話就交給defwindowproc。
在產生視窗之前,如果我們在建立視窗時指定的視窗類為null時,mfc會自動註冊五個預設的視窗類,每個視窗類有自己的視窗函式。不同視窗得到的訊息應該交由不同的視窗函式來處理。所謂的命令傳遞機制是為了讓訊息的流動有線路可循,實現乙個巨大的網,實現所有可能的路線。這就是所謂的訊息對映圖。
wm_command是來自選單或工具欄,被稱為命令訊息。wparam記錄著這一訊息來自哪個選單專案。
除了命令訊息控制項傳給父視窗的訊息,也是以wm_command型別的,但是它們被稱為notification訊息。
command target即命令的目的地。因此所有派生自ccmdtarget類的類都可以處理命令訊息。
派生自cwnd的類可以處理一般的windows訊息和command訊息。
declare_message_map()
begin_message_map
on_comamnd()
end_message()
這些巨集實現了訊息和訊息處理函式的對映,不再介紹哦。
在begin和end之間除了on_command之外,還可以有其他的形式,標準的windows訊息並不需要我們指定處理函式的名稱。如:
on_wm_char();wm_char onchar
on_wm_close(); wm_close onclose
on_wm_create(); wm_create oncreate
這些巨集mfc已經定義好,將標準的訊息和訊息處理函式對應起來。
afx_dat,afx_datadef,afx_msg_call和afx_msg一樣現在還沒有被使用。
訊息對映表有c++多型的味道,但是mfc卻沒有使用多型來實現它,究其原因估計是多型會導致很大的負擔。
前面的介紹中,以afxwinproc作為起點,此處mfc仍以此作為開始,但是卻省略了很多的細節。通常訊息是在訊息佇列中等待視窗抓取,但是mfc安裝了鉤子,就可以提前抓取或抓取不是自己的訊息。這是在所有派生自cwnd的物件建立之際發生的。如:
bool cwnd::createex()
afxhookwindowcreate安裝了wh_cbt型別的鉤子,任何視窗顯示之前,註冊的鉤子函式會被呼叫。
細節不再深入介紹,只要知道以上這些幹了些偷天換日的勾當,把註冊視窗類時註冊的視窗函式,更換為afxwndproc。於是afxwndproc便是dispatchmessage的目的地。之所以弄得這麼複雜書上說是為了相容什麼3d constrols。不懂,暫且放這兒吧。記住結論就是了。
上面可以知道afxwndproc是訊息的源頭,這在前面幾張也提到過。在此函式內部會呼叫afxclasswndproc,後者會呼叫pwnd->windowproc();在整個mfc中擁有windowproc的類有cwnd,ccontrolbar,colecontrol,cdialog......具體呼叫誰的windowproc要看pwnd 的型別。
在cwnd::windowproc中會呼叫onwndmsg函式,它是用來分辨並處理訊息的專職機構。如果是命令就交給oncommand處理,如果是通知訊息就交給onnotify處理。之所以要區分命令訊息和通知訊息是因為它們的上溯路徑並不是單純的只往父類上去,可能有其他路徑。而一般的windows訊息卻沿著直線上溯。
在oncommand又呼叫了oncmdmsg函式。具體呼叫哪個oncommand,oncmdmsg也是不定的,也得看this指標的型別。oncmdmsg它是專門處理命令訊息的函式。
bool cframewnd::oncmdmsg(uint nid,int ncode)
bool cview::oncmdmsg(uint nid,int ncode)
bool cdocument::oncmdmsg(uint nid,int ncode)
以上就是訊息的傳遞路線,這裡跟第三章模擬的命令傳遞路線是相同的,具體可以第三章。
oncmdmsg是各類專門對付命令訊息的函式。本類處理過後又會呼叫下乙個類的oncmdmsg,這樣命令訊息就會不斷傳遞下去。
在定義cruntimeclass時,messagemapentries內定義了訊息函式的指標型別,
typedef void(afx_msg_call
ccmdtarget:::*afx_pmsg)(void);
此時訊息處理函式指標型別為返回值為空,引數為空,這是不符合實際的,實際使用中會經過型別轉換,使其可以接收引數和返回值。
由於訊息處理函式的型別各異,mfc使用了afxsig_來說明訊息處理函式的型別。在找到某訊息的訊息處理函式之後,判斷其型別再進行響應轉換。
union messagemapfunctions mmf;
mmf.pfn=lpentry->pfn;
switch(lpentry->nsig)
afxsig_is代表引數為lptstr字串,返回值為int.
afx_lwl代表引數wiewparam和lparam。返回值為lresult。
afx_vv代表引數和返回值都為void.
(this->*mmf.pfn_vv)();中的pfn_vv是union messagemapfunctions的乙個成員。如
union messagemapfunctions
;注意messagemapfunctions是union型別的哦。
真是佩服當年mfc開發人員的智慧型!!!!!
深入淺出MFC筆記
深入淺出mfc筆記 一 勿在浮砂築高台 1 並不是擴充套件名為 dll dynamic link library 的才是動態鏈結庫。事實上,exe dll fon mod drv 和.ocx 都是所謂的動態鏈結函式庫。2 windows 程式編譯時需要包含 windows.h 標頭檔案,若需要使用諸...
《深入淺出MFC》筆記(三)
1,win32 console程式示例 include include include include const int filemax 300 allow max.300 files in each directory typedef struct destfile destfile typed...
深入淺出MFC學習篇
1.異常處理 exception handling c 中匯入了三個新的exception保留字 1.try,2.catch,3.throw 2.模板 template 模板是根據引數型別生成函式和類的機制 有時稱為 引數決定型別 通過使用模板,可以只設計乙個類來處理多種型別的資料,而不必為每一種型...