下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
MFC中消息映射機(jī)制分析
摘要:MFC以層次結(jié)構(gòu)組織起來,比較龐雜,尤其是它的消息映射機(jī)制,更是涉及到很多底層的東西。本文通過對整個消息映射機(jī)制進(jìn)行系統(tǒng)的分析,可以幫助程序開發(fā)人員更好地了解MFC,進(jìn)行可視化編程。關(guān)鍵詞:消息驅(qū)動;消息映射;MFC程序設(shè)計1引言微軟公司提供的MFC基本類庫(MicrosoftFoundationClasses),是進(jìn)行可視化編程時使用最為流行的一個類庫。MFC封裝了大部分WindowsAPI函數(shù)和Windows控件,使得程序的開發(fā)變得簡單,極大的縮短了程序的開發(fā)周期。MFC獨創(chuàng)的Document/View框架結(jié)構(gòu),能夠?qū)⒐芾頂?shù)據(jù)的代碼和顯示數(shù)據(jù)的程序代碼分開,并且設(shè)計了一套方便的消息映射和命令傳遞機(jī)制,方便程序員的開發(fā)使用。其中消息映射機(jī)制本身比較龐大和復(fù)雜,對它的分析和了解無疑有助于我們寫出更為合理的高效的程序。這里我們分析一下MFC的消息映射機(jī)制,以了解MFC是如何對Windows的消息加以封裝,方便用戶的開發(fā)。2SDK下的消息機(jī)制實現(xiàn)首先,簡單回顧一下SDK下我們是如何進(jìn)行Windows的程序開發(fā)的。Windows程序的運行是依靠外部發(fā)生的事件來驅(qū)動的,事件由操作系統(tǒng)捕捉,以消息的形式進(jìn)入消息隊列,然后通過消息循環(huán)從隊列中不斷取出消息,送到對應(yīng)的窗口過程里處理。相對于DOS程序,Windows是以WinMain作為程序的入口點,以下就是一個簡化的Win32程序的主體,通過while語句實現(xiàn)消息循環(huán):WinMain(…){MSGmsg;RegisterClass(…);//注冊窗口類CreateWindow(…);
//創(chuàng)建窗口ShowWindow(…);
//顯示窗口UpdateWindow(…);While(GetMessage(&msg,…)){//消息循環(huán)TranslateMessage(…);DispatchMessage(…);}returnmsg.wParam;}其中,msg代表消息,程序是通過GetMessage函數(shù)從和某個線程相對應(yīng)的消息隊列里面把消息取出來并放到消息變量msg里面。然后TranslateMessage函數(shù)用來把鍵盤消息轉(zhuǎn)化并放到響應(yīng)的消息隊列里面,最后DispatchMessage函數(shù)把消息分發(fā)到相關(guān)的窗口過程去處理。窗口過程根據(jù)消息的類型對不同的消息進(jìn)行相關(guān)的處理。在SDK編程過程中,用戶需要在窗口過程中分析消息的類型及其參數(shù)的含義,然后做不同的處理,相對比較麻煩;而MFC把消息調(diào)用的過程給封裝起來,使用戶能夠通過ClassWizard方便的使用和處理Windows的各種消息。3MFC中的消息映射機(jī)制在MFC的框架結(jié)構(gòu)下,“消息映射”是通過巧妙的宏定義,形成一張消息映射表格來進(jìn)行的。這樣一旦消息發(fā)生,F(xiàn)ramework就可以根據(jù)消息映射表格來進(jìn)行消息映射和命令傳遞。首先在需要進(jìn)行消息處理的類的頭文件(.H)里,都會含有DECLARE_MESSAGE_MAP()宏,聲明該類擁有消息映射表格:classCscribbleDoc:publicCdocument{
…DECLARE_MESSAGE_MAP()};然后在類應(yīng)用程序文件(.CPP)實現(xiàn)這一表格BEGIN_MESSAGE_MAP(CInheritClass,CBaseClass)
//{{AFX_MSG_MAP(CInheritClass)ON_COMMAND(ID_EDIT_COPY,OnEditCopy)………
//}}AFX_MSG_MAPEND_MESSAGE_MAP()這里主要進(jìn)行消息映射的實現(xiàn),把它和消息處理函數(shù)聯(lián)系在一起。其中出現(xiàn)三個宏,第一個宏是BEGIN_MESSAGE_MAP有兩個參數(shù),分別是擁有消息表格的類,及其父類。第二個宏是ON_COMMAND,指定命令消息的處理函數(shù)名稱。第三個宏是END_MESSAGE_MAP()作為結(jié)尾符號。中間的奇怪符號//}}和//{{,是ClassWizard產(chǎn)生的,對程序無影響。觀察DECLARE_MESSAGE_MAP的定義:#defineDECLARE_MESSAGE_MAP()\private:\staticconstAFX_MESSAGE_ENTRY_messageEntries[];\protected:\staticAFX_DATAconstAFX_MSGMAPmessageMap;\virtualconstAFX_MSGMAP*GetMessageMap()const;\里面又包含了MFC新定義的兩個數(shù)據(jù)結(jié)構(gòu),如下:AFX_MSGMAP_ENTRYstructAFX_MSGMAP_ENTRY{
UINTnMessage;//windowsmessage
UINTnCode;
//controlcodeorWM_NOTIFYcode
UINTnID;//controlID(or0forwindowsmessages)
UINTnLastID;
//usedforentriesspecifyingarangeofcontrolid's
UINTnSig;
//signaturetype(action)orpointertomessage#
AFX_PMSGpfn;
//routinetocall(orspecialvalue)};和AFX_MSGMAPstructAFX_MSGMAP{
constAFX_MSGMAP*pBaseMap;
constAFX_MSGMAP_ENTRY*lpEntries;};其中AFX_MSGMAP_ENTRY結(jié)構(gòu)包含了一個消息的所有相關(guān)信息,而AFX_MSGMAP主要作用有兩個,一是用來得到基類的消息映射入口地址。二是得到本身的消息映射入口地址。實際上,MFC把所有的消息一條條填入到AFX_MSGMAP_ENTRY結(jié)構(gòu)中去,形成一個數(shù)組,該數(shù)組存放了所有的消息和與它們相關(guān)的參數(shù)。同時通過AFX_MSGMAP能得到該數(shù)組的首地址,同時得到基類的消息映射入口地址。當(dāng)本身對該消息不響應(yīng)的時候,就可以上溯到基類的消息映射表尋找對應(yīng)的消息響應(yīng)。現(xiàn)在我們來分析MFC是如何讓窗口過程來處理消息的,實際上所有MFC的窗口類都通過鉤子函數(shù)_AfxCbtFilterHook截獲消息,并且在鉤子函數(shù)_AfxCbtFilterHook中把窗口過程設(shè)定為AfxWndProc。原來的窗口過程保存在成員變量m_pfnSuper中。在MFC框架下,一般一個消息的處理過程是這樣的。(1)函數(shù)AfxWndProc接收Windows操作系統(tǒng)發(fā)送的消息。(2)函數(shù)AfxWndProc調(diào)用函數(shù)AfxCallWndProc進(jìn)行消息處理,這里一個進(jìn)步是把對句柄的操作轉(zhuǎn)換成對CWnd對象的操作。(3)函數(shù)AfxCallWndProc調(diào)用CWnd類的方法WindowProc進(jìn)行消息處理。(4)WindowProc調(diào)用OnWndMsg進(jìn)行正式的消息處理,即把消息派送到相關(guān)的方法中去處理。在CWnd類中都保存了一個AFX_MSGMAP的結(jié)構(gòu),而在AFX_MSGMAP結(jié)構(gòu)中保存有所有我們用ClassWizard生成的消息的數(shù)組的入口,我們把傳給OnWndMsg的message和數(shù)組中的所有的message進(jìn)行比較,找到匹配的那一個消息。實際上系統(tǒng)是通過函數(shù)AfxFindMessageEntry來實現(xiàn)的。找到了那個message,實際上我們就得到一個AFX_MSGMAP_ENTRY結(jié)構(gòu),而我們在上面已經(jīng)提到AFX_MSGMAP_ENTRY保存了和該消息相關(guān)的所有信息,其中主要是消息的動作標(biāo)識和相關(guān)的執(zhí)行函數(shù)。然后我們就可以根據(jù)消息的動作標(biāo)識調(diào)用相關(guān)的執(zhí)行函數(shù),而這個執(zhí)行函數(shù)實際上就是通過ClassWizard在類實現(xiàn)中定義的一個方法。這樣就把消息的處理轉(zhuǎn)化到類中的一個方法的實現(xiàn)上。(5)如果OnWndMsg方法沒有對消息進(jìn)行處理的話,就調(diào)用DefWindowProc對消息進(jìn)行處理。這是實際上是調(diào)用原來的窗口過程進(jìn)行缺省的消息處理。所以如果正常的消息處理的話,MFC窗口類是完全脫離了原來的窗口過程,用自己的一套體系結(jié)構(gòu)實現(xiàn)消息的映射和處理。即先調(diào)用MFC窗口類掛上去的窗口過程,再調(diào)用原先的窗口過程。用戶面對的消息參數(shù)將不再是固定的wParam和lParam,而是和消息類型具體相關(guān)的參數(shù)。比如和消息WM_LButtonDown相對應(yīng)的方法OnLButtonDown的兩個參數(shù)是nFlags和point。nFlags表示在按下鼠標(biāo)左鍵的時候是否有其他虛擬鍵按下,point更簡單,就是表示鼠標(biāo)的位置。同時MFC窗口類消息傳遞中還提供了兩個函數(shù),分別為WalkPreTranslateTree和PreTranslateMessage。我們知道利用MFC框架生成的程序,都是從CWinApp開始執(zhí)行的,而CWinapp實際繼承了CWinThread類。在CWinThread的運行過程中會調(diào)用窗口類中的WalkPreTranslateTree方法。而WalkPreTranslateTree方法實際上就是從當(dāng)前窗口開始查找愿意進(jìn)行消息翻譯的類,直到找到窗口沒有父類為止。在WalkPreTranslateTree方法中調(diào)用了PreTranslateMessage方法。實際上PreTranslateMessage最大的好處是我們在消息處理前可以在這個方法里面先做一些事情。舉一個簡單的例子,比如我們希望在一個CEdit對象里,把所有的輸入的字母都以大寫的形式出現(xiàn)。我們只需要
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 世說新語第二節(jié)讀后感
- 會計畢業(yè)生實習(xí)報告范文六篇
- 亂世佳人觀后感五篇
- bfr訓(xùn)練課件教學(xué)課件
- 航空航天用1100MPa MJ螺紋大六角頭螺栓 征求意見稿
- 星期詞匯課件教學(xué)課件
- 格斗術(shù)課件教學(xué)課件
- 慶云中學(xué)八年級上學(xué)期語文9月質(zhì)量監(jiān)測試卷
- 鐵路工務(wù)課件教學(xué)課件
- 水母手工課件教學(xué)課件
- 分層次教學(xué)與個性化輔導(dǎo)計劃
- 基于物聯(lián)網(wǎng)的農(nóng)業(yè)無人機(jī)高效配送方案
- 毛細(xì)支氣管炎護(hù)理查房課件
- EHS(環(huán)境健康安全)管理制度
- GB/T 10476-2024尿素高壓冷凝器技術(shù)條件
- 2024-2030年中國金融BPO行業(yè)市場發(fā)展分析及投資前景與策略研究報告
- 二年級《公共安全教育》全冊教學(xué)設(shè)計
- 2024-2025學(xué)年小學(xué)科學(xué)四年級下冊青島版(六三制2024)教學(xué)設(shè)計合集
- 2024版中國血脂管理指南
- 2022下半年四川省考公務(wù)員考試行測題及解析(三十二)
- (2024年)傳染病培訓(xùn)課件
評論
0/150
提交評論