




下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、MFC勺類層次結(jié)構(gòu)與運(yùn)行機(jī)制MFC勺類層次結(jié)構(gòu)如圖所示(子類指向父類):其中:CObject:是MFCI供的絕大多數(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è)
2、通用的窗口類,用來(lái)提供Windows中的所有通用特性、對(duì)話框和控件。CFrameWn雇從CWn談繼承來(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)菜單,一般很少用到它。MF定行機(jī)制在程序中,當(dāng)定義一個(gè)類對(duì)象時(shí),它會(huì)自動(dòng)調(diào)用相應(yīng)的構(gòu)造函數(shù)。所謂"類對(duì)象",就是用該類定義的“變量",這個(gè)"變
3、量"又稱為類的一個(gè)實(shí)例。例如,theApp就是類CSimpApp的一個(gè)對(duì)象。MFCE是利用類的這種"自動(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)行到"CSimpApptheApp;"時(shí),系統(tǒng)就會(huì)先調(diào)用基類CWinApp勾造函數(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)看看上述程序中InitIn
4、stance的執(zhí)行過(guò)程。首先執(zhí)行的是:m_pMainWnd=newCMainFrame;該語(yǔ)句用來(lái)創(chuàng)建從CFrameWn酸派生而來(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)入MFCS界!");最后返回TRUE表示窗口創(chuàng)建成功。由于應(yīng)用程序類CWinApp是用來(lái)調(diào)用
5、WinMain以及實(shí)例的初始化,因此每一個(gè)MFC用程序有且只能一個(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(),完成終止
6、應(yīng)用程序的收尾工作。這就是MFC用程序的運(yùn)行機(jī)制。:nl.i#indowl'rot泊Mil也射Rg111ectChi1dXfdify其他OnCmri.MsK消息處理函數(shù)MFC處埋消息流程;nrini!iwh-w;-IOnNotifwWMVOTIFY(10(JnCrod,gAfxWndCalIPrciiOnConuiandOnW'ndWssUriCiiidHsgMFQ肖息響應(yīng)機(jī)制分析-MFC是Windows下程序設(shè)計(jì)的最流行的一個(gè)類庫(kù),但是該類庫(kù)比較龐雜,尤其是它的消息映射機(jī)制,更是涉及到很多低層的東西,我們?cè)谶@里,對(duì)它的整個(gè)消息映射機(jī)制進(jìn)行了系統(tǒng)的分析,可以幫助程序開(kāi)發(fā)人員對(duì)M
7、FC的消息映射機(jī)制有一個(gè)比較透徹的了解。1. 引言-VC+勺MF屢?guī)鞂?shí)際上是Windows下C+編程的一套最為流行的類庫(kù)。MFC勺框架結(jié)構(gòu)大大方便了程序員的編程工作,但是為了更加有效、靈活的使用MF編程,了解MFC的體系結(jié)構(gòu)往往可以使編程工作事半功倍。它合理的封裝了WIN32API函數(shù),并設(shè)計(jì)了一套方便的消息映射機(jī)制。但這套機(jī)制本身比較龐大和復(fù)雜,對(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的程
8、序開(kāi)發(fā)的。一般來(lái)說(shuō),Windows的消息者B是和線程相對(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è)如下的STRUCTUREtypedefstructtagMSGHWNDhwnd;UINTmessage;WPARAMwParam;LPARAMlParam;DWORDtime;POINTpt;MSG;- -其中hwnd表示和窗口過(guò)程相關(guān)的窗口的句柄,message表示消息的ID號(hào),wParam和lParam表示和消息相關(guān)的參數(shù),time表示消
9、息發(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ì)比較麻煩,而MFCm消息調(diào)用的過(guò)程給封裝起來(lái),使用戶能夠通過(guò)ClassWizard方便的使用和處理Windows的各種消息。3. MFC的消息實(shí)現(xiàn)機(jī)制-我們可以看到,在MFC的框架結(jié)構(gòu)下,可以進(jìn)行消息處理的類的頭文件里面都會(huì)含有DECLA
10、RE_MESSAGE_MAP(運(yùn)里主要進(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類是MFO理命令消息的基礎(chǔ)和核心。- -同時(shí)MFC義了下面的兩個(gè)主要結(jié)構(gòu):A
11、FX_MSGMAP_ENTRYstructAFX_MSGMAP_ENTRY(UINTnMessage;/windowsmessageUINTnCode;/controlcodeorWM_NOTIFYcodeUINTnID;/controlID(or0forwindowsmessages)UINTnLastID;/usedforentriesspecifyingarangeofcontrolid'sUINTnSig;/signaturetype(action)orpointertomessage#AFX_PMSGpfn;/routinetocall(orspecialvalue);和AF
12、X_MSGMAPstructAFX_MSGMAP(#ifdef_AFXDLLconstAFX_MSGMAP*(PASCAL*pfnGetBaseMap)();#elseconstAFX_MSGMAP*pBaseMap;#endifconstAFX_MSGMAP_ENTRY*lpEntries;其中AFX_MSGMAP_ENTRY包含了一個(gè)消息的所有相關(guān)信息,其中nMessage為Windows消息的ID號(hào)nCode為控制消息的通知碼nID為Windows控制消息的IDnLastID表示如果是一個(gè)指定范圍的消息被映射的話,nLastID用來(lái)表示它的范圍。nSig表示消息的動(dòng)作標(biāo)識(shí)AFX_PMSG
13、pfn它實(shí)際上是一個(gè)指向和該消息相應(yīng)的執(zhí)行函數(shù)的指針。- -而AFX_MSGMAP要作用是兩個(gè),一:用來(lái)得到基類的消息映射入口地址。二:得到本身的消息映射入口地址。- -實(shí)際上,MFCS所有的消息一條條填入到AFX_MSGMAP_ENTRY中去,形成一個(gè)數(shù)組,該數(shù)組存放了所有的消息和與它們相關(guān)的參數(shù)。同時(shí)通過(guò)AFX_MSGM/f睛到該數(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ù)_Af
14、xCbtFilterHook中把窗口過(guò)程設(shè)定為AfxWndProc。原來(lái)的窗口過(guò)程保存在成員變量m_pfnSuper中。- -所以在MFCf架下,一般一個(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)用CWn談的方法WindowProc進(jìn)行消息處理。注意AfxWndProc和AfxCallWndProc都是AFX的API函數(shù)。而WindowProc已經(jīng)是CWnd勺一個(gè)方法。所以可以注意到在Wi
15、ndowProc中已經(jīng)沒(méi)有關(guān)于句柄或者是CWnd的參數(shù)了。方法WindowProc調(diào)用方法OnWndMs進(jìn)行正式的消息處理,即把消息派送到相關(guān)的方法中去處理。消息是如何派送的呢?實(shí)際上在CWn強(qiáng)中都保存了一個(gè)AFX_MSGMAP吉構(gòu),而在AFX_MSGMAP構(gòu)中保存有所有我們用ClassWizard生成的消息的數(shù)組的入口,我們把傳給OnWndMsgmessage和數(shù)組中的所有的message進(jìn)行比較,找到匹配的那一個(gè)消息實(shí)際上系統(tǒng)是通過(guò)函數(shù)AfxFindMessageEntry來(lái)實(shí)現(xiàn)的。找到了那個(gè)message,實(shí)際上我們就得到一個(gè)AFX_MSGMAP_ENTRY,而我們?cè)谏厦嬉呀?jīng)提到AFX_
16、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_LButtonDowrf肖息的處理就轉(zhuǎn)化成對(duì)如下一個(gè)方法的操作。voidCInheritView:OnLButtonDown(UINTnFlags,CPointpoint)/TODO:Addyourmessagehandlercodehereand/orcalldefaultCVi
17、ew: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)行缺省的消息處理。如果OnWndMs市法沒(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)用MFCW口
18、類掛上去的窗口過(guò)程,再調(diào)用原先的窗口過(guò)程。并且用戶面對(duì)和消息相關(guān)的參數(shù)不再是死板的wParam和lParam,而是和消息類型具體相關(guān)的參數(shù)。比如和消息WM_LbuttonDowWll對(duì)應(yīng)的方法OnLButtonDown的兩個(gè)參數(shù)是nFlags和point。nFlags表示在按下鼠標(biāo)左鍵的時(shí)候是否有其他虛鍵按下,point更簡(jiǎn)單,就是表示鼠標(biāo)的位置。- -同時(shí)MFC®口類消息傳遞中還提供了兩個(gè)函數(shù),分別為WalkPreTranslateTree和PreTranslateMessage。我們知道利用MFC匡架生成的程序,都是從CWinApp開(kāi)始執(zhí)行的,而CWinapp實(shí)際繼承了CWinT
19、hread類。在CWinThread的運(yùn)行過(guò)程中會(huì)調(diào)用窗口類中的WalkPreTranslateTree方法。而WalkPreTranslateTree方法實(shí)際上就是從當(dāng)前窗口開(kāi)始查找愿意進(jìn)行消息翻譯的類,直到找到窗口沒(méi)有父類為止。在WalkPreTranslateTree方法中調(diào)用了PreTranslateMessage方法。實(shí)際上PreTranslateMessage最大的好處是我們?cè)谙⑻幚砬翱梢栽谶@個(gè)方法里面先做一些事情。舉一個(gè)簡(jiǎn)單的例子,比如我們希望在一個(gè)CEdit對(duì)象里,把所有的輸入的字母都以大寫(xiě)的形式出現(xiàn)。我們只需要在PreTranslateMessage方法中判斷message
20、是否為WM_CHAR,果是的話,把wParam俵示鍵值)由小寫(xiě)字母的值該為大寫(xiě)字母的值就實(shí)現(xiàn)了這個(gè)功能。- -繼續(xù)上面的例子,根據(jù)我們對(duì)MFC?肖息機(jī)制的分析,我們很容易得到除了上面的方法,我們至少還可以在另外兩個(gè)地方進(jìn)行操作。一一:在消息的處理方法里面即OnChar中,當(dāng)然最后我們不再調(diào)用CEdit:OnChar(nChar,nRepCnt,nFlags),而是直接調(diào)用DefWindowProc(WM_CHAR,nChar,MAKELPARAM(nRepCnt,nFlags)>因?yàn)閺奈覀兩厦娴姆治隹梢灾繡Edit:OnChar(nChar,nRepCnt,nFlags)實(shí)際上也就是對(duì)
21、DefWindowProc方法的調(diào)用。-二:我們可以直接重載DefWindowProc方法,對(duì)message類型等于WM_CHA,直接彳改nChar的值即可。4.小結(jié)-通過(guò)對(duì)MF陵庫(kù)的分析和了解,不僅能夠使我們更好的使用MF屢?guī)?,同時(shí),對(duì)于我們自己設(shè)計(jì)和實(shí)現(xiàn)框架和類,無(wú)疑也有相當(dāng)大的幫助。二.MFC的消息映射機(jī)制MFC勺設(shè)計(jì)者們?cè)谠O(shè)計(jì)MFCM,緊緊把握一個(gè)目標(biāo),那就是盡可能使得MFC的代碼要小,速度盡可能快。為了這個(gè)目標(biāo),他們使用了許多技巧,其中很多技巧體現(xiàn)在宏的運(yùn)用上,實(shí)現(xiàn)MFC勺消息映射的機(jī)制就是其中之一。同MFC1息映射機(jī)制有關(guān)的宏有下面幾個(gè):DECLARE_MESSAGE_M原()BE
22、GIN_MESSAGE_MAP(theClass,baseClass)和END_MESSAGE_MAP()弄懂mfj肖息映射機(jī)制的最好辦法是將找出一個(gè)具體的實(shí)例,將這些宏展開(kāi),并找出相關(guān)的數(shù)據(jù)結(jié)構(gòu)。DECLARE_MESSAGE_MAP()DECLARE_MESSAGE_MAP初定義如下:#defineDECLARE_MESSAGE_MAP()private:staticconstAFX_MSGMAP_ENTRY_messageEntries;protected:staticAFX_DATAconstAFX_MSGMAPmessageMap;virtualconstAFX_MSGMAP*Get
23、MessageMap()const;從上面的定義可以看出,DECLARE_MESSAGE_MAP()面三件事:定義一個(gè)長(zhǎng)度不定的靜態(tài)數(shù)組變量_messageEntries口;定義一個(gè)靜態(tài)變量messageMap定義一個(gè)虛擬函數(shù)GetMessageMap();在DECLARE_MESSAGE_MAP(),涉及至|JMF計(jì)兩個(gè)對(duì)外不公開(kāi)的數(shù)據(jù)結(jié)構(gòu)AFX_MSGMAP_ENTRYFX_MSGMAP?了弄清楚消息映射,有必要考察一下這兩個(gè)數(shù)據(jù)結(jié)構(gòu)的定義。AFX_MSGMAP_ENTRY義structAFX_MSGMAP_ENTRYUINTnMessage;/windowsmessageUINTnCod
24、e;/controlcodeorWM_NOTIFYcodeUINTnID;/controlID(or0forwindowsmessages)UINTnLastID;/usedforentriesspecifyingarangeofcontrolid'sUINTnSig;/signaturetype(action)orpointertomessage#AFX_PMSGpfn;/routinetocall(orspecialvalue);結(jié)構(gòu)中各項(xiàng)的含義注釋已經(jīng)說(shuō)明得很清楚了,這里不再多述,從上面的定義你是否看出,AFX_MSGMAP_ENTRY結(jié)構(gòu)實(shí)際上定義了消息和處理此消息的動(dòng)作之間的
25、映射關(guān)系。因此靜態(tài)數(shù)組變量_messageEntries口實(shí)際上定義了一張表,表中的每一項(xiàng)指定了相應(yīng)的對(duì)象所要處理的消息和處理此消息的函數(shù)的對(duì)應(yīng)關(guān)系,因而這張表也稱為消息映射表。再看看AFX_MSGMAP定義。(2)AFX_MSGMAP定義structAFX_MSGMAP(constAFX_MSGMAP*pBaseMap;constAFX_MSGMAP_ENTRY*IpEntries;);不難看出,AFX_MSGMAP義了一單向鏈表,鏈表中每一項(xiàng)的值是一指向消息映射表的指針(實(shí)際上就是_messageEntries的值)。通過(guò)這個(gè)鏈表,使得在某個(gè)類中調(diào)用基類的的消息處理函數(shù)很容易,因此,“父類
26、的消息處理函數(shù)是子類的缺省消息處理函數(shù)”就“順理成章”了。在后面的“MFC窗口的消息處理”一節(jié)中會(huì)對(duì)此作詳細(xì)的講解。由上述可見(jiàn),在類的頭文件中主要定義了兩個(gè)數(shù)據(jù)結(jié)構(gòu):消息映射表和單向鏈表。(孫建東總結(jié))BEGIN_MESSAGE_MAP()END_MESSAGE_MAP()它們的定義如下:#defineBEGIN_MESSAGE_MAP(theClass,baseClass)constAFX_MSGMAP*theClass:GetMessageMap()constreturn&theClass:messageMap;AFX_COMDATAFX_DATADEFconstAFX_MSGMA
27、PtheClass:messageMap=&baseClass:messageMap,&theClass:_messageEntries0;AFX_COMDATconstAFX_MSGMAP_ENTRYtheClass:_messageEntries口=#defineEND_MESSAGE_MAP()0,0,0,0,AfxSig_end,(AFX_PMSG)0;對(duì)應(yīng)BEGIN_MESSAGE_MAP(相義可能不是一下子就看得明白,不過(guò)不要緊,舉一例子就很清楚了。對(duì)于BEGIN_MESSAGE_MAP(CView,CWnd,C預(yù)編譯器將其展開(kāi)成下面的形式:constAFX_MSG
28、MAP*CView:GetMessageMap()constreturn&CView:messageMap;AFX_COMDATAFX_DATADEFconstAFX_MSGMAPCView:messageMap=&CWnd:messageMap,&CView:_messageEntries0;AFX_COMDATconstAFX_MSGMAP_ENTRYCView:_messageEntries口=至于END_MESSAGE_MAP(不過(guò)定義了一個(gè)表示映射表結(jié)束的標(biāo)志項(xiàng),我想大家對(duì)于這種簡(jiǎn)單的技巧應(yīng)該是很熟悉的,無(wú)需多述。到此為止,我想大家也已經(jīng)想到了象ON_COMM
29、A幽的宏的具體作用了,不錯(cuò)它們只不過(guò)定義了一種類型的消息映射項(xiàng),看看ON_COMMANtt義:#defineON_COMMAND(id,memberFxn)WM_COMMAND,CN_COMMAND,(WORD)id,(WORD)id,AfxSig_vv,(AFX_PMSG)&memberFxn,根據(jù)上面的定義,ON_COMMAND(ID_FILE_NEW,OnFileNew)被VC預(yù)編譯器展開(kāi)如下:WM_COMMAND,CN_COMMAND,(WORD)id,(WORD)id,AfxSig_vv,(AFX_PMSG)&OnFileNew,到此,MFC的消息映射機(jī)制已經(jīng)清楚了,
30、現(xiàn)在提出并解答兩個(gè)問(wèn)題以作為對(duì)這一節(jié)的小結(jié)。為什么不直接使用虛擬函數(shù)實(shí)現(xiàn)消息處理函數(shù)呢?這是一個(gè)GOODQUESTKONtf面已經(jīng)說(shuō)過(guò),MFC勺設(shè)計(jì)者們?cè)谠O(shè)計(jì)MFC寸有一個(gè)很明確的目標(biāo),就是使得“MFC的代碼盡可能小,速度盡可能快”,如果采用虛擬函數(shù),那么對(duì)于所有的窗口消息,都必須有一個(gè)與之對(duì)應(yīng)的虛擬函數(shù),因而對(duì)每一個(gè)從CWn族生的類而言,都會(huì)有一張很大的虛擬函數(shù)表vtbl。但是在實(shí)際應(yīng)用中,一般只對(duì)少數(shù)的消息進(jìn)行處理,大部分都交給系統(tǒng)缺省處理,所以表中的大部分項(xiàng)都是無(wú)用項(xiàng),這樣做就浪費(fèi)了很多內(nèi)存資源,這同MFC殳計(jì)者們的設(shè)計(jì)目標(biāo)是相違背的。當(dāng)然,MFC所使用的方法只是解決這類問(wèn)題的方式之一,
31、不排除還有其他的解決方式,但就我個(gè)人觀點(diǎn)而言,這是一種最好的解決方式,體現(xiàn)了很高的技巧性,值得我們學(xué)習(xí)。至于這第二個(gè)問(wèn)題,是由上面的問(wèn)題引申出來(lái)的。如果在子類和父類中出現(xiàn)了相同的消息出來(lái)函數(shù),VC編譯器會(huì)怎么處理這個(gè)問(wèn)題呢?VC不會(huì)將它們看作錯(cuò)誤,而會(huì)象對(duì)待虛擬函數(shù)類似的方式去處理,但對(duì)于消息處理函數(shù)(帶afx_msg前綴),則不會(huì)生成虛擬函數(shù)表vtbl。MFCT一個(gè)消息的處理過(guò)程是一般是這樣的。1、_AfxCbtFilterHook截獲消息(這是一個(gè)鉤子函數(shù))2、_AfxCbtFilterHook把窗口過(guò)程設(shè)定為AfxWndProc。3、函數(shù)AfxWndProc接收Windows操作系統(tǒng)發(fā)送
32、的消息。4、函數(shù)AfxWndProc調(diào)用函數(shù)AfxCallWndProc進(jìn)行消息處理。5、函數(shù)AfxCallWndProc調(diào)用CWndl的方法WindowProc進(jìn)行消息處理。如何添加自己的消息?我們已經(jīng)了解了WINDOW!消息機(jī)制,如何加入我們自己的消息呢?好我們來(lái)看一個(gè)標(biāo)準(zhǔn)的消息處理程序是這個(gè)樣子的在CWnd類中預(yù)定義了標(biāo)準(zhǔn)Windows消息(WM_XXXXWM!WINDOWESSAGE縮寫(xiě))的默認(rèn)處理程序。類庫(kù)基于消息名命名這些處理程序。例如,WMPAIN下肖息的處理程序在CWnd中被聲明為:afx_msgvoidOnPaint();afx_msg關(guān)鍵字通過(guò)使這些處理程序區(qū)別于其他CWn
33、d成員函數(shù)來(lái)表明C+virtual關(guān)鍵字的作用。但是請(qǐng)注意,這些函數(shù)實(shí)際上并不是虛擬的,而是通過(guò)消息映射實(shí)現(xiàn)的。我們?cè)诒疚牡囊婚_(kāi)始便說(shuō)明了為什么要這樣做。所有能夠進(jìn)行消息處理的類都是基于CCmdTarget類的,也就是說(shuō)CCmdTarget類是所有可以進(jìn)行消息處理類的父類。CCmdTarget類是MFO理命令消息的基礎(chǔ)和核心。若要重寫(xiě)基類中定義的處理程序,只需在派生類中定義一個(gè)具有相同原型的函數(shù),并創(chuàng)建此處理程序的消息映射項(xiàng)。我們通過(guò)ClassWizard可以建立大多數(shù)窗口消息或自定義的消息,通過(guò)ClassWizard可以自動(dòng)建立消息映射,和消息處理函數(shù)的框架,我們只需要把我們要做的事情填空,
34、添加你要做的事情到處理函數(shù)。這個(gè)非常簡(jiǎn)單,就不細(xì)說(shuō)了。但是也許我們需要添加一些ClassWizard不支持的窗口消息或自定義消息,那么就需要我們親自動(dòng)手建立消息映射和消息處理的框架,通常步驟如下:第一步:定義消息。Microsoft推薦用戶自定義消息至少是WM_USER+10因?yàn)楹芏嘈驴丶惨褂肳M_USER消息。#defineWM_MYMESSAGE(WM_USER+100)第二步:實(shí)現(xiàn)消息處理函數(shù)。該函數(shù)使用WPRAM3LPARA嗪數(shù)并返回LPESULTLPESULTCMainFrame:OnMyMessage(WPARAMwParam,LPARAMlParam)(/TODO:處理用戶自
35、定義消息,填空就是要填到這里。return0;)第三步:在類頭文件的AFX_MS映中說(shuō)明消息處理函數(shù):/AFX_MSG(CMainFrame)afx_msgLRESULTOnMyMessage(WPARAMwParam,LPARAMlParam);/AFX_MSGDECLARE_MESSAGE_MAP()第四步:在用戶類的消息塊中,使用ON_MESSAGEf令將消息映射到消息處理函數(shù)中ON_MESSAGE(WM_MYMESSAGE,OnMyMessage)|MPWInsiderisoneofseveralonlinecommunitieswherethebiggestnamesinibusin
36、essanswertimelycareerandileadershipquestions.Today'sanswerfor:!Whatisonepieceofadviceallmillennials!shouldtakebeforeenteringtheIworkforce?iswrittenbyClaraShih,ffounderandCEOofHearsaySocial.Millennials,youcouldnotbeenteringtheworkforceatamoreexcitingtime.Seizetheday,learnanddothemostyoupossiblyca
37、ntoday,andyourfutureselfLookingbackatmyfirstjob,evenwhenIwasaskedtodosomethingseeminglymenial,unglamorous,orverydifficult,Ialwayswentallin.InmymosttryingmomentswithmanagersIlikedtheleast,Ididnotgiveup,complain,orslackoff.Istayedlate,pulledall-nighterswhennecessary,learnedtoaskforhelponlywhenIcouldn&
38、#39;figureitoutmyself,andbasicallydidwhateverittooktomakemyIImanagerandteamlookgood.ILIOnceIgotgoodatwhatwasaskedofIime,Ichallengedmyselftogofurther.Icontinuallyaskedmyself,WhatelsecanIdo?HowelsecanImakethisbetter?II|Thismindsetledmeearlyinmycareerto!thinkbiggerandproactivelysuggestnewideastotheteam
39、-certainlynotallofthemgoodoraccepted,butalmostalwaysappreciated.Ultimately,goingallinIIwonmpWj部網(wǎng)絡(luò)是一個(gè)邀請(qǐng)最有影響力的商界女性及時(shí)解答職業(yè)與領(lǐng)導(dǎo)力問(wèn)題的在線社區(qū)。本周,我們的問(wèn)題是:千禧一代在進(jìn)入職場(chǎng)之前應(yīng)該聽(tīng)從什么建議?以下是HearsaySocial創(chuàng)始人兼CE魄宗瑋的回答。80后和90后們,要知道,你們這個(gè)年紀(jì)是進(jìn)入職場(chǎng)最好的時(shí)段。抓緊這段時(shí)間,盡最大可能地去學(xué)習(xí)和做事,未來(lái)你肯定會(huì)感激自己今天的付出的?;仡櫸业牡谝环莨ぷ?,即便我被要求去做一些看似很卑微、單調(diào)或者非常困難的事情時(shí),我也會(huì)全力
40、以赴。有的上司是我最不喜歡的類型,但即便如此,我依舊沒(méi)有放棄、抱怨或懈怠。我會(huì)加班到很晚,如果有必要還會(huì)通宵達(dá)旦地工作,我學(xué)會(huì)了只有在自己確實(shí)無(wú)法解決的時(shí)候才去尋求幫助;只要是對(duì)我的上司和團(tuán)隊(duì)有利的事,我都會(huì)主動(dòng)承擔(dān)。一旦能夠游刃有余地完成上司安排的工作,我就會(huì)挑戰(zhàn)自己的能力極限。我會(huì)不斷問(wèn)自己:“我還能做什么?我還能做些什么讓這件事變得更好?”這種心態(tài)讓我在職業(yè)初期便擁有了更開(kāi)闊的思路,主動(dòng)向團(tuán)隊(duì)提出一些新的想法一一雖然并非所有想法都是好的或者被采納,但總能獲得團(tuán)隊(duì)的欣賞。最后,“全力以赴”的工作勁頭,讓我獲得上司和同事的尊重。我有幸加入戰(zhàn)略對(duì)話,這讓我有機(jī)會(huì)了解全局,承擔(dān)更大的職責(zé)。如果你
41、局限于短期思考,你或許認(rèn)為這種想法有違常規(guī),但如果你希望在職業(yè)發(fā)展過(guò)程中實(shí)現(xiàn)工作與生活的平衡,盡早“全力以赴”或許是最明智的選擇。你可以獲得寶貴的經(jīng)驗(yàn)和人脈,這些收獲將給你的職業(yè)發(fā)展帶來(lái)好處。普華永道等公司的研究顯示,80后和90后比他們的前輩更加重視工作與生活的平衡。一方面,許多初入職場(chǎng)的千禧一代會(huì)發(fā)現(xiàn)有些同齡人在工作中總是非常悠閑,即使混日子,依舊能領(lǐng)到工資。他們或許認(rèn)為(你可能也會(huì)同意)自己比這個(gè)體系更聰明。但這樣做其實(shí)會(huì)讓他們錯(cuò)失為職業(yè)生涯奠定基礎(chǔ)的關(guān)鍵時(shí)間段。雖然關(guān)于工作與生活平衡的決定很重要,而且人與人之間存在巨大差異,但從長(zhǎng)遠(yuǎn)來(lái)看,盡量做最少工作的心態(tài)或許并不明智。心理學(xué)家梅格?
42、杰伊在其非常有啟發(fā)性的TED演講20歲光陰不再來(lái)中,給所有二十多歲的年輕人敲響了警鐘。所謂20歲到30歲是“可以揮霍的十年”這種觀念,已經(jīng)成為一種極其危險(xiǎn)的謬論。太多虛度這段光陰的80后和90后將來(lái)肯定會(huì)后悔不迭的。就如今天投資100元產(chǎn)生的價(jià)值要遠(yuǎn)遠(yuǎn)高于10年后投資100元一樣,隨著時(shí)間的推移,出色的工作、職業(yè)關(guān)系和學(xué)習(xí)經(jīng)驗(yàn)會(huì)產(chǎn)生“利滾利”效應(yīng)。你投入的時(shí)間、精力和專注同樣如此。早些起步能讓你獲得管理團(tuán)隊(duì)的權(quán)力,讓你在不得不提前離開(kāi)公司去接孩子放學(xué)時(shí),可以將任務(wù)交給下屬。(財(cái)富中文網(wǎng))譯者:劉進(jìn)龍/汪皓審校:任文科metherespectofmymanagerandcolleagues.Igottobeapartofstrategicconversationsthatallowedmetounderstan
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 基于平衡計(jì)分卡的華辰集團(tuán)零售部績(jī)效考核方案優(yōu)化研究
- 地鐵上蓋混凝土樓板結(jié)構(gòu)地鐵振動(dòng)響應(yīng)特性和傳播規(guī)律研究
- 學(xué)生外出教育主題活動(dòng)方案
- 小學(xué)生安全教育知識(shí)
- 產(chǎn)后媽媽健康管理
- 2025年北京市中考招生考試數(shù)學(xué)真題試卷(真題+答案)
- 預(yù)防火災(zāi)小學(xué)生課件
- 預(yù)防學(xué)生欺凌班會(huì)課件
- 預(yù)防兒童殘疾課件
- 生理衛(wèi)生健康課件
- 護(hù)理核心制度考試試卷(附答案)
- 尾礦工安全培訓(xùn)
- 西安高新區(qū)管委會(huì)招聘筆試真題2024
- 2025年中國(guó)工商銀行招聘筆試備考題庫(kù)(帶答案詳解)
- 研發(fā)項(xiàng)目工時(shí)管理制度
- 浮選藥劑安全管理制度
- 會(huì)陰水腫硫酸鎂濕敷專題報(bào)告
- 技術(shù)異化的解放路徑-洞察及研究
- 2025年連云港市中考語(yǔ)文試卷真題(含標(biāo)準(zhǔn)答案)
- 2025年學(xué)校校長(zhǎng)公開(kāi)選拔筆試試題及參考答案校長(zhǎng)招聘考試筆試真題
- T/CGMA 033002-2020壓縮空氣站節(jié)能設(shè)計(jì)指南
評(píng)論
0/150
提交評(píng)論