版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
深入剖析WTL—WTL框架窗口分析開發(fā)者.cn更新時間:2007-11-16作者:建新來源:賽迪網(wǎng)本文:窗口分析WTLWTL的基礎(chǔ)是ATL。WTL的框架窗口是ATL窗口類的繼承。因此,先介紹一下ATL對由第一部分介紹的Windows應(yīng)用程序可以知道創(chuàng)建窗口和窗口工作的邏輯是1一個窗口顯示和激活該窗WDND對應(yīng)的虛函數(shù)即可。但這樣,會有很多虛函數(shù),使得類的虛函數(shù)表十分巨大。為此,封裝窗口就是要解決上面兩個基本問題。對于第二個問題,ATL是通過只定義一個虛函數(shù)。然后,通過使用宏,來生成消息處理函數(shù)。對于第一個問題,ATL通過使用動態(tài)改變HWND參數(shù)方法來實現(xiàn)的。ATL對窗口的圖示是ATL封裝的類的繼承關(guān)系圖。從圖中可以看到有兩個最基本的類。一個是CWindow,另一個是CMessageMap。CWindowsWindows的窗口API的一個封裝。它把一個Windows句柄封裝了起來,并提供了對該句柄所代表的API的封裝。CWindowC++語言中的一個對象。它與實際的Windows的窗口通過窗口句柄聯(lián)系。創(chuàng)建一個CWindow的實例時并沒有創(chuàng)建相應(yīng)的Windows的窗口CWindow.Create()來創(chuàng)建Windows窗口。也可以創(chuàng)建一個CWindow的實例,然后將它與已經(jīng)存在的Windows窗口掛接起來。CMessageMap僅僅定義了一個抽象虛函數(shù)——ProcessWindowMessage()。所有的包含消息處理機(jī)制的窗口都必須實現(xiàn)該函數(shù)。通常使用ATL開發(fā)程序CWindowImplT類派生MESSAGE_HANDLER(WM_CREATE,OnCreate)COMMAND_ID_HANDLER(ID_APP_EXIT,OnFileExit)COMMAND_ID_HANDLER(ID_FILE_NEW,OnFileNew)COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR,OnViewToolBar)COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR,OnViewStatusBar)COMMAND_ID_HANDLER(ID_APP_ABOUT,OnAppAbout)MESSAGE_HANDLER(WM_CREATE,OnCreate)COMMAND_ID_HANDLER(ID_APP_EXIT,OnFileExit)COMMAND_ID_HANDLER(ID_FILE_NEW,OnFileNew)COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR,OnViewToolBar)COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR,OnViewStatusBar)COMMAND_ID_HANDLER(ID_APP_ABOUT,OnAppAbout)我們知道一個窗口函數(shù)的通case語句。ATL通過使用宏,直接形成窗口函數(shù)的代碼。消息映射是用宏來實現(xiàn)的。通過定義消息映射消息映射中的消息處理句柄,編譯器在編譯時,會為你生成你的窗口類的ProcessWindowMessage()射宏包含消息處理宏BEGIN_MSG_MAP()和#defineBOOLProcessWindowMessage(HWNDhWnd,UINTLPARAMlParam,LRESULT&lResult,DWORDdwMsgMapID={BOOLbHandled=TRUE;#defineBOOLProcessWindowMessage(HWNDhWnd,UINTLPARAMlParam,LRESULT&lResult,DWORDdwMsgMapID={BOOLbHandled=TRUE;{case一目了然,這是ProcessWindowMessage()的實現(xiàn)。與MFC的消息映射相比,ATL的是簡單。記住越是簡單越吸引人。需要注意的是dwMsgMapID。每個消息映射都有一個ID。后面會介紹為什么要用這個。于是可以推斷,消息處理宏應(yīng)該是該函數(shù)的函數(shù)體中的某一部分。也可以斷定END_MSG_MAP()應(yīng)該定義該函數(shù)的函數(shù)結(jié)尾。我們來驗證一下#define#defineATLTRACE2(atlTraceWindowing,0,_T("InvalidmapID(%i)n"),}return}下面看一下消息映射中的消息處理宏深入剖析WTL—WTL框架窗口分析開發(fā)者.cn更新時間:2007-11-16作者:建新來源:賽迪網(wǎng)本文:窗口分析WTLATL的消息處消息映射的目的是實現(xiàn)ProcessWindowMessage()。ProcessWindowMessage()函數(shù)是窗口函數(shù)的關(guān)鍵邏輯。一共有三種消息處理宏,分別對應(yīng)三類窗口消息——普通窗口消息(如 MANS)和通知消息(WM_NOTIFY)。消息處理宏的·普通消息處有兩個這樣的宏:MESSAGE_HANDLER和MESSAGE_RANGE_HANDLERLRESULTMessageHandler(UINTBOOL&ram,LPARAM消息處理函數(shù)通LRESULTMessageHandler(UINTBOOL&ram,LPARAM注意最后一個參數(shù)bHandled。它的作用是該處理函數(shù)是否處理該消息。FALSE,消息MAP的其它處理函數(shù)會來處理這個消息。#defineMESSAGE_HANDLER(msg,if(uMsg=={bHandled=TRUE;lResult#defineMESSAGE_HANDLER(msg,if(uMsg=={bHandled=TRUE;lResult=func(uMsg,return}ram,lParam,息處理函數(shù)來處理該消息。注意bHandled,如果在消息處理函數(shù)中設(shè)置為TRUE,那么,在完成該消息處理后,會進(jìn)入returnTRUE語句,從ProcessWindowMessage()函數(shù)中返回。如果bHandled在調(diào)用消息處理函數(shù)時,設(shè)置為FALSE,則不會從ProcessWindowMessage中返·命令消息處理宏和通知消息處理COMMAND_CODE_HANDLER,COMMAND_RANGE_HANDLER和NOTIFY_CODE_HANDLER,NOTIFY_RANGE_HANDLER和我們不再詳細(xì)分通過上面的分析ATL是怎樣實現(xiàn)窗口函數(shù)邏輯的。那么ATL是怎樣封裝窗口函數(shù)的呢?為了能理解ATL的封裝方法,還必須了解ATL中的窗口subclass等技術(shù)。在分析完這些技術(shù)之后,再ATL對窗口消息處理函數(shù)的封裝。我們知道Windows窗口的功能由它的窗口函數(shù)指定。通常在創(chuàng)建Windows應(yīng)用程序時,我returnDefWindowProc(hWnd,ram, 它傳遞給Windows的確省窗口函數(shù)。Windows除了提供這個缺省的窗口函數(shù),還為某些標(biāo)準(zhǔn)的控制提供了一些預(yù)定義的窗口函數(shù)。returnDefWindowProc(hWnd,ram,下面我們來看幾種擴(kuò)展窗口功能的技術(shù),以及看看ATL是怎樣實現(xiàn)的。classCBase:publicCWindowImpl<CBase//simplebasewindowclass:shutsdownappwhen{BEGIN_MSG_MAP(CBaseMESSAGE_HANDLER(WM_DESTROY,OnDestroyLRESULTOnDestroy({PostQuitMessage(0return}RAM,LPARAM,BOOL&classCBase:publicCWindowImpl<CBase//simplebasewindowclass:shutsdownappwhen{BEGIN_MSG_MAP(CBaseMESSAGE_HANDLER(WM_DESTROY,OnDestroyLRESULTOnDestroy({PostQuitMessage(0return}RAM,LPARAM,BOOL&classCDerived:public//derivedfromCBase;handlesmousebutton{BEGIN_MSG_MAP(CDerivedMESSAGE_HANDLER(WM_LBUTTONDOWN,OnButtonDownCHAIN_MSG_MAP(CBase)//chaintobaseclassLRESULTOnButtonDown( RAM,LPARAM,BOOL&{ATLTRACE("buttondownn");return0;}深入剖析WTL—WTL框架窗口分析開發(fā)者.cn更新時間:2007-11-16作者:建新來源:賽迪網(wǎng)本文:窗口分析WTLCDerived類通過定義一WM_LBUTTONDOWN消息處理函數(shù)來改變CBase類代表的窗口的功能。這樣,CBase類的消息映射定義了ProcessWindowMessage()CDerived類的消息映射也定義了一個ProcessWindowMessage()函數(shù)。們在窗口處理函數(shù)邏輯中怎樣把這兩個類的ProcessWindowMessage()連起來呢?(想想為什么要連起來?)在CDerived的消息映射中CHAIN_MSG_MAP()。它的作用就是把兩個類對消息的處理#define{if(theChainClass::ProcessWindowMessage(hWnd,uMsg,lParam,lResult))return}#define{if(theChainClass::ProcessWindowMessage(hWnd,uMsg,lParam,lResult))return}調(diào)用了基類的也就是說,CDerived類的ProcessWindowMessage()包含兩部分,一部分是調(diào)用處理WM_LBUTTONDOWN的消息處理函數(shù),該函數(shù)是該類的成員函數(shù)。第二部分是調(diào)用CBase類的ProcessWindowMessage()函數(shù),該函數(shù)用于處理WM_DESTROY消息。在后面對窗口函數(shù)的封裝中,我們會知道,對于其他消息處理,CDerived會傳遞給缺省窗口函如果我們希望在CBase類上再派生一個新的窗口類。該類除了要對WM_RBUTTONDOWN做不同的處理外CBase對WM_DESTROY消息的響應(yīng)與前一個例子不同。比如希望能提示關(guān)閉窗口信息。ATL提供了一種機(jī)制,它由ALT_MSG_MAP()實現(xiàn)。它使得一個類的消息映射能處理多個Windows窗口類。//inclassCBase:BEGIN_MSG_MAP(CBase)MESSAGE_HANDLER(//inclassCBase:BEGIN_MSG_MAP(CBase)MESSAGE_HANDLER(WM_DESTROY,OnDestroy1)ALT_MSG_MAP(100)MESSAGE_HANDLER(WM_DESTROY,OnDestroy2)ALT_MSG_MAP()將消息映射分成兩個部分。每個部分的消息映射都有一個ID。上面的消息映射的ID0100。#definecase分#definecase很簡單,它結(jié)束msgMapID的處理,開始進(jìn)入另一個msgMapID的處理//inclassCDerived:BEGIN_MSG_MAP(CDerived)CHAIN_MSG_MAP_ALT(CBase,100)那么CDerived類的消//inclassCDerived:BEGIN_MSG_MAP(CDerived)CHAIN_MSG_MAP_ALT(CBase,100)#defineCHAIN_MSG_MAP_ALT(theChainClass,{if(theChainClass::ProcessWindowMessage(hWnd,uMsg,return}ram,#defineCHAIN_MSG_MAP_ALT(theChainClass,{if(theChainClass::ProcessWindowMessage(hWnd,uMsg,return}ram,不再分析其原理。請 深入剖析WTL—WTL框架窗口分析
開發(fā)者.cn更新時間:2007-11-13作者:建新來源:賽迪網(wǎng)本文:分析窗口WTLsuperclass是一種生成新的窗口類的方法。它的中心思想是依靠現(xiàn)有的窗口類,克隆出另一個窗口類。被克隆的類可以是Windows預(yù)定義的窗口類,這些預(yù)定義的窗口類有按鈕或下拉框控制classCBeepButton:publicCWindowImpl<CBeepButton{DECLARE_WND_SUPERCLASS(_T("BeepButton"),classCBeepButton:publicCWindowImpl<CBeepButton{DECLARE_WND_SUPERCLASS(_T("BeepButton"),_T("Button"))BEGIN_MSG_MAP(CBeepButton)MESSAGE_HANDLER(WM_LBUTTONDOWN,OnLButtonDown)LRESULTOnLButtonDown( RAM,LPARAM,BOOL&bHandled{MessageBeep(MB_ICONASTERISKbHandled=FALSE;//alternatively:DefWindowProc()return0;}};//該類實現(xiàn)一個按鈕,在點擊它時,會有響聲該類的消息映射處理WM_LBUTTONDOWN消息。其它的消息由Windows缺省窗口函數(shù)理#defineDECLARE_WND_SUPERCLASS(WndClassName,OrigWndClassName)staticCWndClassInfo&GetWndClassInfo(){staticCWndClassInfowc{{ ),0,0,0,NULL,NULL,NULL,NULL,NULL,#defineDECLARE_WND_SUPERCLASS(WndClassName,OrigWndClassName)staticCWndClassInfo&GetWndClassInfo(){staticCWndClassInfowc{{ ),0,0,0,NULL,NULL,NULL,NULL,NULL,NULLOrigWndClassName,NULL,NULL,TRUE,0,return}struct{ Am_wc;LPCSTRm_lpszOrigName;WNDPROCpWndProc;這個宏定義了一個靜態(tài)函數(shù)GetWndClassInfo()。這個函數(shù)返回了一個窗口類 結(jié)構(gòu)CWndClassInfo。該結(jié)struct{ Am_wc;LPCSTRm_lpszOrigName;WNDPROCpWndProc;LPCSTRLPCSTRm_lpszCursorID;BOOLm_bSystemCursor;ATOMm_atom;CHARm_szAutoName[13];ATOMRegister(WNDPROC*p){returnthis,}struct{…{returnthis,}typedef_ATL_WNDCLASSINFOACWndClassInfoA;typedef_ATL_WNDCLASSINFOWCWndClassInfoW;#ifdefUNICODE#defineCWndClassInfoCWndClassInfoW#defineCWndClassInfoCWndClassInfoA這個結(jié)構(gòu)調(diào)用了AtlModuleRegisterWndClassInfoA(&_Module,thisp);。這個函數(shù)的用處就是窗口類。它指定了WndClassName是OrigWdClassName的函數(shù)可以對某些需要處理的特定的消息進(jìn)行處理,然后再將處理傳給原來的窗口函數(shù)。注意它與superclass的區(qū)別。Superclass是以一個類為原版,進(jìn)行克隆。既在新的窗口類時,使用的是基類窗口的窗口函數(shù)。而subclass是在某一個窗口并創(chuàng)建后,通過修改該窗口的窗口消息classCNoNumEdit:publicCWindowImpl<CNoNumEdit{BEGIN_MSG_MAP(CNoNumEdit)MESSAGE_HANDLER(WM_CHAR,classCNoNumEdit:publicCWindowImpl<CNoNumEdit{BEGIN_MSG_MAP(CNoNumEdit)MESSAGE_HANDLER(WM_CHAR,OnChar)LRESULTOnChar({ram,LPARAM,BOOL&bHandledTCHARchTCHARchif(_T('0')<=ch&&ch<=_T('9')MessageBeep(0);bHandled=return}classCMyDialog:public{enum{IDD=IDD_DIALOG1BEGIN_MSG_MAP(CMyDialogMESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog)LRESULTOnInitDialog( RAM,LPARAM,BOOL&{ed.SubclassWindow(GetDlgItem(IDC_EDIT1));return0;}CNoNumEditclassCMyDialog:public{enum{IDD=IDD_DIALOG1BEGIN_MSG_MAP(CMyDialogMESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog)LRESULTOnInitDialog( RAM,LPARAM,BOOL&{ed.SubclassWindow(GetDlgItem(IDC_EDIT1));return0;}CNoNumEdit上述代碼中,ed.SubclassWindowGetDlgItem(IDC_EDIT1語句是對IDC_EDIT1這個編輯控件進(jìn)行subclass。該語句實際上是替換了編輯控件的窗口函數(shù)。由于SubClassWindows()實現(xiàn)ATL封裝窗口函數(shù)的機(jī)制一樣,我們會在后面介紹ATL是怎么實現(xiàn)它的。深入剖析WTL—WTL框架窗口分析開發(fā)者.cn更新時間:2007-11-13作者:建新來源:賽迪網(wǎng)本文:分析窗口WTL發(fā)到HWND相對應(yīng)的類的實例中的相應(yīng)函數(shù)。來看一下,ATL采用的是什么辦法來實現(xiàn)我們知道每個Windows的窗口類都有一LRESULTWndProc(HWNDhWnd,UINTuMsg,RAMram,LPARAM te<classTBase=CWindow,classTWinTraits= te<classTBase=CWindow,classTWinTraits=classATL_NO_VTABLECWindowImplBaseT:publicCWindowImplRoot<TBase>{…staticLRESULTCALLBACKStartWindowProc(HWNDhWnd,UINTuMsg, LPARAMstaticLRESULTCALLBACKWindowProc(HWNDhWnd,UINTuMsg, LPARAM…}ProcessWindowsMessage(HWNDhWnd,UINTuMsg,RAMram,LPARAMlParam,LRESULT&lResult,DWORDdwMsgMapID)。其它成員函數(shù),參數(shù)中沒有this指針。注意,之所以存在這個問題是因為通常想到的解決辦法是根據(jù)窗口函數(shù)的HWND參數(shù),尋找與其對應(yīng)的類的實例的指針。然后,通過該指針,調(diào)用該實例的消息邏輯處理函數(shù)ProcessWindowsMessage()。這樣就要求一個全局?jǐn)?shù)組,將HWND和該類的實例的指針一一對應(yīng)地存放在該數(shù)組中ATL解決這個問題的方法很巧妙。該方法并不這些對應(yīng)關(guān)系,而是使窗口函數(shù)接收C++類指針作為參數(shù)來替代HWND作為參數(shù)。具體步驟如下創(chuàng)建窗口類時,將this指針暫時·Windows在創(chuàng)建該類的窗口時會調(diào)用起始窗口函數(shù)。它的作用是創(chuàng)建一系列二進(jìn)制(thunk)。這些代碼用this指針的物理地址來取代窗口函數(shù)的HWND參數(shù),然后跳轉(zhuǎn)到實際的詳細(xì)ATL的封裝代碼。 te<classTBase,class te<classTBase,classHWNDCWindowImplBaseT<TBase,TWinTraits>::Create(HWNDhWndParent,RECT&rcPos,LPCTSTRszWindowName,DWORDdwStyle,DWORDdwExStyle,UINTnID,ATOMatom,LPVOID{ATLASSERT(m_hWnd==if(atom==0)returnNULL;_Module.AddCreateWndData(&m_thunk.cd,if(nID==0&&(dwStyle&WS_CHILD))nID=(UINT)this;HWNDhWnd=::CreateWindowEx(dwExStyle,(LPCTSTR)MAKELONG(atom,0),szWindowName,dwStyle,rcPos.left,rcPos.top,rcPos.right-rcPos.left,rcPos.bottom-rcPos.top,hWndParent,(H_Module.GetModuleInstance(),ATLASSERT(m_hWnd==hWnd);returnhWnd;}_Module.AddCreateWndData(&m_thunk.cd,this);語句把this指針保存在_Module的某個第二件事就是創(chuàng)建一個Windows窗口下面我們來看一下一段關(guān)鍵的二進(jìn)制代碼。它的作用是將傳遞給實際窗口函數(shù)的HWND參數(shù)用類#pragmapack(push,1)struct{ m_mov;//movdwordptr[esp+0x4],pThis(esp+0x4#pragmapack(push,1)struct{ m_mov;//movdwordptr[esp+0x4],pThis(esp+0x4 //jmpWndProc //relative#pragma#pragmapack(push,1)的意思是告訴編譯器,該結(jié)構(gòu)在內(nèi)存中每個字段都緊緊挨著。因為它存放movdwordptr[esp+4],pThisjmpWndProc這movdwordptr[esp+4],pThisjmpWndProcMOVHWND參數(shù)(esp+0x4)變成類的實例pThis。JMP指令完成一個相對跳轉(zhuǎn)到實際的窗口函數(shù)WndProc的任務(wù)。注意,此時堆棧HWND參數(shù)已經(jīng)變pThis,也就是說,WinProc得到的HWND參數(shù)實際pThis。class{{_AtlCreateWndData_WndProcThunkvoidInit(WNDPROCproc,void*{thunk.m_mov=0x042444C7; //C744240Cthunk.m_this=(DWORD)pThis;thunk.m_jmp=0xe9;thunk.m_relproc=(int)procclass{{_AtlCreateWndData_WndProcThunkvoidInit(WNDPROCproc,void*{thunk.m_mov=0x042444C7; //C744240Cthunk.m_this=(DWORD)pThis;thunk.m_jmp=0xe9;thunk.m_relproc=(int)proc-//writeblockfromdatacache flushfrominstructioncacheFlushInstructionCache(GetCurrentProcess(),&thunk,}ATL包裝了一個類并定Init()成員函數(shù)來設(shè)置初始值的。在語句thunk.m_relproc=(int)procint)this+sizeof(_WndProcThunk));用于把跳轉(zhuǎn)指令的相對地址設(shè)置為(int)proc-((對地址是(int)proc-((int)this+sizeof(_WndProcThunk))。 te<classTBase,class te<classTBase,classLRESULTCALLBACKCWindowImplBaseT<TBase,TWinTraits>::StartWindowProc(HWNDUINT{ram,LPARAMCWindowImplBaseT<TBase,TWinTraits>*pThis=(CWindowImplBaseT<TWinTraitsTWinTraits>*)_Module.ExtractCreateWndData();ATLASSERT(pThis!=NULL);pThis->m_hWnd=pThis->m_thunk.Init(pThis->GetWindowProc(),pThis);WNDPROCpProc=(WNDPROC)&(pThis->m_thunk.thunk);WNDPROCpOldProc=(WNDPROC)::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)pProc);#ifdef_DEBUG//checkifsomebodyhassubclassedusalreadysincewediscarditif(pOldProc!=StartWindowProc)ATLTRACE2(atlTraceWindowing,0,_T("SubclassingthroughapOldProc;//avoidunusedreturnpProc(hWnd, ram,}該函數(shù)做了四件一是調(diào)用_Module.ExtractCreateWndData()語句,從保存this指針的地方得到該this指針。二是m_thunk.Init(pThis->GetWindowProc(),pThis)語句初始化thunk代碼。WNDPROCpProc=(WNDPROC)&(pThis->m_thunk.thunk);WNDPROCpOldProc=(WNDPROC)::SetWindowLong(hWnd,GWL_WNDPROC,三是將thunkWNDPROCpProc=(WNDPROC)&(pThis->m_thunk.thunk);WNDPROCpOldProc=(WNDPROC)::SetWindowLong(hWnd,GWL_WNDPROC,這樣,以后的消息處理首先thunk代碼。它將HWNDpThis指針,然后跳轉(zhuǎn)到實際的窗口函數(shù)WindowProc()。由于StartWindowProc()在創(chuàng)建窗口時被Windows調(diào)用。在完成上述任務(wù)后它應(yīng)該 te<classTBase,classLRESULTCALLBACKCWindowImplBaseT<TBase, te<classTBase,classLRESULTCALLBACKCWindowImplBaseT<TBase,TWinTraits>::WindowProc(HWNDUINT{ram,LPARAMCWindowImplBaseT<TBase,TWinTraits>*pThis=(CWindowImplBaseT<TWinTraits//setaptrtothismessageandsavetheoldMSGmsg={pThis->m_hWnd,uMsg, ram,lParam,0,{0,0}};constMSG*pOldMsg=pThis->m_pCurrentMsg;pThis->m_pCurrentMsg=//passtothemessagemaptoprocessLRESULTlRes;BOOLbRet=pThis->ProcessWindowMessage(pThis->m_hWnd, ram,lParam,//restoresavedvalueforthecurrentmessageATLASSERT(pThis->m_pCurrentMsg==&msg);pThis->m_pCurrentMsg=pOldMsg;//dothedefaultprocessingifmessagewasnothandled{if(uMsg!=lRes=pThis->DefWindowProc(uMsg, ram,lParam);{//unsubclass,ifLONGpfnWndProc=::GetWindowLong(pThis-lRes=pThis->DefWindowProc(uMsg, ram,lParam);if(pThis->m_pfnSuperWindowProc!=::DefWindowProc&&::GetWindowLong(pThis->m_hWnd,GWL_WNDPROC)==::SetWindowLong(pThis->m_hWnd,//clearoutwindowhandleHWNDhWnd=pThis->m_hWnd;pThis->m_hWnd=NULL;//cleanupafterwindowisdestroyed}}return}首先,該函數(shù)把hWnd參數(shù)cast到一個pThis然后調(diào)用pThis->ProcessWindowMessage(pThis->m_hWnd,uMsg,ram,lParam,lRes,0);語句,也就是調(diào)用消息邏輯處理,將具體的消息處理事務(wù)交給接下ProcessWindowMessage()沒有對任何消息進(jìn)行處理,就調(diào)用缺省的消息處理。注意這里處理WM_NCDESTROYsubclass有關(guān),最后恢復(fù)沒有subclass以前的窗WTLsubclass的封 te<classTBase,classBOOLCWindowImplBaseT<TBase,TWinTraits>::SubclassWindow(HWND{ATLASSERT(m_hWnd== te<classTBase,classBOOLCWindowImplBaseT<TBase,TWinTraits>::SubclassWindow(HWND{ATLASSERT(m_hWnd==m_thunk.Init(GetWindowProc(),this);WNDPROCpProc=WNDPROCpProc=WNDPROCpfnWndProc=(WNDPROC)::SetWindowLong(hWnd,if(pfnWndProc==returnFALSE;m_pfnSuperWindowProc=pfnWndProc;m_hWnd=hWnd;return}深入剖析WTL—WTL框架窗口分析開發(fā)者.cn更新時間:2007-11-13作者:建新來源:賽迪網(wǎng)本文:分析窗口WTLWTL對框架ATL僅僅是封裝了窗口函數(shù)和提供了消息映射。實際應(yīng)用中,需要各種種類的窗口,比如,每個界面線程所對應(yīng)的框架窗口。WTLATL基礎(chǔ)上,為我們提供了框架窗口和其他各種窗口。MFC中的一樣圖示是WTL的窗口類的WTL框架窗口為我們提供了一個應(yīng)用程序的標(biāo)題,窗口框架,菜單, 在狀態(tài)欄顯示幫助信息等等WTL提供的方法是在界面線程的邏輯中創(chuàng)建框架窗口,而視的創(chuàng)建由框架窗口負(fù)責(zé)。后面會介紹,框架窗口在處理WM_CREATE消息時創(chuàng)建視。如果要創(chuàng)建一個框架窗口,需要加入DECLARE_FRAME_WND_CLASS,指定菜單和的資源ID下面是使用ATL/WTLAppWizardSDI應(yīng)用程序的主框架窗口的申明。classCMainFrame:publicCFrameWindowImpl<CMainFrame>,publicCUpdateUI<CMainFrame>,publicCMessageFilter,{DECLARE_FRAME_WND_CLASS(NULL,CView//該框架窗 令工具CCommandBarCtrlvirtualBOOLPreTranslateMessage(MSG*pMsg);virtualBOOLOnIdle();UPDATE_ELEMENT(ID_VIEW_TOOLBAR,UPDUI_ UPDATE_ELEMENT(ID_VIEW_STATUS_BAR,UPDUI_ MESSAGE_HANDLER(WM_CREATE,OnCreate)COMMAND_ID_HANDLER(ID_APP_EXIT,OnFileExit)COMMAND_ID_HANDLER(ID_FILE_NEW,OnFileNew)COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR,OnViewToolBar)COMMAND_ID_HANDLER(ID_APP_ABOUT,//Handlerpro
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 零售企業(yè)行政經(jīng)理合同
- 幼兒園放學(xué)接送合同范本參考
- 建筑工程維修合同完整版
- 交通運輸總監(jiān)合同模板
- 人才引進(jìn)服務(wù)協(xié)議合同范例
- 鉆石升值回購合同范例
- 財產(chǎn)保險合同范本(2篇)
- 托運人案例合同法
- 集體經(jīng)濟(jì)與公司合作協(xié)議書
- 拆監(jiān)控設(shè)備合同范例
- 三傻大鬧寶萊塢課件
- 護(hù)理科普作品
- 國家OTC藥品目錄(全部品種)
- 社會主義發(fā)展簡史智慧樹知到課后章節(jié)答案2023年下北方工業(yè)大學(xué)
- Android課程設(shè)計報告
- 課題研究技術(shù)路線圖
- 2023年江西省公務(wù)員考試真題及答案解析行測
- 六年級上冊科學(xué)活動手冊參考答案(2023年新改版教科版)
- 廣東省文物保護(hù)單位“四有”工作規(guī)范
- 面對基層醫(yī)院兒科的兒童肺功能理論培訓(xùn)題庫及答案華醫(yī)網(wǎng)繼續(xù)教育兒科內(nèi)科學(xué)
- 2021年廣東省廣州市增城區(qū)中考物理一模試題( 含答案解析 )
評論
0/150
提交評論