?? mfc教程9.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0041)http://www.vczx.com/tutorial/mfc/mfc9.php -->
<HTML><HEAD><TITLE>MFC教程</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2900.3157" name=GENERATOR></HEAD>
<BODY bgColor=#ffffff>
<OL start=9>
<P align=justify>
<LI><A name=_Toc445889095></A><A name=_Toc445782498></A><A
name=_Toc452640959></A><A name=_Toc457299057></A><B>MFC的狀態</B>
<P></P>
<P
align=justify>MFC定義了多種狀態信息,這里要介紹的是模塊狀態、進程狀態、線程狀態。這些狀態可以組合在一起,例如MFC句柄映射就是模塊和線程局部有效的,屬于模塊-線程狀態的一部分。</P>
<OL>
<P align=justify>
<LI><A name=_Toc445889096></A><A name=_Toc445782499></A><A
name=_Toc452640960></A><A name=_Toc457299058></A><B>模塊狀態</B>
<P></P>
<P align=justify>這里模塊的含義是:一個可執行的程序或者一個使用MFC DLL的DLL,比如一個OLE控件就是一個模塊。</P>
<P align=justify>一個應用程序的每一個模塊都有一個狀態,模塊狀態包括這樣一些信息:用來加載資源的
Windows實例句柄、指向當前CWinApp或者CWinThread對象的指針、OLE模塊的引用計數、Windows對象與相應的MFC對象之間的映射。只有單一模塊的應用程序的狀態如圖9-1所示。</P><IMG
height=281 hspace=12 src="MFC教程.files/image143.gif" width=181 align=left>
<P align=justify>m_pModuleState
指針是線程對象的成員變量,指向當前模塊狀態信息(一個AFX_MODULE_STATE結構變量)。當程序運行進入某個特定的模塊時,必須保證當前使用的模塊狀態是有效的模塊狀態──是這個特定模塊的模塊狀態。所以,每個線程對象都有一個指針指向有效的模塊狀態,每當進入某個模塊時都要使它指向有效模塊狀態,這對維護應用程序全局狀態和每個模塊狀態的完整性來說是非常重要的。為了作到這一點,每個模塊的所有入口點有責任實現模塊狀態的切換。模塊的入口點包括:DLL的輸出函數;OLE/COM界面的成員函數;窗口過程。</P><IMG
height=304 hspace=12 src="MFC教程.files/image144.gif" width=384 align=left
vspace=18>
<P align=justify>在講述窗口過程和動態鏈接到MFC
DLL的規則DLL時,曾提到了語句AFX_MANAGE_STATE(AfxGetStaticModuleState(
)),它就是用來在入口點切換模塊狀態的。其實現機制將在后面9.4.1節講解。</P>
<P align=justify>多個模塊狀態之間切換的示意圖如圖9-2所示。</P>
<P align=justify>圖9-2中,m_pModuleState總是指向當前模塊的狀態。</P>
<P align=justify></P>
<LI><A name=_Toc445889097></A><A name=_Toc445782500></A><A
name=_Toc452640961></A><A name=_Toc457299059></A><B>模塊、進程和線程狀態的數據結構</B>
<P></P>
<P
align=justify>MFC定義了一系列類或者結構,通過它們來實現狀態信息的管理。這一節將描述它們的關系,并逐一解釋它們的數據結構、成員函數等。</P>
<OL>
<P align=justify>
<LI><A name=_Toc445889098></A><A name=_Toc445782501></A><A
name=_Toc452640962></A><A name=_Toc457299060></A><B>層次關系</B>
<P></P>
<P align=justify>圖9-3顯示了線程狀態、模塊狀態、線程-模塊狀態等幾個類的層次關系:</P>
<P
align=justify>線程狀態用類_AFX_THREAD_STATE描述,模塊狀態用類AFX_MODULE_STATE描述,模塊-線程狀態用類AFX_MODULE_THREAD_STATE描述。這些類從類CNoTrackObject派生。進程狀態類用_AFX_BASE_MODULE_STATE描述,從模塊狀態類AFX_MODULE_STATE派生。進程狀態是了一個可以獨立執行的MFC應用程序的模塊狀態。還有其他狀態如DLL的模塊狀態等也從模塊狀態類_AFX_MODULE_STATE派生。</P>
<P align=justify>圖9-4顯示了這幾個類的交互關系。</P>
<P align=justify></P><IMG height=177 hspace=12
src="MFC教程.files/image145.gif" width=421 align=left>
<P align=justify></P><IMG height=364 hspace=12
src="MFC教程.files/image146.gif" width=360 align=left>
<P align=justify></P>
<P
align=justify>從圖9-4可以看出:首先,每個線程有一個線程狀態,線程狀態的指針m_pModuleState和m_pPreModuleState分別指向線程當前運行模塊的狀態或前一運行模塊的狀態;其次,每一個模塊狀態都有一個線程局部的變量用來存儲模塊-線程狀態。</P>
<P align=justify>下面各小節列出狀態信息管理所涉及的各個類的定義。</P>
<P align=justify></P>
<LI><A name=_Toc445889099></A><A name=_Toc445782502></A><A
name=_Toc452640963></A><A name=_Toc457299061></A><B>CNoTrackObject類</B>
<P></P>
<P align=justify>在圖9-3中, CnoTrackObject是根類,所有狀態類都是從它這里派生的,其定義如下:</P>
<P align=justify>class CNoTrackObject</P>
<P align=justify>{</P>
<P align=justify>public:</P>
<P align=justify>void* PASCAL operator new(size_t nSize);</P>
<P align=justify>void PASCAL operator delete(void*);</P>
<P align=justify></P>
<P align=justify>#if defined(_DEBUG) &&
!defined(_AFX_NO_DEBUG_CRT)</P>
<P align=justify>void* PASCAL operator new(size_t nSize, LPCSTR, int);</P>
<P align=justify>#endif</P>
<P align=justify>virtual ~CNoTrackObject() { }</P>
<P align=justify>};</P>
<P
align=justify>該類的析構函數是虛擬函數;而且,CNoTrackObject重載new操作符用來分配內存,重載delete操作符號用來釋放內存,內部通過LocalAlloc/LocalFree提供了一個低層內存分配器(Low_level
alloctor)。</P>
<P align=justify></P>
<LI><A name=_Toc445889100></A><A name=_Toc445782503></A><A
name=_Toc452640964></A><A name=_Toc457299062></A><B>AFX_MODULE_STATE類</B>
<P></P>
<P align=justify>AFX_MODULE_STATE類的定義如下:</P>
<P align=justify>// AFX_MODULE_STATE (global data for a module)</P>
<P align=justify>class AFX_MODULE_STATE : public CNoTrackObject</P>
<P align=justify>{</P>
<P align=justify>public:</P>
<P align=justify>#ifdef _AFXDLL</P>
<P align=justify>AFX_MODULE_STATE(BOOL bDLL,WNDPROC pfnAfxWndProc,</P>
<P align=justify>DWORD dwVersion);</P>
<P align=justify>AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, </P>
<P align=justify>DWORD dwVersion,BOOL bSystem);</P>
<P align=justify>#else</P>
<P align=justify>AFX_MODULE_STATE(BOOL bDLL);</P>
<P align=justify>#endif</P>
<P align=justify>~AFX_MODULE_STATE();</P>
<P align=justify></P>
<P align=justify>CWinApp* m_pCurrentWinApp;</P>
<P align=justify>HINSTANCE m_hCurrentInstanceHandle;</P>
<P align=justify>HINSTANCE m_hCurrentResourceHandle;</P>
<P align=justify>LPCTSTR m_lpszCurrentAppName;</P>
<P align=justify>BYTE m_bDLL;// TRUE if module is a DLL, FALSE if it is an
EXE</P>
<P align=justify>//TRUE if module is a "system" module, FALSE if not</P>
<P align=justify>BYTE m_bSystem;</P>
<P align=justify>BYTE m_bReserved[2]; // padding</P>
<P align=justify></P>
<P align=justify>//Runtime class data:</P>
<P align=justify>#ifdef _AFXDLL</P>
<P align=justify>CRuntimeClass* m_pClassInit;</P>
<P align=justify>#endif</P>
<P align=justify>CTypedSimpleList<CRuntimeClass*> m_classList;</P>
<P align=justify></P>
<P align=justify>// OLE object factories</P>
<P align=justify>#ifndef _AFX_NO_OLE_SUPPORT</P>
<P align=justify>#ifdef _AFXDLL</P>
<P align=justify>COleObjectFactory* m_pFactoryInit;</P>
<P align=justify>#endif</P>
<P align=justify>CTypedSimpleList<COleObjectFactory*>
m_factoryList;</P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>// number of locked OLE objects</P>
<P align=justify>long m_nObjectCount;</P>
<P align=justify>BOOL m_bUserCtrl;</P>
<P align=justify></P>
<P align=justify>// AfxRegisterClass and AfxRegisterWndClass data</P>
<P align=justify>TCHAR m_szUnregisterList[4096];</P>
<P align=justify>#ifdef _AFXDLL</P>
<P align=justify>WNDPROC m_pfnAfxWndProc;</P>
<P align=justify>DWORD m_dwVersion; // version that module linked
against</P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>// variables related to a given process in a module</P>
<P align=justify>// (used to be AFX_MODULE_PROCESS_STATE)</P>
<P align=justify>#ifdef _AFX_OLD_EXCEPTIONS</P>
<P align=justify>// exceptions</P>
<P align=justify>AFX_TERM_PROC m_pfnTerminate;</P>
<P align=justify>#endif</P>
<P align=justify>void (PASCAL *m_pfnFilterToolTipMessage)(MSG*,
CWnd*);</P>
<P align=justify></P>
<P align=justify>#ifdef _AFXDLL</P>
<P align=justify>// CDynLinkLibrary objects (for resource chain)</P>
<P align=justify>CTypedSimpleList<CDynLinkLibrary*>
m_libraryList;</P>
<P align=justify></P>
<P align=justify>// special case for MFCxxLOC.DLL (localized MFC
resources)</P>
<P align=justify>HINSTANCE m_appLangDLL;</P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>#ifndef _AFX_NO_OCC_SUPPORT</P>
<P align=justify>// OLE control container manager</P>
<P align=justify>COccManager* m_pOccManager;</P>
<P align=justify>// locked OLE controls</P>
<P align=justify>CTypedSimpleList<COleControlLock*> m_lockList;</P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>#ifndef _AFX_NO_DAO_SUPPORT</P>
<P align=justify>_AFX_DAO_STATE* m_pDaoState;</P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>#ifndef _AFX_NO_OLE_SUPPORT</P>
<P align=justify>// Type library caches</P>
<P align=justify>CTypeLibCache m_typeLibCache;</P>
<P align=justify>CMapPtrToPtr* m_pTypeLibCacheMap;</P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>// define thread local portions of module state</P>
<P align=justify>THREAD_LOCAL(AFX_MODULE_THREAD_STATE, m_thread)</P>
<P align=justify>};</P>
<P align=justify>從上面的定義可以看出,模塊狀態信息分為如下幾類:</P>
<P align=justify>模塊信息,資源信息,對動態鏈接到MFC
DLL的支持信息,對擴展DLL的支持信息,對DAO的支持信息,對OLE的支持信息,模塊-線程狀態信息。</P>
<P
align=justify>模塊信息包括實例句柄、資源句柄、應用程序名稱、指向應用程序的指針、是否為DLL模塊、模塊注冊的窗口類,等等。其中,成員變量m_fRegisteredClasses、m_szUnregisterList曾經在討論MFC的窗口注冊時提到過它們的用處。</P>
<P align=justify>在“#ifdef _AFXDLL…#endif”條件編譯范圍內的是支持MFC DLL的數據;</P>
<P align=justify>在“#ifndef
_AFX_NO_OLE_SUPPOR…#endif”條件編譯范圍內的是支持OLE的數據;</P>
<P align=justify>在“#ifndef
_AFX_NO_OCC_SUPPOR…#endif”條件編譯范圍內的是支持OLE控件的數據;</P>
<P align=justify>在“#ifndef _AFX_NO_DAO_SUPPORT”條件編譯范圍內的是支持DAO的數據。</P>
<P align=justify>THREAD_LOCAL宏定義了線程私有的模塊-線程類型的變量m_thread。</P>
<P align=justify></P>
<LI><A name=_Toc445889101></A><A name=_Toc445782504></A><A
name=_Toc452640965></A><A
name=_Toc457299063></A><B>_AFX_BASE_MODULE_STATE</B>
<P></P>
<P align=justify>該類定義如下:</P>
<P align=justify>class _AFX_BASE_MODULE_STATE : public
AFX_MODULE_STATE</P>
<P align=justify>{</P>
<P align=justify>public:</P>
<P align=justify>#ifdef _AFXDLL</P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -