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

下載本文檔

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

文檔簡介

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類派生而來的。CWinThread類用來完成對(duì)線程的控制,包括線程的創(chuàng)建、運(yùn)行、終止和掛起等。CDocument:是文檔類,包含了應(yīng)用程序在運(yùn)行期間所用到的數(shù)據(jù)。CWnd是一個(gè)

2、通用的窗口類,用來提供Windows中的所有通用特性、對(duì)話框和控件。CFrameWn雇從CWn談繼承來的,并實(shí)現(xiàn)了標(biāo)準(zhǔn)的框架應(yīng)用程序。CDialog類用來控制對(duì)話框窗口。CView:用于讓用戶通過窗口來訪問文檔。CMDIFrameWnd口CMDIChildWnd:分別用于多文檔應(yīng)用程序的主框架窗口和文檔子窗口的顯示和管理。CMiniFrameWnd類是一種簡化的框架窗口,它沒有最大化和最小化窗口按鈕,也沒有窗口系統(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ù)來完成主窗口的構(gòu)造和顯示工作。下面來看看上述程序中InitIn

4、stance的執(zhí)行過程。首先執(zhí)行的是:m_pMainWnd=newCMainFrame;該語句用來創(chuàng)建從CFrameWn酸派生而來的用戶框架窗口CMainFrame類對(duì)象,繼而調(diào)用該類的構(gòu)造函數(shù),使得Create函數(shù)被調(diào)用,完成了窗口創(chuàng)建工作。然后執(zhí)行后面兩句:m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();用作窗口的顯示和更新。接下來調(diào)用:m_pMainWnd->MessageBox(,你好,歡迎進(jìn)入MFCS界!");最后返回TRUE表示窗口創(chuàng)建成功。由于應(yīng)用程序類CWinApp是用來調(diào)用

5、WinMain以及實(shí)例的初始化,因此每一個(gè)MFC用程序有且只能一個(gè)這樣的應(yīng)用程序類,且需要一個(gè)全局的對(duì)象實(shí)例,如上述程序中的theApp,當(dāng)然也可換一個(gè)對(duì)象名。InitInstance()完成初始化工作之后,接下來就是調(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ì)列為空且又沒有后臺(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è)類庫,但是該類庫比較龐雜,尤其是它的消息映射機(jī)制,更是涉及到很多低層的東西,我們?cè)谶@里,對(duì)它的整個(gè)消息映射機(jī)制進(jìn)行了系統(tǒng)的分析,可以幫助程序開發(fā)人員對(duì)M

7、FC的消息映射機(jī)制有一個(gè)比較透徹的了解。1. 引言-VC+勺MF屢?guī)鞂?shí)際上是Windows下C+編程的一套最為流行的類庫。MFC勺框架結(jié)構(gòu)大大方便了程序員的編程工作,但是為了更加有效、靈活的使用MF編程,了解MFC的體系結(jié)構(gòu)往往可以使編程工作事半功倍。它合理的封裝了WIN32API函數(shù),并設(shè)計(jì)了一套方便的消息映射機(jī)制。但這套機(jī)制本身比較龐大和復(fù)雜,對(duì)它的分析和了解無疑有助于我們寫出更為合理的高效的程序。這里我們簡單的分析MFC勺消息響應(yīng)機(jī)制,以了解MFC是如彳對(duì)Windows的消息加以封裝,方便用戶的開發(fā)。2. SDK下的消息機(jī)制實(shí)現(xiàn)-這里簡單的回顧一下SDK下我們是如何進(jìn)行Windows的程

8、序開發(fā)的。一般來說,Windows的消息者B是和線程相對(duì)應(yīng)的。即Windows會(huì)把消息發(fā)送給和該消息相對(duì)應(yīng)的線程。在SDK勺模式下,程序是通過GetMessage函數(shù)從和某個(gè)線程相對(duì)應(yīng)的消息隊(duì)列里面把消息取出來并放到一個(gè)特殊的結(jié)構(gòu)里面,一個(gè)消息的結(jié)構(gòu)是一個(gè)如下的STRUCTUREtypedefstructtagMSGHWNDhwnd;UINTmessage;WPARAMwParam;LPARAMlParam;DWORDtime;POINTpt;MSG;- -其中hwnd表示和窗口過程相關(guān)的窗口的句柄,message表示消息的ID號(hào),wParam和lParam表示和消息相關(guān)的參數(shù),time表示消

