今天重新整理mfc的訊息機制,最終的結果應該是利用win32程式模擬乙個mfc的訊息鏈。
1.標準訊息
除wm_command之外,所有以wm_開頭的訊息。 從cwnd派生的類,都可以接收到這類訊息。
2.命令訊息
來自選單、加速鍵或工具欄按鈕的訊息。這類訊息都以wm_command呈現。在mfc中,通過選單項的標識(id)來區分不同的命令訊息;在sdk中,通過訊息的wparam引數識別。 ccmdtarget派生的類,都可以接收到這類訊息。
3.通告訊息
由控制項產生的訊息,例如,按鈕的單擊,列表框的選擇等均產生此類訊息,為的是向其父視窗(通常是對話方塊)通知事件的發生。這類訊息也是以wm_command形式呈現。 例如當你在listbox上選擇其中乙個專案,listbox就會產生lbn_selchange傳送給父視窗。從ccmdtarget派生的類,都可以接收到這類訊息。
萬流歸宗 command target(ccmdtarget)
在mfc中,我們可以找到如下三個巨集
1、declare_massage_map()
2、begine_massage_map(class, bassclass)
3、end_massage_map()
下面來分析這三個巨集
1 declare_message_map()
作用:為乙個訊息響應類宣告必需的成員變數和成員函式。
#define declare_message_map()
private:
static const afx_msgmap_entry _messageentries;
protected:
static const afx_msgmap messagemap;
virtual const afx_msgmap* getmessagemap() const;
可以看出declare_message_map() 巨集中定義了兩個靜態成員函式和乙個過載的虛函式
afx_msgmap_entry 根據題意,可以看出這是乙個訊息入口(訊息和訊息函式之間的對映)
struct afx_msgmap_entry
;再看看afx_message結構
struct afx_msgmap
;可見結構體afx_msgmap中定義了兩個指標,pbasemap指向另乙個afx_msgmap,lpentries指向乙個訊息入口表。可以推想,在響應訊息時,一定是在lpentries指向的訊息入口表中尋找響應函式,也可能會在pbasemap指向的結構體中做同樣的響應函式尋找操作(有點不理解)。
過載的虛函式getmessagemap,可以猜測只是用來返回成員messagemap的位址而已
2 begin_messgae_map(class, baseclass)
作用:定義declare_message_map巨集宣告的靜態變數。
#define begin_message_map(theclass, baseclass)
const afx_msgmap* theclass::getmessagemap() const
afx_comdat const afx_msgmap theclass::messagemap =
; afx_comdat const afx_msgmap_entry theclass::_messageentries =
然後初始化了當前類的成員變數messagemap。messagemap的pbasemap指標指向其父類的messagemap成員,lpentries指標指向當前類的_messageentries陣列的首位址。
afx_comdat const afx_msgmap theclass::messagemap =
;最後,定義了_messageentries陣列初始化**的開始部分。
afx_comdat const afx_msgmap_entry theclass::_messageentries =
}; 在declare_message_map和end_message_map之間還有一些巨集,如on_command、on_wm_create等,這些巨集最終都會被生成一條afx_msgmap_entry結構體資料,並成為_messageentries訊息對映表資料的乙個元素。我們以常見的on_command巨集為例。on_command巨集的源**為:
#define on_command(id, memberfxn)
,通過以上分析,我們可以得到乙個鍊錶式的資料結構,子類的messagemap成員為鍊錶的頭節點。鍊錶的每個節點都包含乙個訊息入口表。mfc的訊息系統的標準備訊息處理函式ccmdtarget::oncmdmsg正是通過這樣乙個鍊錶查詢到訊息的響應函式,並呼叫該函式來響應訊息。
假設有這樣的檢視類class ctestmfcview : public cview,裡面有乙個訊息響應函式:onmenutest,則展開巨集後,標頭檔案形如:
class ctestmfcview : public cview
afx_comdat afx_datadef const afx_msgmap ctestmfcview::messagemap =
; afx_comdat const afx_msgmap_entry ctestmfcview::_messageentries = ,
}; void ctestmfcview::onmenutest()
由以上**即可發現,實際上程式通過虛函式得到本類的指標afx_msgmap,而這個指標包含兩個值,乙個是指向基類的afx_msgmap*,乙個是指向本類函式入口的指標afx_msgmap_entry*,這樣,當程式執行到cwnd::onwndmsg()裡面,通過如下**:
const afx_msgmap* pmessagemap;
pmessagemap = getmessagemap();//注意,此為虛函式,實際呼叫的為各子類的函式
即可得到當前類的afx_msgmap* ,然後在ccmdtarget::oncmdmsg中通過以下**:
const afx_msgmap_entry* lpentry;
lpentry = afxfindmessageentry(pmessagemap->lpentries, nmsg, ncode, nid);可找到訊息函式的入口位址,至此便可呼叫函式onmenutest()了(呼叫此函式是通過函式指標實現)。
在mfc訊息流中,還有訊息的上溯,拐彎等一系列的變化,這些還需要進一步深入研究。
MFC 訊息機制
windows應用程式是通過訊息驅動的,在mfc軟體開發時,進行介面操作經常要用到訊息,通過訊息對應的處理函式來實現響應的操作。比如,使用者操作視窗,就會產生訊息,送給對應的訊息處理函式進行處理,對使用者的操作做出一些反應。mfc使用訊息對映機制來處理訊息,具體表現就是訊息和訊息處理函式一一對應的訊...
MFC訊息機制
一 訊息的分類 1 佇列訊息 非佇列訊息 l佇列訊息 windows 為每個應用程式都建立乙個訊息佇列,那麼通過訊息佇列,進行傳送的訊息都屬於佇列訊息 一般來說,由滑鼠 鍵盤產生的訊息都屬於佇列訊息。為什麼呢?想想,滑鼠 鍵盤事件都是由系統捕獲的,系統捕獲後要傳遞給應用程式,就一定的通過訊息佇列 l...
MFC的訊息機制
note 一般用postthreadmessage函式傳送執行緒之間的訊息,他和視窗訊息不同,需要指定執行緒id,訊息被系統放入到目標執行緒的訊息佇列中 用on thread message message,memberfxn 巨集可以對映執行緒訊息和他的處理函式。這個巨集必須在應用程式類 從cwi...