MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制_第1頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制_第2頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制_第3頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制_第4頁(yè)
MFC運(yùn)行機(jī)制和消息響應(yīng)機(jī)制_第5頁(yè)
已閱讀5頁(yè),還剩7頁(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、MFC的類層次結(jié)構(gòu)與運(yùn)行機(jī)制MFC的類層次結(jié)構(gòu)如圖所示(子類指向父類): 其中:CObject:是MFC提供的絕大多數(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ù)。

2、CWnd:是一個(gè)通用的窗口類,用來(lái)提供Windows中的所有通用特性、對(duì)話框和控件。CFrameWnd是從CWnd類繼承來(lái)的,并實(shí)現(xiàn)了標(biāo)準(zhǔn)的框架應(yīng)用程序。CDialog類用來(lái)控制對(duì)話框窗口。CView:用于讓用戶通過(guò)窗口來(lái)訪問文檔。CMDIFrameWnd和CMDIChildWnd:分別用于多文檔應(yīng)用程序的主框架窗口和文檔子窗口的顯示和管理。CMiniFrameWnd類是一種簡(jiǎn)化的框架窗口,它沒有最大化和最小化窗口按鈕,也沒有窗口系統(tǒng)菜單,一般很少用到它。           

3、0;    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)行到"CSimpApp theApp;"時(shí),

4、系統(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 = new CMainFrame;該語(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->

5、;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ì)列為空

6、時(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(),完成終止應(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)的分析,可以幫助程序開發(fā)人員對(duì)MFC的消息映射機(jī)制有一個(gè)比較透徹的了解。1引言- VC+的MFC類庫(kù)實(shí)際上是

7、Windows下C+編程的一套最為流行的類庫(kù)。MFC的框架結(jié)構(gòu)大大方便了程序員的編程工作,但是為了更加有效、靈活的使用MFC編程,了解MFC的體系結(jié)構(gòu)往往可以使編程工作事半功倍。它合理的封裝了WIN32 API函數(shù),并設(shè)計(jì)了一套方便的消息映射機(jī)制。但這套機(jī)制本身比較龐大和復(fù)雜,對(duì)它的分析和了解無(wú)疑有助于我們寫出更為合理的高效的程序。這里我們簡(jiǎn)單的分析MFC的消息響應(yīng)機(jī)制,以了解MFC是如何對(duì)Windows的消息加以封裝,方便用戶的開發(fā)。2. SDK下的消息機(jī)制實(shí)現(xiàn)- 這里簡(jiǎn)單的回顧一下SDK下我們是如何進(jìn)行Windows的程序開發(fā)的。一般來(lái)說(shuō),Windows的消息都是和線程相對(duì)應(yīng)的。即Wind

8、ows會(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。 typedef struct tagMSG HWND hwnd;UINT message; WPARAM wParam;LPARAM lParam;DWORD time;POINT pt; MSG;- 其中hwnd表示和窗口過(guò)程相關(guān)的窗口的句柄,message表示消息的ID號(hào),wParam和lParam表示和消息相關(guān)的參數(shù),time表示消息發(fā)送的時(shí)間,pt

9、表示消息發(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的各種消息。3MFC的消息實(shí)現(xiàn)機(jī)制- 我們可以看到,在MFC的框架結(jié)構(gòu)下,可以進(jìn)行消息處理的類的頭文件里面都會(huì)含有DECLARE_MESSAGE

10、_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è)主

11、要結(jié)構(gòu):AFX_MSGMAP_ENTRYstruct AFX_MSGMAP_ENTRYUINT nMessage; / windows messageUINT nCode; / control code or WM_NOTIFY codeUINT nID; / control ID (or 0 for windows messages)UINT nLastID; / used for entries specifying a range of control id'sUINT nSig; / signature type (action) or point

12、er to message #AFX_PMSG pfn; / routine to call (or special value);和AFX_MSGMAPstruct AFX_MSGMAP#ifdef _AFXDLLconst AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();#elseconst AFX_MSGMAP* pBaseMap;#endifconst AFX_MSGMAP_ENTRY* lpEntries;其中AFX_MSGMAP_ENTRY結(jié)構(gòu)包含了一個(gè)消息的所有相關(guān)信息,其中nMessage為Windows消息的ID號(hào)nCode為控制消息的通知碼nID

13、為Windows控制消息的IDnLastID表示如果是一個(gè)指定范圍的消息被映射的話,nLastID用來(lái)表示它的范圍。nSig表示消息的動(dòng)作標(biāo)識(shí)AFX_PMSG pfn 它實(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)用其基類的消

14、息響應(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類的方法WindowPr

15、oc進(jìn)行消息處理。注意AfxWndProc和AfxCallWndProc都是AFX的API函數(shù)。而WindowProc已經(jīng)是CWnd的一個(gè)方法。所以可以注意到在WindowProc中已經(jīng)沒有關(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è)消息。

16、實(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è)方法的操作。 void CInheri

17、tView:OnLButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call default CView: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方

18、法沒有對(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,而是和消息類型具體相關(guān)的參數(shù)。比如和消息WM_LbuttonDown相對(duì)應(yīng)的方法OnLButtonDown的兩個(gè)參數(shù)是nFlags和point。nFlags表示在按下鼠標(biāo)左鍵的時(shí)候是否有其他虛鍵按下,point更簡(jiǎn)單,就是

19、表示鼠標(biāo)的位置。 - 同時(shí)MFC窗口類消息傳遞中還提供了兩個(gè)函數(shù),分別為WalkPreTranslateTree和PreTranslateMessage。我們知道利用MFC框架生成的程序,都是從CWinApp開始執(zhí)行的,而CWinapp實(shí)際繼承了CWinThread類。在CWinThread的運(yùn)行過(guò)程中會(huì)調(diào)用窗口類中的WalkPreTranslateTree方法。而WalkPreTranslateTree方法實(shí)際上就是從當(dāng)前窗口開始查找愿意進(jìn)行消息翻譯的類,直到找到窗口沒有父類為止。在WalkPreTranslateTree方法中調(diào)用了PreTranslateMessage方法。實(shí)際

20、上PreTranslateMessage最大的好處是我們?cè)谙⑻幚砬翱梢栽谶@個(gè)方法里面先做一些事情。舉一個(gè)簡(jiǎn)單的例子,比如我們希望在一個(gè)CEdit對(duì)象里,把所有的輸入的字母都以大寫的形式出現(xiàn)。我們只需要在PreTranslateMessage方法中判斷message是否為WM_CHAR,如果是的話,把wParam(表示鍵值)由小寫字母的值該為大寫字母的值就實(shí)現(xiàn)了這個(gè)功能。- 繼續(xù)上面的例子,根據(jù)我們對(duì)MFC消息機(jī)制的分析,我們很容易得到除了上面的方法,我們至少還可以在另外兩個(gè)地方進(jìn)行操作。- 一:在消息的處理方法里面即OnChar中,當(dāng)然最后我們不再調(diào)用CEdit:OnChar(nChar,

21、nRepCnt, nFlags),而是直接調(diào)用DefWindowProc(WM_CHAR,nChar,MAKELPARAM (nRepCnt,nFlags)。因?yàn)閺奈覀兩厦娴姆治隹梢灾繡Edit:OnChar(nChar, nRepCnt, nFlags)實(shí)際上也就是對(duì)DefWindowProc方法的調(diào)用。- 二:我們可以直接重載DefWindowProc方法,對(duì)message類型等于WM_CHAR的,直接修改nChar的值即可。4小結(jié)- 通過(guò)對(duì)MFC類庫(kù)的分析和了解,不僅能夠使我們更好的使用MFC類庫(kù),同時(shí),對(duì)于我們自己設(shè)計(jì)和實(shí)現(xiàn)框架和類,無(wú)疑也有相當(dāng)大的幫助。  二M

22、FC的消息映射機(jī)制 MFC的設(shè)計(jì)者們?cè)谠O(shè)計(jì)MFC時(shí),緊緊把握一個(gè)目標(biāo),那就是盡可能使得MFC的代碼要小,速度盡可能快。為了這個(gè)目標(biāo),他們使用了許多技巧,其中很多技巧體現(xiàn)在宏的運(yùn)用上,實(shí)現(xiàn)MFC的消息映射的機(jī)制就是其中之一。同MFC消息映射機(jī)制有關(guān)的宏有下面幾個(gè):DECLARE_MESSAGE_MAP()宏BEGIN_MESSAGE_MAP(theClass, baseClass)和END_MESSAGE_MAP()宏弄懂MFC消息映射機(jī)制的最好辦法是將找出一個(gè)具體的實(shí)例,將這些宏展開,并找出相關(guān)的數(shù)據(jù)結(jié)構(gòu)。DECLARE_MESSAGE_MAP()  DECLARE_MES

23、SAGE_MAP()宏的定義如下:#define DECLARE_MESSAGE_MAP() private: static const AFX_MSGMAP_ENTRY _messageEntries; protected: static AFX_DATA const AFX_MSGMAP messageMap; virtual const AFX_MSGMAP* GetMessageMap() const; 從上面的定義可以看出,DECLARE_MESSAGE_MAP()作下面三件事:定義一個(gè)長(zhǎng)度不定的靜態(tài)數(shù)組變量_messageEntries;定義一個(gè)靜態(tài)變量messageMap;定義一

24、個(gè)虛擬函數(shù)GetMessageMap();在DECLARE_MESSAGE_MAP()宏中,涉及到MFC中兩個(gè)對(duì)外不公開的數(shù)據(jù)結(jié)構(gòu)AFX_MSGMAP_ENTRY和AFX_MSGMAP。為了弄清楚消息映射,有必要考察一下這兩個(gè)數(shù)據(jù)結(jié)構(gòu)的定義。AFX_MSGMAP_ENTRY的定義struct AFX_MSGMAP_ENTRYUINT nMessage; / windows messageUINT nCode; / control code or WM_NOTIFY codeUINT nID; / control ID (or 0 for windows messages)UINT nLastI

25、D; / used for entries specifying a range of control id'sUINT nSig; / signature type (action) or pointer to message #AFX_PMSG pfn; / routine to call (or special value);結(jié)構(gòu)中各項(xiàng)的含義注釋已經(jīng)說(shuō)明得很清楚了,這里不再多述,從上面的定義你是否看出,AFX_MSGMAP_ENTRY結(jié)構(gòu)實(shí)際上定義了消息和處理此消息的動(dòng)作之間的映射關(guān)系。因此靜態(tài)數(shù)組變量_messageEntries實(shí)際上定義了一張表,表中的每一項(xiàng)指定了相應(yīng)的對(duì)象

26、所要處理的消息和處理此消息的函數(shù)的對(duì)應(yīng)關(guān)系,因而這張表也稱為消息映射表。再看看AFX_MSGMAP的定義。(2)AFX_MSGMAP的定義struct AFX_MSGMAPconst AFX_MSGMAP* pBaseMap;const AFX_MSGMAP_ENTRY* lpEntries;不難看出,AFX_MSGMAP定義了一單向鏈表,鏈表中每一項(xiàng)的值是一指向消息映射表的指針(實(shí)際上就是_messageEntries的值)。通過(guò)這個(gè)鏈表,使得在某個(gè)類中調(diào)用基類的的消息處理函數(shù)很容易,因此,“父類的消息處理函數(shù)是子類的缺省消息處理函數(shù)”就“順理成章”了。在后面的“MFC窗口的消息處理”一節(jié)中

27、會(huì)對(duì)此作詳細(xì)的講解。由上述可見,在類的頭文件中主要定義了兩個(gè)數(shù)據(jù)結(jié)構(gòu):消息映射表和單向鏈表。(孫建東總結(jié))BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()它們的定義如下:#define BEGIN_MESSAGE_MAP(theClass, baseClass) const AFX_MSGMAP* theClass:GetMessageMap() const return &theClass:messageMap; AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass:messageMap = &baseCl

28、ass:messageMap, &theClass:_messageEntries0 ; AFX_COMDAT const AFX_MSGMAP_ENTRY theClass:_messageEntries = #define END_MESSAGE_MAP() 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 ; 對(duì)應(yīng)BEGIN_MESSAGE_MAP()的定義可能不是一下子就看得明白,不過(guò)不要緊,舉一例子就很清楚了。對(duì)于BEGIN_MESSAGE_MAP(CView, CWnd),VC預(yù)編譯器將其展開成下面的形式:const AFX_MSGMAP* CView

29、:GetMessageMap() const return &CView:messageMap; AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CView:messageMap = &CWnd:messageMap, &CView:_messageEntries0 AFX_COMDAT const AFX_MSGMAP_ENTRY CView:_messageEntries =至于END_MESSAGE_MAP()則不過(guò)定義了一個(gè)表示映射表結(jié)束的標(biāo)志項(xiàng),我想大家對(duì)于這種簡(jiǎn)單的技巧應(yīng)該是很

30、熟悉的,無(wú)需多述。到此為止,我想大家也已經(jīng)想到了象ON_COMMAND這樣的宏的具體作用了,不錯(cuò)它們只不過(guò)定義了一種類型的消息映射項(xiàng),看看ON_COMMAND的定義:#define ON_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, Afx

31、Sig_vv, (AFX_PMSG)&OnFileNew,到此,MFC的消息映射機(jī)制已經(jīng)清楚了,現(xiàn)在提出并解答兩個(gè)問題以作為對(duì)這一節(jié)的小結(jié)。為什么不直接使用虛擬函數(shù)實(shí)現(xiàn)消息處理函數(shù)呢?這是一個(gè)GOOD QUESTION。前面已經(jīng)說(shuō)過(guò),MFC的設(shè)計(jì)者們?cè)谠O(shè)計(jì)MFC時(shí)有一個(gè)很明確的目標(biāo),就是使得“MFC的代碼盡可能小,速度盡可能快”,如果采用虛擬函數(shù),那么對(duì)于所有的窗口消息,都必須有一個(gè)與之對(duì)應(yīng)的虛擬函數(shù),因而對(duì)每一個(gè)從CWnd派生的類而言,都會(huì)有一張很大的虛擬函數(shù)表vtbl。但是在實(shí)際應(yīng)用中,一般只對(duì)少數(shù)的消息進(jìn)行處理,大部分都交給系統(tǒng)缺省處理,所以表中的大部分項(xiàng)都是無(wú)用項(xiàng),這

32、樣做就浪費(fèi)了很多內(nèi)存資源,這同MFC設(shè)計(jì)者們的設(shè)計(jì)目標(biāo)是相違背的。當(dāng)然,MFC所使用的方法只是解決這類問題的方式之一,不排除還有其他的解決方式,但就我個(gè)人觀點(diǎn)而言,這是一種最好的解決方式,體現(xiàn)了很高的技巧性,值得我們學(xué)習(xí)。至于這第二個(gè)問題,是由上面的問題引申出來(lái)的。如果在子類和父類中出現(xiàn)了相同的消息出來(lái)函數(shù),VC編譯器會(huì)怎么處理這個(gè)問題呢?VC不會(huì)將它們看作錯(cuò)誤,而會(huì)象對(duì)待虛擬函數(shù)類似的方式去處理,但對(duì)于消息處理函數(shù)(帶afx_msg前綴),則不會(huì)生成虛擬函數(shù)表vtbl。MFC下一個(gè)消息的處理過(guò)程是一般是這樣的。1、_AfxCbtFilterHook截獲消息(這是一個(gè)鉤子函數(shù))2、_AfxCb

33、tFilterHook把窗口過(guò)程設(shè)定為AfxWndProc。3、函數(shù)AfxWndProc接收Windows操作系統(tǒng)發(fā)送的消息。4、函數(shù)AfxWndProc調(diào)用函數(shù)AfxCallWndProc進(jìn)行消息處理。5、函數(shù)AfxCallWndProc調(diào)用CWnd類的方法WindowProc進(jìn)行消息處理。如何添加自己的消息?我們已經(jīng)了解了WINDOW的消息機(jī)制,如何加入我們自己的消息呢?好我們來(lái)看一個(gè)標(biāo)準(zhǔn)的消息處理程序是這個(gè)樣子的在 CWnd 類中預(yù)定義了標(biāo)準(zhǔn) Windows 消息 (WM_XXXX  WM是WINDOW MESSAGE的縮寫) 的默認(rèn)處理程序。類庫(kù)基于消息名命名這些處

34、理程序。例如,WM_PAINT 消息的處理程序在 CWnd 中被聲明為:afx_msg void OnPaint();afx_msg 關(guān)鍵字通過(guò)使這些處理程序區(qū)別于其他 CWnd 成員函數(shù)來(lái)表明 C+ virtual 關(guān)鍵字的作用。但是請(qǐng)注意,這些函數(shù)實(shí)際上并不是虛擬的,而是通過(guò)消息映射實(shí)現(xiàn)的。我們?cè)诒疚牡囊婚_始便說(shuō)明了為什么要這樣做。所有能夠進(jìn)行消息處理的類都是基于CCmdTarget類的,也就是說(shuō)CCmdTarget類是所有可以進(jìn)行消息處理類的父類。CCmdTarget類是MFC處理命令消息的基礎(chǔ)和核心。若要重寫基類中定義的處理程序,只需在派生類中定義一個(gè)具有相同原型的函數(shù),并創(chuàng)建此處理程

35、序的消息映射項(xiàng)。我們通過(guò)ClassWizard可以建立大多數(shù)窗口消息或自定義的消息,通過(guò)ClassWizard可以自動(dòng)建立消息映射,和消息處理函數(shù)的框架,我們只需要把我們要做的事情填空,添加你要做的事情到處理函數(shù)。這個(gè)非常簡(jiǎn)單,就不細(xì)說(shuō)了。但是也許我們需要添加一些ClassWizard不支持的窗口消息或自定義消息,那么就需要我們親自動(dòng)手建立消息映射和消息處理的框架,通常步驟如下:第一步:定義消息。Microsoft推薦用戶自定義消息至少是WM_USER+100,因?yàn)楹芏嘈驴丶惨褂肳M_USER消息。#define WM_MYMESSAGE (WM_USER + 100)第二步:實(shí)現(xiàn)消息處理

