何謂訊息、訊息處理函式、訊息對映?
訊息簡單的說就是指通過輸入裝置向程式發出指令要執行某個操作。具體的某個操作是你的一系列**。稱為訊息處理函式。在sdk中訊息其實非常容易理解,當視窗建立後便會有乙個函式(視窗處理函式)開始執行乙個訊息迴圈,我們還可以清楚的看到訊息處理的脈絡。乙個switch case語句就可以搞定,訊息迴圈直到遇到wm_quit訊息才會結束,其餘的訊息均被攔截後呼叫相應的處理函式。但在封裝了api的mfc中,訊息似乎變的有些複雜了,我們看不到熟悉的switch case語句了,取而代之的是乙個叫訊息對映的東西。為什麼mfc要引入訊息對映機制,你可以想象一下,在現在的程式開發活動中,你的乙個程式是否擁有多個窗體,主視窗就算只有乙個,那選單、工具條、控制項這些都是子視窗,那我們需要寫多少個switch case,並且還要為每個訊息分配乙個訊息處理函式,這樣做是多麼的複雜呀。因此mfc採用了一種新的機制。利用乙個陣列,將視窗訊息和相對應的訊息處理函式進行對映,你可以理解成這是乙個表。這種機制就是訊息對映。這張表在視窗基類cwnd定義,派生類的訊息對映表如果你沒有動作它是空的,也就是說如果你不手工的增加訊息處理函式,則當派生視窗接受乙個訊息時會執行父類的訊息處理函式。這樣做顯然是高效的。
mfc提供的訊息結構
同時mfc定義了下面的兩個主要結構:
afx_msgmap_entry
struct afx_msgmap_entry;
afx_msgmap
struct afx_msgmap;
///afx_msgmap可以得到基類的訊息對映入口位址和得到本身的訊息對映入口位址。
mfc下乙個訊息的處理過程是一般是這樣的。
1、_afxcbtfilterhook截獲訊息(這是乙個鉤子函式)
2、_afxcbtfilterhook把視窗過程設定為afxwndproc。
3、函式afxwndproc接收windows作業系統傳送的訊息。
4、函式afxwndproc呼叫函式afxcallwndproc進行訊息處理。
5、函式afxcallwndproc呼叫cwnd類的方法windowproc進行訊息處理。
如何新增自己的訊息?
我們已經了解了window的訊息機制,如何加入我們自己的訊息呢?好我們來看
乙個標準的訊息處理程式是這個樣子的
在 cwnd 類中預定義了標準 windows 訊息 (wm_***x wm是window message的縮寫) 的預設處理程式。類庫基於訊息名命名這些處理程式。例如,wm_paint 訊息的處理程式在 cwnd 中被宣告為:
afx_msg void onpaint();
afx_msg 關鍵字通過使這些處理程式區別於其他 cwnd 成員函式來表明 c++ virtual 關鍵字的作用。但是請注意,這些函式實際上並不是虛擬的,而是通過訊息對映實現的。我們在本文的一開始便說明了為什麼要這樣做。
所有能夠進行訊息處理的類都是基於ccmdtarget類的,也就是說ccmdtarget類是所有可以進行訊息處理類的父類。ccmdtarget類是mfc處理命令訊息的基礎和核心。
若要重寫基類中定義的處理程式,只需在派生類中定義乙個具有相同原型的函式,並建立此處理程式的訊息對映項。我們通過classwizard可以建立大多數視窗訊息或自定義的訊息,通過classwizard可以自動建立訊息對映,和訊息處理函式的框架,我們只需要把我們要做的事情填空,新增你要做的事情到處理函式。這個非常簡單,就不細說了。但是也許我們需要新增一些classwizard不支援的視窗訊息或自定義訊息,那麼就需要我們親自動手建立訊息對映和訊息處理的框架,通常步驟如下:
#define wm_mymessage (wm_user + 100)
第二步:實現訊息處理函式。該函式使用wpram和lparam引數並返回lpesult。
lpesult cmainframe::onmymessage(wparam wparam, lparam lparam)
第三步:在類標頭檔案的afx_msg塊中說明訊息處理函式:
// }afx_msg
declare_message_map()
第四步:在使用者類的訊息塊中,使用on_message巨集指令將訊息對映到訊息處理函式中。
on_message( wm_mymessage, onmymessage )
可以看出,使用者自定義的訊息和我們通過classwizard新增的訊息一樣,都是利用了on_message巨集,建立的訊息對映。
其實訊息類別可以分成多種,上面說的只是其中之一。有三種主要的訊息類別:(以下部分摘自msdn)
1、windows 訊息
此類訊息主要包括以字首 wm_ 開頭的訊息,wm_command 除外。windows 訊息由視窗和檢視處理。此類訊息往往帶有用於確定如何處理訊息的引數。
2、控制項通知
此類訊息包括從控制項和其他子視窗傳送到其父視窗的 wm_command 通知訊息。例如,當使用者在編輯控制項 (edit control) 中執行可能更改文字的操作後,該編輯控制項 (edit control) 將向其父級傳送包含 en_change 控制項通知**的 wm_command 訊息。該訊息的視窗處理程式以某種適當的方式響應此通知訊息,例如在控制項中檢索該文字。
框架像傳送其他 wm_ 訊息一樣傳送控制項通知訊息。但是有乙個例外的情況,即當使用者單擊按鈕時由按鈕傳送的 bn_clicked 控制項通知訊息。該訊息被作為命令訊息特別處理,並像其他命令一樣傳送。
3、命令訊息
此類訊息包括使用者介面物件(選單、工具欄按鈕和快捷鍵)發出的 wm_command 通知訊息。框架處理命令的方式與處理其他訊息不同,可以使用更多種類的物件處理命令。
windows 訊息和控制項通知訊息由視窗來處理(視窗是從 cwnd 類派生的類的物件)。包括 cframewnd、cmdiframewnd、cmdichildwnd、cview、cdialog 以及從這些基類派生的您自己的類。這些物件封裝了 hwnd——windows 視窗的控制代碼。
命令訊息可以由範圍更廣的物件(文件、文件模板以及應用程式物件本身)處理,而不僅僅由視窗和檢視處理。當某一命令直接影響到某個特定物件時,應當讓該物件處理此命令。例如,「檔案」選單中的「開啟」命令在邏輯上與應用程式相關聯:該應用程式接收到此命令時會開啟指定的文件。因此「開啟」命令的處理程式是應用程式類的成員函式。
命令訊息我們比較常見的便是選單項和工具條了,大家可以看到他的訊息對映巨集和視窗訊息不太一樣,一般的形式是這樣的
on_command(id,memberfxn)
第乙個引數是命令id,乙個id號對應乙個訊息處理,當然你可以讓多個id共用乙個處理函式。常見的應用例如:選單項開啟文件的id和工具條按鈕開啟文件的id同時使用乙個處理函式,或者直接將它們的id設成相同的。
on_control(en_change,id,memberfxn)
還有很多種訊息存在於mfc,巨集定義有區別,大家可以觸類旁通。
視窗訊息有上百個。你可以從msdn上查到wm_開頭的,或者檢視cwnd的成員函式,會給你列出很多,別忘了還有很多非視窗訊息。雷神無法一一列出,也沒有必要。大家查一下就行了。不過對一些常用的、新的控制項訊息和特殊的通知訊息我還是把他們列出幾個表,大家做個參考吧。
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...