9、息發(fā)送的時(shí)間,pt表示消息發(fā)送時(shí)的鼠標(biāo)的位置。- -然后TranslateMessage函數(shù)用來把虛鍵消息翻譯成字符消息并放到響應(yīng)的消息隊(duì)列里面,最后DispatchMessage函數(shù)把消息分發(fā)到相關(guān)的窗口過程。然后窗口過程根據(jù)消息的類型對(duì)不同的消息進(jìn)行相關(guān)的處理。在SDK程過程中,用戶需要在窗口過程中分析消息的類型和跟消息一起的參數(shù)的含義,做不同的處理,相對(duì)比較麻煩,而MFCm消息調(diào)用的過程給封裝起來,使用戶能夠通過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類的,也就是說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用來表示它的范圍。nSig表示消息的動(dòng)作標(biāo)識(shí)AFX_PMSG

13、pfn它實(shí)際上是一個(gè)指向和該消息相應(yīng)的執(zhí)行函數(shù)的指針。- -而AFX_MSGMAP要作用是兩個(gè),一:用來得到基類的消息映射入口地址。二:得到本身的消息映射入口地址。- -實(shí)際上,MFCS所有的消息一條條填入到AFX_MSGMAP_ENTRY中去,形成一個(gè)數(shù)組,該數(shù)組存放了所有的消息和與它們相關(guān)的參數(shù)。同時(shí)通過AFX_MSGM/f睛到該數(shù)組的首地址,同時(shí)得到基類的消息映射入口地址,這是為了當(dāng)本身對(duì)該消息不響應(yīng)的時(shí)候,就調(diào)用其基類的消息響應(yīng)。- -現(xiàn)在我們來分析MFC是如何讓窗口過程來處理消息的,實(shí)際上所有MFC的窗口類都通過鉤子函數(shù)_AfxCbtFilterHook截獲消息,并且在鉤子函數(shù)_Af

14、xCbtFilterHook中把窗口過程設(shè)定為AfxWndProc。原來的窗口過程保存在成員變量m_pfnSuper中。- -所以在MFCf架下,一般一個(gè)消息的處理過程是這樣的。函數(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)沒有關(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)是通過函數(shù)AfxFindMessageEntry來實(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í)際上就是通過ClassWizard在類實(shí)現(xiàn)中定義的一個(gè)方法。這樣就把消息的處理轉(zhuǎn)化到類中的一個(gè)方法的實(shí)現(xiàn)上。舉一個(gè)簡單的例子,比如在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)用原來的窗口過程進(jìn)行缺省的消息處理。如果OnWndMs市法沒有對(duì)消息進(jìn)行處理的話,就調(diào)用DefWindowProc對(duì)消息進(jìn)行處理。這是實(shí)際上是調(diào)用原來的窗口過程進(jìn)行缺省的消息處理。- -所以如果正常的消息處理的話,MFC®口類是完全脫離了原來的窗口過程,用自己的一套體系結(jié)構(gòu)實(shí)現(xiàn)消息的映射和處理。即先調(diào)用MFCW口

18、類掛上去的窗口過程,再調(diào)用原先的窗口過程。并且用戶面對(duì)和消息相關(guān)的參數(shù)不再是死板的wParam和lParam,而是和消息類型具體相關(guān)的參數(shù)。比如和消息WM_LbuttonDowWll對(duì)應(yīng)的方法OnLButtonDown的兩個(gè)參數(shù)是nFlags和point。nFlags表示在按下鼠標(biāo)左鍵的時(shí)候是否有其他虛鍵按下,point更簡單,就是表示鼠標(biāo)的位置。- -同時(shí)MFC®口類消息傳遞中還提供了兩個(gè)函數(shù),分別為WalkPreTranslateTree和PreTranslateMessage。我們知道利用MFC匡架生成的程序,都是從CWinApp開始執(zhí)行的,而CWinapp實(shí)際繼承了CWinT

19、hread類。在CWinThread的運(yùn)行過程中會(huì)調(diào)用窗口類中的WalkPreTranslateTree方法。而WalkPreTranslateTree方法實(shí)際上就是從當(dāng)前窗口開始查找愿意進(jìn)行消息翻譯的類,直到找到窗口沒有父類為止。在WalkPreTranslateTree方法中調(diào)用了PreTranslateMessage方法。實(shí)際上PreTranslateMessage最大的好處是我們?cè)谙⑻幚砬翱梢栽谶@個(gè)方法里面先做一些事情。舉一個(gè)簡單的例子,比如我們希望在一個(gè)CEdit對(duì)象里,把所有的輸入的字母都以大寫的形式出現(xiàn)。我們只需要在PreTranslateMessage方法中判斷message

20、是否為WM_CHAR,果是的話,把wParam俵示鍵值)由小寫字母的值該為大寫字母的值就實(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é)-通過對(duì)MF陵庫的分析和了解,不僅能夠使我們更好的使用MF屢?guī)?,同時(shí),對(duì)于我們自己設(shè)計(jì)和實(shí)現(xiàn)框架和類,無疑也有相當(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í)例,將這些宏展開,并找出相關(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è)長度不定的靜態(tài)數(shù)組變量_messageEntries口;定義一個(gè)靜態(tài)變量messageMap定義一個(gè)虛擬函數(shù)GetMessageMap();在DECLARE_MESSAGE_MAP(),涉及至|JMF計(jì)兩個(gè)對(duì)外不公開的數(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)說明得很清楚了,這里不再多述,從上面的定義你是否看出,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的值)。通過這個(gè)鏈表,使得在某個(gè)類中調(diào)用基類的的消息處理函數(shù)很容易,因此,“父類

26、的消息處理函數(shù)是子類的缺省消息處理函數(shù)”就“順理成章”了。在后面的“MFC窗口的消息處理”一節(jié)中會(huì)對(duì)此作詳細(xì)的講解。由上述可見,在類的頭文件中主要定義了兩個(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(相義可能不是一下子就看得明白,不過不要緊,舉一例子就很清楚了。對(duì)于BEGIN_MESSAGE_MAP(CView,CWnd,C預(yù)編譯器將其展開成下面的形式: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(不過定義了一個(gè)表示映射表結(jié)束的標(biāo)志項(xiàng),我想大家對(duì)于這種簡單的技巧應(yīng)該是很熟悉的,無需多述。到此為止,我想大家也已經(jīng)想到了象ON_COMM

29、A幽的宏的具體作用了,不錯(cuò)它們只不過定義了一種類型的消息映射項(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ù)編譯器展開如下:WM_COMMAND,CN_COMMAND,(WORD)id,(WORD)id,AfxSig_vv,(AFX_PMSG)&OnFileNew,到此,MFC的消息映射機(jī)制已經(jīng)清楚了,

30、現(xiàn)在提出并解答兩個(gè)問題以作為對(duì)這一節(jié)的小結(jié)。為什么不直接使用虛擬函數(shù)實(shí)現(xiàn)消息處理函數(shù)呢?這是一個(gè)GOODQUESTKONtf面已經(jīng)說過,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)都是無用項(xiàng),這樣做就浪費(fèi)了很多內(nèi)存資源,這同MFC殳計(jì)者們的設(shè)計(jì)目標(biāo)是相違背的。當(dāng)然,MFC所使用的方法只是解決這類問題的方式之一,

31、不排除還有其他的解決方式,但就我個(gè)人觀點(diǎn)而言,這是一種最好的解決方式,體現(xiàn)了很高的技巧性,值得我們學(xué)習(xí)。至于這第二個(gè)問題,是由上面的問題引申出來的。如果在子類和父類中出現(xiàn)了相同的消息出來函數(shù),VC編譯器會(huì)怎么處理這個(gè)問題呢?VC不會(huì)將它們看作錯(cuò)誤,而會(huì)象對(duì)待虛擬函數(shù)類似的方式去處理,但對(duì)于消息處理函數(shù)(帶afx_msg前綴),則不會(huì)生成虛擬函數(shù)表vtbl。MFCT一個(gè)消息的處理過程是一般是這樣的。1、_AfxCbtFilterHook截獲消息(這是一個(gè)鉤子函數(shù))2、_AfxCbtFilterHook把窗口過程設(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ī)制,如何加入我們自己的消息呢?好我們來看一個(gè)標(biāo)準(zhǔn)的消息處理程序是這個(gè)樣子的在CWnd類中預(yù)定義了標(biāo)準(zhǔn)Windows消息(WM_XXXXWM!WINDOWESSAGE縮寫)的默認(rèn)處理程序。類庫基于消息名命名這些處理程序。例如,WMPAIN下肖息的處理程序在CWnd中被聲明為:afx_msgvoidOnPaint();afx_msg關(guān)鍵字通過使這些處理程序區(qū)別于其他CWn

33、d成員函數(shù)來表明C+virtual關(guān)鍵字的作用。但是請(qǐng)注意,這些函數(shù)實(shí)際上并不是虛擬的,而是通過消息映射實(shí)現(xiàn)的。我們?cè)诒疚牡囊婚_始便說明了為什么要這樣做。所有能夠進(jìn)行消息處理的類都是基于CCmdTarget類的,也就是說CCmdTarget類是所有可以進(jìn)行消息處理類的父類。CCmdTarget類是MFO理命令消息的基礎(chǔ)和核心。若要重寫基類中定義的處理程序,只需在派生類中定義一個(gè)具有相同原型的函數(shù),并創(chuàng)建此處理程序的消息映射項(xiàng)。我們通過ClassWizard可以建立大多數(shù)窗口消息或自定義的消息,通過ClassWizard可以自動(dòng)建立消息映射,和消息處理函數(shù)的框架,我們只需要把我們要做的事情填空,

34、添加你要做的事情到處理函數(shù)。這個(gè)非常簡單,就不細(xì)說了。但是也許我們需要添加一些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映中說明消息處理函數(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)力問題的在線社區(qū)。本周,我們的問題是:千禧一代在進(jìn)入職場之前應(yīng)該聽從什么建議?以下是HearsaySocial創(chuàng)始人兼CE魄宗瑋的回答。80后和90后們,要知道,你們這個(gè)年紀(jì)是進(jìn)入職場最好的時(shí)段。抓緊這段時(shí)間,盡最大可能地去學(xué)習(xí)和做事,未來你肯定會(huì)感激自己今天的付出的。回顧我的第一份工作,即便我被要求去做一些看似很卑微、單調(diào)或者非常困難的事情時(shí),我也會(huì)全力

40、以赴。有的上司是我最不喜歡的類型,但即便如此,我依舊沒有放棄、抱怨或懈怠。我會(huì)加班到很晚,如果有必要還會(huì)通宵達(dá)旦地工作,我學(xué)會(huì)了只有在自己確實(shí)無法解決的時(shí)候才去尋求幫助;只要是對(duì)我的上司和團(tuán)隊(duì)有利的事,我都會(huì)主動(dòng)承擔(dān)。一旦能夠游刃有余地完成上司安排的工作,我就會(huì)挑戰(zhàn)自己的能力極限。我會(huì)不斷問自己:“我還能做什么?我還能做些什么讓這件事變得更好?”這種心態(tài)讓我在職業(yè)初期便擁有了更開闊的思路,主動(dòng)向團(tuán)隊(duì)提出一些新的想法一一雖然并非所有想法都是好的或者被采納,但總能獲得團(tuán)隊(duì)的欣賞。最后,“全力以赴”的工作勁頭,讓我獲得上司和同事的尊重。我有幸加入戰(zhàn)略對(duì)話,這讓我有機(jī)會(huì)了解全局,承擔(dān)更大的職責(zé)。如果你

41、局限于短期思考,你或許認(rèn)為這種想法有違常規(guī),但如果你希望在職業(yè)發(fā)展過程中實(shí)現(xiàn)工作與生活的平衡,盡早“全力以赴”或許是最明智的選擇。你可以獲得寶貴的經(jīng)驗(yàn)和人脈,這些收獲將給你的職業(yè)發(fā)展帶來好處。普華永道等公司的研究顯示,80后和90后比他們的前輩更加重視工作與生活的平衡。一方面,許多初入職場的千禧一代會(huì)發(fā)現(xiàn)有些同齡人在工作中總是非常悠閑,即使混日子,依舊能領(lǐng)到工資。他們或許認(rèn)為(你可能也會(huì)同意)自己比這個(gè)體系更聰明。但這樣做其實(shí)會(huì)讓他們錯(cuò)失為職業(yè)生涯奠定基礎(chǔ)的關(guān)鍵時(shí)間段。雖然關(guān)于工作與生活平衡的決定很重要,而且人與人之間存在巨大差異,但從長遠(yuǎn)來看,盡量做最少工作的心態(tài)或許并不明智。心理學(xué)家梅格?

42、杰伊在其非常有啟發(fā)性的TED演講20歲光陰不再來中,給所有二十多歲的年輕人敲響了警鐘。所謂20歲到30歲是“可以揮霍的十年”這種觀念,已經(jīng)成為一種極其危險(xiǎn)的謬論。太多虛度這段光陰的80后和90后將來肯定會(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)力,讓你在不得不提前離開公司去接孩子放學(xué)時(shí),可以將任務(wù)交給下屬。(財(cái)富中文網(wǎng))譯者:劉進(jìn)龍/汪皓審校:任文科metherespectofmymanagerandcolleagues.Igottobeapartofstrategicconversationsthatallowedmetounderstan

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論