36、函數(shù)。該函數(shù)使用WPRAM和LPARAM參數(shù)并返回LPESULT。LPESULT CMainFrame:OnMyMessage(WPARAM wParam, LPARAM lParam)/ TODO: 處理用戶自定義消息,填空就是要填到這里。return 0;第三步:在類頭文件的AFX_MSG塊中說(shuō)明消息處理函數(shù):/ AFX_MSG(CMainFrame)afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);/AFX_MSGDECLARE_MESSAGE_MAP()第四步:在用戶類的消息塊中,使用ON_MESSAGE宏指令將消息映射

37、到消息處理函數(shù)中。ON_MESSAGE( WM_MYMESSAGE, OnMyMessage )MPW內(nèi)部網(wǎng)絡(luò)是一個(gè)邀請(qǐng)最有影響力的商界女性及時(shí)解答職業(yè)與領(lǐng)導(dǎo)力問題的在線社區(qū)。本周,我們的問題是:千禧一代在進(jìn)入職場(chǎng)之前應(yīng)該聽從什么建議?以下是Hearsay Social創(chuàng)始人兼CEO史宗瑋的回答。    80后和90后們,要知道,你們這個(gè)年紀(jì)是進(jìn)入職場(chǎng)最好的時(shí)段。抓緊這段時(shí)間,盡最大可能地去學(xué)習(xí)和做事,未來(lái)你肯定會(huì)感激自己今天的付出的。    回顧我的第一份工作,即便我被要求去做一些看似很卑微、單調(diào)或者非常困難的事

