📄 mfc
字号:
<!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.3132" 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教程9_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教程9_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教程9_MFC的状态.files/image145.gif" width=421 align=left>
<P align=justify></P><IMG height=364 hspace=12
src="MFC教程9_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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -