MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制圖文小學(xué)教育_第1頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制圖文小學(xué)教育_第2頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制圖文小學(xué)教育_第3頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制圖文小學(xué)教育_第4頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制圖文小學(xué)教育_第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1/1MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制-圖文-小學(xué)教育

MFC的類層次結(jié)構(gòu)與運(yùn)行機(jī)制MFC的類層次結(jié)構(gòu)

如圖所示(子類指向父類):

其中:

CObject:是MFC供應(yīng)的絕大多數(shù)類的基類。該類完成動(dòng)態(tài)空間的安排與回收,支持一般的診斷、出錯(cuò)信息處理和文檔序列化等。

CCmdTarget:主要負(fù)責(zé)將系統(tǒng)大事(消息)和窗口大事(消息)發(fā)送給響應(yīng)這些大事的對(duì)象,完成消息發(fā)送、等待和派遣調(diào)度等工作,實(shí)現(xiàn)應(yīng)用程序的對(duì)象之間的協(xié)調(diào)運(yùn)行。

CWinApp:是應(yīng)用程序的主線程類,它是從CWinThread類派生而來(lái)的。CWinThread類用來(lái)完成對(duì)線程的掌握,包括線程的創(chuàng)建、運(yùn)行、終止和掛起等。

CDocument:是文檔類,包含了應(yīng)用程序在運(yùn)行期間所用到的數(shù)據(jù)。

CWnd:是一個(gè)通用的窗口類,用來(lái)供應(yīng)Windows中的全部通用特性、對(duì)話框和控件。CFrameWnd是從CWnd類繼承來(lái)的,并實(shí)現(xiàn)了標(biāo)準(zhǔn)的框架應(yīng)用程序。CDialog類用來(lái)掌握對(duì)話框窗口。CView:用于讓用戶通過(guò)窗口來(lái)訪問(wèn)文檔。

CMDIFrameWnd和CMDIChildWnd:分別用于多文檔應(yīng)用程序的主框架窗口和文檔子窗口的顯示和管理。CMiniFrameWnd類是一種簡(jiǎn)化的框架窗口,它沒(méi)有最大化和最小化窗口按鈕,也沒(méi)有窗口系統(tǒng)菜單,一般很少用到它。

MFC運(yùn)行機(jī)制

在程序中,當(dāng)定義一個(gè)類對(duì)象時(shí),它會(huì)自動(dòng)調(diào)用相應(yīng)的構(gòu)造函數(shù)。所謂\類對(duì)象\,就是用該類定義的\變量\,這個(gè)\變量\又稱為類的一個(gè)實(shí)例。例如,theApp就是類CSimpApp的一個(gè)對(duì)象。

MFC正是利用類的這種\自動(dòng)調(diào)用相應(yīng)的構(gòu)造函數(shù)\特性,使得WinMain函數(shù)的調(diào)用變成了應(yīng)用程序框架內(nèi)部的調(diào)用,所以我們?cè)诖a中看不到每個(gè)Windows程序所必需有的WinMain函數(shù)。

當(dāng)應(yīng)用程序運(yùn)行到\theApp;\時(shí),系統(tǒng)就會(huì)先調(diào)用基類CWinApp構(gòu)造函數(shù),進(jìn)行一系列的內(nèi)部初始化操作,然后自動(dòng)調(diào)用CSimpApp的虛函數(shù)InitInstance,該函數(shù)會(huì)進(jìn)一步調(diào)用相應(yīng)的函數(shù)來(lái)完成主窗口的構(gòu)造和顯示工作。下面來(lái)看看上述程序中InitInstance的執(zhí)行過(guò)程。首先執(zhí)行的是:

m_pMainWnd=newCMainFrame;

該語(yǔ)句用來(lái)創(chuàng)建從CFrameWnd類派生而來(lái)的用戶框架窗口CMainFrame類對(duì)象,繼而調(diào)用該類的構(gòu)造函數(shù),使得Create函數(shù)被調(diào)用,完成了窗口創(chuàng)建工作。

然后執(zhí)行后面兩句:

m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow;用作窗口的顯示和更新。接下來(lái)調(diào)用:

m_pMainWnd->MessageBox(\你好,歡迎進(jìn)入MFC世界!\最終返回TRUE,表示窗口創(chuàng)建勝利。

由于應(yīng)用程序類CWinApp是用來(lái)調(diào)用WinMain以及實(shí)例的初始化,因此每一個(gè)MFC應(yīng)用程序有且只能一個(gè)這樣的應(yīng)用程序類,且需要一個(gè)全局的對(duì)象實(shí)例,如上述程序中的theApp,當(dāng)然也可換一個(gè)對(duì)象名。InitInstance完成初始化工作之后,接下來(lái)就是調(diào)用基類CWinApp的成員函數(shù)Run,執(zhí)行應(yīng)用程序的消息循環(huán),即重復(fù)執(zhí)行接收消息并轉(zhuǎn)發(fā)消息的工作。當(dāng)Run檢查到消息隊(duì)列為空時(shí),將調(diào)用基類CWinApp的成員函數(shù)OnIdle進(jìn)行空閑時(shí)的后臺(tái)處理工作。若消息隊(duì)列為空且又沒(méi)有后臺(tái)工作要處理時(shí),則應(yīng)用程序始終處于等待狀態(tài),始終等到有消息為止。

當(dāng)程序結(jié)束后,調(diào)用基類CWinApp的成員函數(shù)ExitInstance,完成終止應(yīng)用程序的收尾工作。這就是MFC應(yīng)用程序的運(yùn)行機(jī)制。

MFC消息響應(yīng)機(jī)制分析

MFC是Windows下程序設(shè)計(jì)的最流行的一個(gè)類庫(kù),但是該類庫(kù)比較龐雜,尤其是它的消息映射機(jī)制,更是涉及到許多低層的東西,我們?cè)谶@里,對(duì)它的整個(gè)消息映射機(jī)制進(jìn)行了系統(tǒng)的分析,可以關(guān)心程序開(kāi)發(fā)人員對(duì)MFC的消息映射機(jī)制有一個(gè)比較透徹的了解。1.引言

VC++的MFC類庫(kù)實(shí)際上是Windows下C++編程的一套最為流行的類庫(kù)。MFC的框架結(jié)構(gòu)大大便利了程序員的編程工作,但是為了更加有效、敏捷的使用MFC編程,了解MFC的體系結(jié)構(gòu)往往可以使編程工作事半功倍。它合理的封裝了WIN32API函數(shù),并設(shè)計(jì)了一套便利的消息映射機(jī)制。但這套機(jī)制本身比較浩大和簡(jiǎn)單,對(duì)它的分析和了解無(wú)疑有助于我們寫(xiě)出更為合理的高效的程序。這里我們簡(jiǎn)潔的分析MFC的消息響應(yīng)機(jī)制,以了解MFC是如何對(duì)Windows的消息加以封裝,便利用戶的開(kāi)發(fā)。2.SDK下的消息機(jī)制實(shí)現(xiàn)

這里簡(jiǎn)潔的回顧一下SDK下我們是如何進(jìn)行Windows的程序開(kāi)發(fā)的。一般來(lái)說(shuō),Windows的消息都是和線程相對(duì)應(yīng)的。即Windows會(huì)把消息發(fā)送給和該消息相對(duì)應(yīng)的線程。在SDK的模式下,程序是通過(guò)GetMessage函數(shù)從和某個(gè)線程相對(duì)應(yīng)的消息隊(duì)列里面把消息取出來(lái)并放到一個(gè)特別的結(jié)構(gòu)里面,一個(gè)消息的結(jié)構(gòu)是一個(gè)如下的STRUCTURE。typedefstructtagMSG{HWNDhwnd;UINTmessage;WPARAMwParam;LPARAMlParam;DWORDtime;POINTpt;}MSG;

其中hwnd表示和窗口過(guò)程相關(guān)的窗口的句柄,message表示消息的ID號(hào),wParam和lParam表示和消息相關(guān)的參數(shù),time表示消息發(fā)送的時(shí)間,pt表示消息發(fā)送時(shí)的鼠標(biāo)的位置。

然后TranslateMessage函數(shù)用來(lái)把虛鍵消息翻譯成字符消息并放到響應(yīng)的消息隊(duì)列里面,最終DispatchMessage函數(shù)把消息分發(fā)到相關(guān)的窗口過(guò)程。然后窗口過(guò)程依據(jù)消息的類型對(duì)不同的消息進(jìn)行相關(guān)的處理。在SDK編程過(guò)程中,用戶需要在窗口過(guò)程中分析消息的類型和跟消息一起的參數(shù)的含義,做不同的處理,相對(duì)比較麻煩,而MFC把消息調(diào)用的過(guò)程給封裝起來(lái),使用戶能夠通過(guò)ClassWizard便利的使用和處理Windows的各種消息。3.MFC的消息實(shí)現(xiàn)機(jī)制

我們可以看到,在MFC的框架結(jié)構(gòu)下,可以進(jìn)行消息處理的類的頭文件里面都會(huì)含有

DECLARE_MESSAGE_MAP宏,這里主要進(jìn)行消息映射和消息處理函數(shù)的聲明??梢赃M(jìn)行消息處理的類的實(shí)現(xiàn)文件里一般都含有如下的結(jié)構(gòu)。

BEGIN_MESSAGE_MAP(CInheritClass,CBaseClass)//{{AFX_MSG_MAP(CInheritClass)//}}AFX_MSG_MAPEND_MESSAGE_MAP

這里主要進(jìn)行消息映射的實(shí)現(xiàn)和消息處理函數(shù)的實(shí)現(xiàn)。

全部能夠進(jìn)行消息處理的類都是基于CCmdTarget類的,也就是說(shuō)CCmdTarget類是全部可以進(jìn)行消息處理類的父類。CCmdTarget類是MFC處理命令消息的基礎(chǔ)和核心。同時(shí)MFC定義了下面的兩個(gè)主要結(jié)構(gòu):

AFX_MSGMAP_ENTRYstructAFX_MSGMAP_ENTRY{

UINTnMessage;//windowsmessage

UINTnCode;//controlcodeorWM_NOTIFYcodeUINTnID;

//controlID(or0forwindowsmessages)UINTnLastID;

//usedforentriesspecifyingarangeofcontrolid'sUINTnSig;

//signaturetype(action)orpointertomessage#AFX_PMSGpfn;//routinetocall(orspecialvalue)};

和AFX_MSGMAPstructAFX_MSGMAP{

#ifdef_AFXDLL

constAFX_MSGMAP*(PASCAL*pfnGetBaseMap);#else

constAFX_MSGMAP*pBaseMap;#endif

constAFX_MSGMAP_ENTRY*lpEntries;};

其中AFX_MSGMAP_ENTRY結(jié)構(gòu)包含了一個(gè)消息的全部相關(guān)信息,其中nMessage為Windows消息的ID號(hào)nCode為掌握消息的通知碼nID為Windows掌握消息的ID

nLastID表示假如是一個(gè)指定范圍的消息被映射的話,nLastID用來(lái)表示它的范圍。nSig表示消息的動(dòng)作標(biāo)識(shí)

AFX_PMSGpfn它實(shí)際上是一個(gè)指向和該消息相應(yīng)的執(zhí)行函數(shù)的指針。

而AFX_MSGMAP主要作用是兩個(gè),一:用來(lái)得到基類的消息映射入口地址。二:得到本身的消息映射入口地址。

實(shí)際上,MFC把全部的消息一條條填入到AFX_MSGMAP_ENTRY結(jié)構(gòu)中去,形成一個(gè)數(shù)組,該數(shù)組存放了全部的消息和與它們相關(guān)的參數(shù)。同時(shí)通過(guò)AFX_MSGMAP能得到該數(shù)組的首地址,同時(shí)得到基類的消息映射入口地址,這是為了當(dāng)本身對(duì)該消息不響應(yīng)的時(shí)候,就調(diào)用其基類的消息響應(yīng)。

現(xiàn)在我們來(lái)分析MFC是如何讓窗口過(guò)程來(lái)處理消息的,實(shí)際上全部MFC的窗口類都通過(guò)鉤子函數(shù)_AfxCbtFilterHook截獲消息,并且在鉤子函數(shù)_AfxCbtFilterHook中把窗口過(guò)程設(shè)定為AfxWndProc。原來(lái)的窗口過(guò)程保存在成員變量m_pfnSuper中。

所以在MFC框架下,一般一個(gè)消息的處理過(guò)程是這樣的。函數(shù)AfxWndProc接收Windows操作系統(tǒng)發(fā)送的消息。

函數(shù)AfxWndProc調(diào)用函數(shù)AfxCallWndProc進(jìn)行消息處理,這里一個(gè)進(jìn)步是把對(duì)句柄的操作轉(zhuǎn)換成對(duì)CWnd對(duì)象的操作。

函數(shù)AfxCallWndProc調(diào)用CWnd類的方法WindowProc進(jìn)行消息處理。留意AfxWndProc和AfxCallWndProc都是AFX的API函數(shù)。而WindowProc已經(jīng)是CWnd的一個(gè)方法。所以可以留意到在WindowProc中已經(jīng)沒(méi)有關(guān)于句柄或者是CWnd的參數(shù)了。

方法WindowProc調(diào)用方法OnWndMsg進(jìn)行正式的消息處理,即把消息派送到相關(guān)的方法中去處理。消息是如何派送的呢?實(shí)際上在CWnd類中都保存了一個(gè)AFX_MSGMAP的結(jié)構(gòu),而在AFX_MSGMAP結(jié)構(gòu)中保存有全部我們用ClassWizard生成的消息的數(shù)組的入口,我們把傳給OnWndMsg的message和數(shù)組中的全部的message進(jìn)行比較,找到匹配的那一個(gè)消息。實(shí)際上系統(tǒng)是通過(guò)函數(shù)AfxFindMessageEntry來(lái)實(shí)現(xiàn)的。找到了那個(gè)message,實(shí)際上我們就得到一個(gè)AFX_MSGMAP_ENTRY結(jié)構(gòu),而我們?cè)谏厦嬉呀?jīng)提到

AFX_MSGMAP_ENTRY保存了和該消息相關(guān)的全部信息,其中主要的是消息的動(dòng)作標(biāo)識(shí)和跟消息相關(guān)的執(zhí)行函數(shù)。然后我們就可以依據(jù)消息的動(dòng)作標(biāo)識(shí)調(diào)用相關(guān)的執(zhí)行函數(shù),而這個(gè)執(zhí)行函數(shù)實(shí)際上就是通過(guò)ClassWizard在類實(shí)現(xiàn)中定義的一個(gè)方法。這樣就把消息的處理轉(zhuǎn)化到類中的一個(gè)方法的實(shí)現(xiàn)上。舉一個(gè)簡(jiǎn)潔的例子,比如在View中對(duì)WM_LButtonDown消息的處理就轉(zhuǎn)化成對(duì)如下一個(gè)方法的操作。voidCInheritView::OnLButtonDown(UINTnFlags,CPointpoint){

//TODO:Addyourmessage

handlercodehereand/orcalldefaultCView::OnLButtonDown(nFlags,point);}

留意這里CView::OnLButtonDown(nFlags,point)實(shí)際上就是調(diào)用CWnd的Default方法。而Default方法所做的工作就是調(diào)用DefWindowProc對(duì)消息進(jìn)行處理。這實(shí)際上是調(diào)用原來(lái)的窗口過(guò)程進(jìn)行缺省的消息處理。

假如OnWndMsg方法沒(méi)有對(duì)消息進(jìn)行處理的話,就調(diào)用DefWindowProc對(duì)消息進(jìn)行處理。這是實(shí)際上是調(diào)用原來(lái)的窗口過(guò)程進(jìn)行缺省的消息處理。

所以假如正常的消息處理的話,MFC窗口類是完全脫離了原來(lái)的窗口過(guò)程,用自己的一套體系結(jié)構(gòu)實(shí)現(xiàn)消息的映射和處理。即先調(diào)用MFC窗口類掛上去的窗口過(guò)程,再調(diào)用原先的窗口過(guò)程。并且用戶面對(duì)和消息相關(guān)的參數(shù)不再是死板的wParam和lParam,而是和消息類型詳細(xì)相關(guān)的參數(shù)。比如和消息WM_LbuttonDown相對(duì)應(yīng)的方法OnLButtonDown的兩個(gè)參數(shù)是nFlags和point。nFlags表示在按下鼠標(biāo)左鍵的時(shí)候是否有其他虛鍵按下,point更簡(jiǎn)潔,就是表示鼠標(biāo)的位置。

同時(shí)MFC窗口類消息傳遞中還供應(yīng)了兩個(gè)函數(shù),分別為WalkPreTranslateTree和

PreTranslateMessage。我們知道利用MFC框架生成的程序,都是從CWinApp開(kāi)頭執(zhí)行的,而CWinapp實(shí)際繼承了CWinThread類。在CWinThread的運(yùn)行過(guò)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論