38、情時(shí),我也會(huì)全力以赴。有的上司是我最不喜歡的類型,但即便如此,我依舊沒有放棄、抱怨或懈怠。我會(huì)加班到很晚,如果有必要還會(huì)通宵達(dá)旦地工作,我學(xué)會(huì)了只有在自己確實(shí)無(wú)法解決的時(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ì)的欣賞。最后,“全力以赴”的工作勁頭,讓我獲得上司和同事的尊重。我有

39、幸加入戰(zhàn)略對(duì)話,這讓我有機(jī)會(huì)了解全局,承擔(dān)更大的職責(zé)。    如果你局限于短期思考,你或許認(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ò)失為

40、職業(yè)生涯奠定基礎(chǔ)的關(guān)鍵時(shí)間段。    雖然關(guān)于工作與生活平衡的決定很重要,而且人與人之間存在巨大差異,但從長(zhǎng)遠(yuǎn)來(lái)看,盡量做最少工作的心態(tài)或許并不明智。心理學(xué)家梅格杰伊在其非常有啟發(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)。

41、你投入的時(shí)間、精力和專注同樣如此。早些起步能讓你獲得管理團(tuán)隊(duì)的權(quán)力,讓你在不得不提前離開公司去接孩子放學(xué)時(shí),可以將任務(wù)交給下屬。(財(cái)富中文網(wǎng))    譯者:劉進(jìn)龍/汪皓    審校:任文科    MPW Insider is one of several online communities where the biggest names in business answer timely career and leadership questions. Todays ans

42、wer for: What is one piece of advice all millennials should take before entering the workforce? is written by Clara Shih, founder and CEO of Hearsay Social.    Millennials, you could not be entering the workforce at a more exciting time. Seize the day, learn and do the most you p

43、ossibly can today, and your future self    Looking back at my first job, even when I was asked to do something seemingly menial, unglamorous, or very difficult, I always went all in. In my most trying moments with managers I liked the least, I did not give up, complain, or slack

44、off. I stayed late, pulled all-nighters when necessary, learned to ask for help only when I couldnt figure it out myself, and basically did whatever it took to make my manager and team look good.    Once I got good at what was asked of me, I challenged myself to go further. I con

45、tinually asked myself, “What else can I do? How else can I make this better?” This mindset led me early in my career to think bigger and proactively suggest new ideas to the teamcertainly not all of them good or accepted, but almost always appreciated. Ultimately, going “all in” won me the respect o

46、f my manager and colleagues. I got to be a part of strategic conversations that allowed me to understand the bigger picture and play ever-bigger roles.    This idea might seem counterintuitive if you are stuck in short-term thinking, but if you really want work/life balance over a career, going all in as much as pos

溫馨提示

  • 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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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)論