MFC訊息對映與命令傳遞

2021-09-07 04:53:09 字數 3651 閱讀 4596

declare_message_map巨集

在 mfc 幾乎每個標頭檔案下(類的最後一行宣告),都會有這麼幾行**:

// 生成的訊息對映函式

protected:

declare_message_map()

我們看一看 declare_message_map到底為何物,檢視 declare_message_map原始碼(c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afxwin.h):

#define declare_message_map() \

protected: \

static const afx_msgmap* pascal getthismessagemap(); \

virtual const afx_msgmap* getmessagemap() const; \

我們看到了乙個陌生的型別 afx_msgmap ,檢視其定義: 

struct afx_msgmap

;這個結構體第乙個成員是乙個函式指標,第二個成員型別為 afx_msgmap_entry* ,檢視afx_msgmap_entry 定義:

struct afx_msgmap_entry

;typedef void (afx_msg_call ccmdtarget::*afx_pmsg)(void);

是乙個函式指標。是不是將每個訊息與其處理方法繫結起來呢?真有可能。

begin_message_map/on.../end_messagebox 巨集

在mfc 幾乎每個(類定義的)原始檔下都會出現下面幾行**(或者類似):

begin_message_map(c***, c***)

on_……

end_message_map()

我們繼續一**竟,檢視這幾個巨集的原始碼:

#define begin_message_map(theclass, baseclass) \

ptm_warning_disable \

const afx_msgmap* theclass::getmessagemap() const \

\const afx_msgmap* pascal theclass::getthismessagemap() \

\}; \

static const afx_msgmap messagemap = \

; \return &messagemap; \

}   \

ptm_warning_restore

關於 on_...型別的巨集就多了,下面我摘了(c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afxmsg_.h)下面一些我們很熟悉的**:

#define on_command(id, memberfxn) \

,// on_command(id, onbar) is the same as

//   on_control(0, id, onbar) or on_bn_clicked(0, id, onbar)

#define on_notify(wnotifycode, id, memberfxn) \

,// for general controls

#define on_control(wnotifycode, id, memberfxn) \

,#define on_wm_destroy() \

,#define on_wm_size() \

,又加了一些巨集,一步一步的看吧,ptm_warning_disable與ptm_warning_restore:

#define ptm_warning_disable \

__pragma(warning( push )) \

__pragma(warning( disable : 4867 ))

#define ptm_warning_restore \

__pragma(warning( pop ))

是處理警告的,貌似和我們的話題不符,就先不看了。

檢視 afxsig_end 定義:

enum afxsig

;afxsig 的含義暫時不講,稍後再說。

把幾個巨集分散開來,沒有整體效果。還是舉個例子吧:

declare_message_map()

end_message_map()

展開以後為:

protected: 

static const afx_msgmap* pascal getthismessagemap(); 

virtual const afx_msgmap* getmessagemap() const; 

const afx_msgmap* pascal ,,

};static const afx_msgmap messagemap = 

; return &messagemap; 

}仔細看上述**,會發現這和 rtti 一樣,還是乙個鍊錶。將子類的訊息對映表和父類的訊息對映表聯絡起來。

下圖為 mfc 訊息對映表:

訊息幫浦的開始

訊息傳遞方式

(1)直線上溯(一般 windows 訊息)

cwnd::windowproc 呼叫 onwndmsg 用來分辨並處理訊息;如果是命令訊息,交給 oncommand 處理,如果是通知訊息(notification),交給 onnotify 處理。而一般的 windows 訊息,就直接在訊息對映表中上溯,尋找其歸宿(訊息處理程式)。

下圖是wm_paint 訊息發生於 view 時,訊息傳遞路徑:

(2)拐彎上溯(wm_command命令訊息)

如果訊息是 wm_command ,cwnd::onwndmsg 另闢蹊徑,交流 oncommand 來處理。這並不一定是 cwnd::oncommand ,得視 this 指標指向哪一種物件而定。在 mfc 之中,以下類都改寫了 oncommand 函式;

class cwnd : public ccmdtarget

class cframewnd : public cframewnd

class cmdiframewnd : public cwnd

class csplitterwnd : public cwnd

class cpropertysheet : public cwnd

class colepropertypage : public cdialog 

下圖示出了 framewnd 視窗收到命令訊息後的四個嘗試路徑:

訊息對映和命令傳遞,大體上應該有了乙個了解。一些細節如「afxsig_xx 的奧秘」以及具體到程式的**,這是乙個極其複雜的過程,需要深厚的 windows 程式設計功底。而我覺得作為 mfc 普通使用者而言,了解到這裡就已經夠了。

MFC訊息對映與處理

今天我們主要了解一下mfc程式的訊息對映 mfc程式中訊息的種類 a 視窗訊息 window message 這種訊息一般與視窗的內部運作有關,如建立視窗 繪製視窗和銷毀視窗等。通常,訊息是從系統傳送到視窗,或從視窗傳送到視窗。形式通常為ww 不包括ww command 如 wm create,告訴...

MFC訊息對映與處理

declare message map 宣告訊息對映表 訊息對映表 begin message map cmyframewnd,cframewnd on wm paint 響應wm paint訊息 end message map 訊息響應函式 afx msg void onpaint 即處理訊息的函...

MFC訊息對映

run這個函式來建立和處理訊息迴圈 bool afxapi afxinternalpumpmessage return true 顯而易見,mfc中處理訊息也是利用了win32下的訊息處理 那麼還是這樣的結構 typedef struct tagmsg msg 有了這個概念之後我們知道,mfc通過訊...