原創 MFC訊息對映機制

2021-08-03 08:51:31 字數 2873 閱讀 7245

mfc訊息對映機制

mfc程式是靠訊息對映驅動的,當使用者執行滑鼠/鍵盤、移動視窗等操作時,windows系統基於這些動作生成訊息並存入系統訊息佇列。mfc程式執行訊息迴圈,取出屬於自己的訊息並執行這些訊息。mfc處理訊息時,先進行預處理,預處理返回真的訊息則當前處理結束,繼續抓取下一條訊息進行處理,預處理返回假的訊息再分發處理,進入mfc訊息對映機制。

1.       訊息預處理

mfc訊息迴圈在抓取訊息後,先使用afxpretranslatemessage進行訊息預處理,對沒有預處理的訊息再進行翻譯和分發處理。

預處理流程從接受訊息的視窗出發,逐步向其父視窗迭代,每次均使用迭代視窗進行預處理,直到視窗指標為空為止。沒有預處理的訊息則進行翻譯(translatemessage)和分發處理(dispachmessage)。預處理函式(pretranslatemessage)為虛函式。

2.       訊息分發處理

分發時,根據cwnd::onwndmsg(wincore.cpp:1760中)處理訊息的方法,將訊息分wm_command、wm_notify和其他訊息。選單訊息、按鈕訊息等通過on_command、on_control等巨集實現的訊息屬於wm_command訊息,與wm_notify訊息相比,只能傳遞乙個通知碼。wm_notify訊息傳遞複雜一些(lparam引數使用乙個nmhdr結構體),一般listctrl控制項傳遞的屬於wm_notify訊息,其他訊息的處理方式參見2.3。

2.1   wm_command處理

message source

wparam (high word)

wparam (low word)

lparam

menu

0menu identifier (idm_*)

0accelerator

1accelerator identifier (idm_*)

0control

control-defined notification code

control identifier

handle to the control window

wm_command訊息傳送個父視窗,其訊息引數如上圖所示,處理方式如下:

cwnd::onwndmsg

cwnd::oncommand

檢測命令是否可用/cwnd::reflectlastmsg

cmdtarget::oncmdmsg

由於是虛函式,在實際執行時,可能根據物件的不同呼叫到不同類中的**,所以此處以wincore.cpp中的cwnd物件為主,其餘類中的處理方式可參閱具體的源**。

cwnd::oncommand處理流程:對於選單和加速鍵(上表中lparam為0),先判斷當前選單、命令是否可用,然後再呼叫ccmdtarget::oncmdmsg處理;對於控制項,先反射給子視窗處理,如果子視窗沒有處理,則呼叫ccmdtarget::oncmdmsg進行處理。

ccmdtarget::oncmdmsg處理流程:從當前類開始,向父類逐步向上查詢,如果在訊息對映表中找到了處理函式,則呼叫處理,否則到根類ccmdtarget還沒有找到時,則使用預設處理方式defwindowproc。

由於cwnd::oncommand和ccmdtarget::oncmdmsg是虛函式,所以可重寫這兩個函式,改變訊息處理方法。mfc的cdialog,cframewnd, csplitterwnd等類都重寫了oncommand函式。

2.2   wm_notify處理

wparam

lparam

control identifier

nmhdr

nmhdr的定義如下:

typedef struct tagnmhdr nmhdr;

wm_notify訊息傳送給父視窗,訊息引數的wparam值為控制項id,lparam值指向nmhdr,或指向第乙個成員為nmhdr的結構體,可處理複雜的訊息。處理方式如下:

cwnd::onwndmsg

cwnd::onnotify

cwnd::reflectlastmsg

cmdtarget::oncmdmsg

cwnd::onnotify先呼叫reflectlastmsg反射給子視窗處理,如果子視窗沒有處理,則呼叫oncmdmsg處理。

2.3  其他訊息處理

其他訊息如wm_vscroll,wm_create等,訊息引數、傳送物件參考msdn。從當前類開始,向父類逐步向上查詢,如果在訊息對映表中找到了處理函式,則呼叫處理。

3.      反射訊息處理

在訊息分發時,帶控制代碼的wm_command訊息和wm_notify訊息,都會先反射給子視窗處理,最終通過cwnd::refelectchildnotify進行反射處理,此時的this指標指向子視窗。訊息碼在當前的基礎上,增加了wm_reflect_base。一般對combobox,edit,listctrl進行子類化,然後實現其反射訊息。

4.      小結

一般的wm_create,wm_vscroll訊息,對映機制簡單,從子類到父類逐級查詢,而對於wm_notify,wm_command,mfc提供了增加了onnotify,oncommand處理流程,並且對於cwnd,cframewnd等不同的類,onnotify,oncommand等內部的流程也是不同,這是通過虛函式實現的,onnotify,oncommand沒有找到訊息對映函式時,再從子類到父類逐級查詢。需要注意的是,wm_notify,wm_command時傳送給控制項的父視窗的,如果我們通過spy++剖析訊息流程時,除了監控控制項本身,控制項的父視窗也要監控。

MFC訊息對映機制

一 mfc中採用的這種訊息處理機制成為 mfc訊息對映機制 乙個mfc訊息響應函式在程式中有三處相關資訊 函式原型,函式實現,關聯訊息和訊息響應函式的巨集。函式原型 標頭檔案cdrawview 兩個afx msg注釋巨集之間 訊息響應函式原型的宣告 afx msg void onlbuttondow...

MFC訊息對映機制

win32的訊息迴圈機制是 產生的訊息交由作業系統,將其放到應用程式的訊息佇列中。應用程式通過getmessage函式從這個佇列中取出 一條訊息 由dispatchmessage函式把訊息又交給作業系統,作業系統呼叫視窗過程函式wndproc進行處理。該函式利用switch case結構來判斷並響應...

MFC訊息對映機制

mfc的設計者們在設計mfc時,緊緊把握乙個目標,那就是盡可能使得mfc的 要小,速度盡可能快。為了這個目標,他們使用了許多技巧,其中很多技巧體現在巨集的運用上,實現mfc的訊息對映的機制就是其中之一。同mfc訊息對映機制有關的巨集有下面幾個 declare message map 巨集 begin...