mfc的設計者們在設計mfc時,緊緊把握乙個目標,那就是盡可能使得mfc的**要小,速度盡可能快。為了這個目標,他們使用了許多技巧,其中很多技巧體現在巨集的運用上,實現mfc的訊息對映的機制就是其中之一。
同mfc訊息對映機制有關的巨集有下面幾個:
declare_message_map()巨集
begin_message_map(theclass, baseclass)和end_message_map()巨集
弄懂mfc訊息對映機制的最好辦法是將找出乙個具體的例項,將這些巨集展開,並找出相關的資料結構。
declare_message_map()
declare_message_map()巨集的定義如下:
#define declare_message_map() \
private: \
static const afx_msgmap_entry _messageentries; \
protected: \
static afx_data const afx_msgmap messagemap; \
virtual const afx_msgmap* getmessagemap() const; \
從上面的定義可以看出,declare_message_map()作下面三件事:
定義乙個長度不定的靜態陣列變數_messageentries;
定義乙個靜態變數messagemap;
定義乙個虛函式getmessagemap();
在declare_message_map()巨集中,涉及到mfc中兩個對外不公開的資料結構
afx_msgmap_entry和afx_msgmap。為了弄清楚訊息對映,有必要考察一下這兩個資料結構的定義。
afx_msgmap_entry的定義
struct afx_msgmap_entry
;結構中各項的含義注釋已經說明得很清楚了,這裡不再多述,從上面的定義你是否看出,afx_msgmap_entry結構實際上定義了訊息和處理此訊息的動作之間的對映關係。因此靜態陣列變數_messageentries實際上定義了一張表,表中的每一項指定了相應的物件所要處理的訊息和處理此訊息的函式的對應關係,因而這張表也稱為訊息對映表。再看看afx_msgmap的定義。
(2)afx_msgmap的定義
struct afx_msgmap
;不難看出,afx_msgmap定義了一單向鍊錶,鍊錶中每一項的值是一指向訊息對映表的指標(實際上就是_messageentries的值)。通過這個鍊錶,使得在某個類中呼叫基類的的訊息處理函式很容易,因此,「父類的訊息處理函式是子類的預設訊息處理函式」就「順理成章」了。在後面的「mfc視窗的訊息處理」一節中會對此作詳細的講解。
begin_message_map()和end_message_map()
它們的定義如下:
#define begin_message_map(theclass, baseclass) \
const afx_msgmap* theclass::getmessagemap() const \
\afx_comdat afx_datadef const afx_msgmap theclass::messagemap = \
; \afx_comdat const afx_msgmap_entry theclass::_messageentries = \
\}; \
對應begin_message_map()的定義可能不是一下子就看得明白,不過不要緊,舉一例子就很清楚了。對於begin_message_map(cview, cwnd),vc預編譯器將其展開成下面的形式:
const afx_msgmap* cview::getmessagemap() const
afx_comdat afx_datadef const afx_msgmap cview::messagemap =
;afx_comdat const afx_msgmap_entry cview::_messageentries =
,根據上面的定義,on_command(id_file_new, onfilenew)將被vc預編譯器展開
如下:,
到此,mfc的訊息對映機制已經清楚了,現在提出並解答兩個問題以作為對這一節的小結。
為什麼不直接使用虛函式實現訊息處理函式呢?這是乙個good question。前面已經說過,mfc的設計者們在設計mfc時有乙個很明確的目標,就是使得「mfc的**盡可能小,速度盡可能快」,如果採用虛函式,那麼對於所有的視窗訊息,都必須有乙個與之對應的虛函式,因而對每乙個從cwnd派生的類而言,都會有一張很大的虛函式表vtbl。但是在實際應用中,一般只對少數的訊息進行處理,大部分都交給系統預設處理,所以表中的大部分項都是無用項,這樣做就浪費了很多記憶體資源,這同mfc設計者們的設計目標是相違背的。當然,mfc所使用的方法只是解決這類問題的方式之一,不排除還有其他的解決方式,但就我個人觀點而言,這是一種最好的解決方式,體現了很高的技巧性,值得我們學習。
至於這第二個問題,是由上面的問題引申出來的。如果在子類和父類中出現了相同的訊息出來函式,vc編譯器會怎麼處理這個問題呢?vc不會將它們看作錯誤,而會象對待虛函式類似的方式去處理,但對於訊息處理函式(帶afx_msg字首),則不會生成虛函式表vtbl。
MFC訊息對映機制
一 mfc中採用的這種訊息處理機制成為 mfc訊息對映機制 乙個mfc訊息響應函式在程式中有三處相關資訊 函式原型,函式實現,關聯訊息和訊息響應函式的巨集。函式原型 標頭檔案cdrawview 兩個afx msg注釋巨集之間 訊息響應函式原型的宣告 afx msg void onlbuttondow...
MFC訊息對映機制
win32的訊息迴圈機制是 產生的訊息交由作業系統,將其放到應用程式的訊息佇列中。應用程式通過getmessage函式從這個佇列中取出 一條訊息 由dispatchmessage函式把訊息又交給作業系統,作業系統呼叫視窗過程函式wndproc進行處理。該函式利用switch case結構來判斷並響應...
MFC訊息對映機制
windows應用程式是訊息驅動的。在mfc 軟體開發中,介面操作或者執行緒之間通訊都會經常用到訊息,通過對訊息的處理實現相應的操作。比較典型的過程是,使用者操作視窗,然後有訊息產生,送給視窗的訊息處理函式處理,對使用者的操作做出響應。什麼是訊息 視窗訊息一般由三個部分組成 1.乙個無符號整數,是訊...