MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
2009-08-30 19:39
429 查看
本文转自CSDN博客:http://blog.csdn.net/ATField/archive/2007/03/04/1520379.aspx
作者:张羿
1.
当我们在用
MFC
编程的时候,我们经常用到
AfxGetApp()
来获得当前的
CWinApp
的
Instance
。看看
MFC
的源代码中
AfxGetApp()
的实现,你会发现
AfxGetApp()
的实现并不像一般情况下面那样直接:
AfxGetApp()
调用的是
AfxGetModuleState()
,该函数返回一个
AFX_MODULE_STATE
的指针,其中的一个成员保存着当前的
CWinApp
的指针。可
AfxGetModuleState()
的作用又是什么呢?
此外,当我们在开发
MFC DLL
程序的时候,我们会在每个输出的
DLL
函数前面加上一句
AFX_MANAGE_STATE
:
AFX_MANAGE_STATE
又是起什么作用呢?从字面上看来,它是
Manage
某种
State
,而
AfxGetStaticModuleState
又是获得
State
的,那么
State
究竟是什么呢?
在
MFC
中,
States
用来保存某种相关的状态信息,分为下面几类:
1.
Process State
,和某个单独的进程绑定起来
2.
Thread State
,和某个单独的线程绑定
3.
Module State
,和
Module
相关
前两种
State
和一般的全局变量十分类似,只是根据需求的不同被绑定于不同的进程
/
线程,如多线程支持等。而
Module State
本身比较特别,
Module State
根据情况的不同,可以是全局,线程,或者进程相关的
State
,并且可以根据要求快速切换。
2.
常见的
Process State
有:
1.
_AFX_WIN_STATE
2.
_AFX_DB_STATE
3.
_AFX_DEBUG_STATE
4.
_AFX_SOCK_STATE
5.
……
从字面上面可以很容易猜出这些状态的用处。
MFC
通过下面的宏来定义
Process State:
PROCESS_LOCAL
用
CProcessLocal
模板类定义了一个
CProcessLocal<class_name>
的一个实例作为状态变量,而
EXTERN_PROCESS_LOCAL
则使在头文件中声明此状态变量。
CProcessLocal
的定义如下:
CProcessLocal
的作用只是一个
Wrapper
,
Hold
一个
TYPE*
的指针,一旦用户调用
GetData
来获得这个指针,
GetData
会首先判断该指针是否为空,如果为空,则创建一个新的实例保存起来,否则返回已有的指针。前提条件是,
TYPE
必须从
CNoTrackObject
继承。任何从
CNoTrackObject
继承的类都拥有自己的
new/delete
,这样此对象便不会被
Debug
的内存分配系统所跟踪而误判为
Leak
。
3.
和
Process State
类似,
Thread State
和某个线程绑定起来,
Thread State
有:
1.
_AFX_THREAD_STATE
2.
_AFXCTL_AMBIENT_CACHE
同样的,
Thread State
是被
THREAD_LOCAL
和
EXTERN_THREAD_LOCAL
定义,也有
CThreadLocal
和
CThreadLocalObject
来
Hold
住
Thread State
的指针。
CThreadLocal
和
CProcessLocal
的实现方式不太一样,
CThreadLocal
利用
TLS(Thread Local Storage)
来保存指针,而不是用成员变量。简单来说,
Thread Local Storage
是
Windows
支持的功能,可以在任意线程中保存多个
DWORD
数据,每个这样的
DWORD
数据所占的位置称之为
Slot
,分配数据需要分配一个
Slot
,获得和修改数据
CThreadLocalObject::GetData
的实现如下:
CThreadLocalObject::GetData
首先判断
m_nSlot
,如果
m_nSlot == 0
,说明该
Thread State
未曾分配,
GetData
函数将会使用
_afxThreadData->AllocSlot
函数分配一个新的
TLS
的
Slot
,保存在
m_nSlot
之中,然后调用
GetThreadValue
检查
pValue
是否为
NULL
,如果是,则创建一个新的对象然后调用
SetValue
把
pValue
设置到该
Slot
之中。
_afxThreadData
的类型为
CThreadSlotData
,是对
TLS API
的一个简单的封装。
_AFX_THREAD_STATE
是一个很常用的
Thread State
,每个
Thread
,都会有自己的一份
_AFX_THREAD_STATE
。
MFC
提供了一个函数
AfxGetThreadState
来获得当前进程的
Thread State
,如果当前的线程还没有
Thread State
,该函数会创建一个新的
Thread State
。
_AFX_THREAD_STATE
中保存着下列信息:
1.
当前的
m_pModuleState
,每个线程都知道它当前的
Module State
,这个信息被用来获得当前的
Module State
,
AfxGetModuleState
正是这么做的:
2.
之前的
m_pModuleState
,用来保存之前的
Module State
,用于
Module State
切换,可参考
AFX_MANAGE_STATE
3.
其他信息,具体可以参考
_AFX_THREAD_STATE
的定义
4.
Module State
保存着和
Module
相关的状态信息。
Module
是
Windows
的术语,代表任何一个可执行的代码文件,
EXE
和
DLL
都是
Module
的一种。
Module State
有下面几种:
1.
AFX_MODULE_STATE
,保存
MODULE
的信息,是
_AFX_BASE_MODULE_STATE
和
_AFX_DLL_MODULE_STATE
的基类
2.
_AFX_BASE_MODULE_STATE
,保存
MFC Module
的状态信息,没有定义其他的成员
3.
_AFX_DLL_MODULE_STATE
,保存
DLL
的状态信息,没有定义其他的成员
4.
AFX_MODULE_THREAD_STATE
,保存主线程的有关状态信息,虽然
AFX_MODULE_THREAD_STATE
是保存的线程的状态信息,但是它只保存
Module
的主线程的状态信息,所以可以看作是
Module State
的一种。
这些
Module State
保存了
MFC
中的大量重要信息:
1.
CWinApp
指针
2.
实例句柄
3.
资源
Module
的句柄
4.
句柄表
5.
OLE
相关信息
6.
窗口过程
7.
Activation Context
8.
……
4.1
AFX_MODULE_STATE
的定义如下:
可以看到:
1.
AFX_MODULE_STATE
从
CNoTrackObject
继承。
CNoTrackObject
定义了自己的
new/delete
保证自己不会被各种调试版本的
new/delete
来
Track
,以免自己被错误的当作
Leak
。
2.
AFX_MODULE_STATE
在
DLL
和非
DLL
(也就是
EXE
)的情况下具有不同的构造函数(和成员)
3.
AFX_MODULE_STATE
在成员中保存了一些和
Module
相关的重要信息
实际上,
AFX_MODULE_STATE
并没有被直接使用,而是作为
_AFX_BASE_MODULE_STATE
和
_AFX_DLL_MODULE_STATE
的基类:
_AFX_BASE_MODULE_STATE
被用于
Module
,其定义如下:
_AFX_DLL_MODULE_STATE
和
_AFX_BASE_MODULE_STATE
类似,只是仅用于
DLL
:
这两个
class
都没有定义额外的成员,比较简单,只是传入到基类
AFX_MODULE_STATE
的参数不同。此外,他们定义的方式不太一样,前者使用的是
PROCESS_LOCAL
宏,定义了一个变量
_afxBaseModuleState
。后者只是简单的定义了一个
static
变量
afxModuleState
。
下面这些函数可以用来获得
Module
的
State
:
1.
AfxGetModuleState
AfxGetModuleState
首先获得
_afxThreadState
的
m_pModuleState
,如果当前的
Thread State
的
m_pModuleState
返回
NULL
,说明当前的
Thread State
没有正确的初始化(通常的原因是创建线程的时候调用的是
CreateThread
函数而非
AfxBeginThread
),则使用
_afxBaseModuleState
。
_afxBaseModuleState
是用
PROCESS_LOCAL
定义的:
它代表整个
MFC Module
的
State
。当你的程序是动态链接到
MFC DLL
的时候,该
State
只有一份。如果你的程序是静态链接到
MFC
的话,有几个模块(
EXE/DLL
)静态链接到
MFC
,
MFC
的代码就有几份,那么
_afxBaseModuleState
也就有几份。
2.
AfxGetStaticModuleState
AfxGetStaticModuleState
在不同的
Project
下面有着不同的行为:在
DLL
项目中,
AfxGetSaticModuleState
返回
afxModuleState
,也就是定义好的
_AFX_DLL_MODULE_STATE
,而在非
DLL
项目中,
AfxGetStaticModuleState
直接调用
AfxGetModuleState
。可以看到,在
DLL
的情况下,必须使用
AfxGetStaticModuleState
才可以获得
DLL
本身的
Module State
。
3.
AfxGetAppModuleState
AfxGetAppModuleState
是最简单的,直接返回
_afxBaseModuleState
:
从上面的讨论可以看出,当前处于那个
MFC Module
的状态之中,返回的就是那个
MFC Module
所相关联的
CWinApp
对象。如果你有多个
Module
都是动态链接到
MFC DLL
的话,那么
AfxGetAppModuleState
返回的总是同一个
CWinApp
。
5.
AFX_MANAGE_STATE
的作用切换到指定的
Module State
,当出了作用域的时候将
Module State
恢复到原来的值。是在不同的
Module State
之中切换,原因有
2
:
1.
在不同的
MFC DLL
和
MFC EXE
的
Module State
之间切换,保持正确的
AFX_MODULE_STATE
,最常见的问题是在
DLL
输出的函数之中无法获得
DLL
本身相关的资源,这就是没有正确维护
Module State
的原因造成的,因为当前
Resource DLL
的句柄就保存在
Module State
之中。
2.
切换
Activation Context
,不同的
Module
必然有着不同的
Activation Context
,需要切换。这是属于
Side By Side
的内容,以后我会专门写一篇文章来讲述
Side By Side
和
manifest
的相关信息。
一般的用法如下:
注意这里使用的是
AfxGetStaticModuleState
,而非
AfxGetModuleState
。原因是在
DLL
项目中,
AfxGetStaticModuleState
返回的是
DLL
本身的
Module State
,而
AfxGetModuleState
则是返回当前线程相关的
Module State
,由于一般
DLL
输出的函数是被其他
Module
调用,那么大部分情况下当前线程的
Module State
都是错误的,所以必须得使用
DLL
本身的
Module State
。
AFX_MANAGE_STATE
只是一个宏,如下:
可以看到
AFX_MANAGE_STATE
声明了一个栈上的局部变量
_ctrlState
,类型为
AFX_MAINTAIN_STATE2
。这是一个很常用的
Pattern
,
AFX_MAINTAIN_STATE2
在构造函数的时候会将当前的
Module State
切换为参数中指定的
Module State
:
然后在析构函数的时候将其恢复回来:
可以看到,
AFX_MAINTAIN_STATE2
将当前
_afxThreadState
在
m_pThreadState
中存起来,然后将所指向的
Module State
保存在
m_pPrevModuleState
中。在析构函数中,则使用保存起来的
m_pPrevModuleState
恢复到
m_pThreadState
的
Module State
。除了保存恢复
Module state
之外,
AFX_MAINTAIN_STATE2
也会在切换
Activation Context
。这个
Activation Context
被用来查找
Side By Side Assemblies
,我以后会专门写一篇文章讲述
Side By Side
和
Manifest
相关的一些信息。这次就写到这里。
作者:张羿
1.
Introduction
当我们在用MFC
编程的时候,我们经常用到
AfxGetApp()
来获得当前的
CWinApp
的
Instance
。看看
MFC
的源代码中
AfxGetApp()
的实现,你会发现
AfxGetApp()
的实现并不像一般情况下面那样直接:
_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp() { return afxCurrentWinApp; } #define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp |
调用的是
AfxGetModuleState()
,该函数返回一个
AFX_MODULE_STATE
的指针,其中的一个成员保存着当前的
CWinApp
的指针。可
AfxGetModuleState()
的作用又是什么呢?
此外,当我们在开发
MFC DLL
程序的时候,我们会在每个输出的
DLL
函数前面加上一句
AFX_MANAGE_STATE
:
void SomeMFCDllFunction() { AFX_MANAGE_STATE(AfxGetStaticModuleState()) … |
又是起什么作用呢?从字面上看来,它是
Manage
某种
State
,而
AfxGetStaticModuleState
又是获得
State
的,那么
State
究竟是什么呢?
在
MFC
中,
States
用来保存某种相关的状态信息,分为下面几类:
1.
Process State
,和某个单独的进程绑定起来
2.
Thread State
,和某个单独的线程绑定
3.
Module State
,和
Module
相关
前两种
State
和一般的全局变量十分类似,只是根据需求的不同被绑定于不同的进程
/
线程,如多线程支持等。而
Module State
本身比较特别,
Module State
根据情况的不同,可以是全局,线程,或者进程相关的
State
,并且可以根据要求快速切换。
2.
Process State
常见的Process State
有:
1.
_AFX_WIN_STATE
2.
_AFX_DB_STATE
3.
_AFX_DEBUG_STATE
4.
_AFX_SOCK_STATE
5.
……
从字面上面可以很容易猜出这些状态的用处。
MFC
通过下面的宏来定义
Process State:
#define PROCESS_LOCAL(class_name, ident_name) / AFX_COMDAT CProcessLocal<class_name> ident_name; #define EXTERN_PROCESS_LOCAL(class_name, ident_name) / extern CProcessLocal<class_name> ident_name; |
用
CProcessLocal
模板类定义了一个
CProcessLocal<class_name>
的一个实例作为状态变量,而
EXTERN_PROCESS_LOCAL
则使在头文件中声明此状态变量。
CProcessLocal
的定义如下:
class AFX_NOVTABLE CProcessLocalObject { public: // Attributes CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)()); // Implementation CNoTrackObject* volatile m_pObject; ~CProcessLocalObject(); }; template<class TYPE> class CProcessLocal : public CProcessLocalObject { // Attributes public: AFX_INLINE TYPE* GetData() { TYPE* pData = (TYPE*)CProcessLocalObject::GetData(&CreateObject); ENSURE(pData != NULL); return pData; } AFX_INLINE TYPE* GetDataNA() { return (TYPE*)m_pObject; } AFX_INLINE operator TYPE*() { return GetData(); } AFX_INLINE TYPE* operator->() { return GetData(); } // Implementation public: static CNoTrackObject* AFXAPI CreateObject() { return new TYPE; } }; |
的作用只是一个
Wrapper
,
Hold
一个
TYPE*
的指针,一旦用户调用
GetData
来获得这个指针,
GetData
会首先判断该指针是否为空,如果为空,则创建一个新的实例保存起来,否则返回已有的指针。前提条件是,
TYPE
必须从
CNoTrackObject
继承。任何从
CNoTrackObject
继承的类都拥有自己的
new/delete
,这样此对象便不会被
Debug
的内存分配系统所跟踪而误判为
Leak
。
CNoTrackObject* CProcessLocalObject::GetData( CNoTrackObject* (AFXAPI* pfnCreateObject)()) { if (m_pObject == NULL) { AfxLockGlobals(CRIT_PROCESSLOCAL); TRY { if (m_pObject == NULL) m_pObject = (*pfnCreateObject)(); } CATCH_ALL(e) { AfxUnlockGlobals(CRIT_PROCESSLOCAL); THROW_LAST(); } END_CATCH_ALL AfxUnlockGlobals(CRIT_PROCESSLOCAL); } return m_pObject; } |
3.
Thread State
和Process State
类似,
Thread State
和某个线程绑定起来,
Thread State
有:
1.
_AFX_THREAD_STATE
2.
_AFXCTL_AMBIENT_CACHE
同样的,
Thread State
是被
THREAD_LOCAL
和
EXTERN_THREAD_LOCAL
定义,也有
CThreadLocal
和
CThreadLocalObject
来
Hold
住
Thread State
的指针。
CThreadLocal
和
CProcessLocal
的实现方式不太一样,
CThreadLocal
利用
TLS(Thread Local Storage)
来保存指针,而不是用成员变量。简单来说,
Thread Local Storage
是
Windows
支持的功能,可以在任意线程中保存多个
DWORD
数据,每个这样的
DWORD
数据所占的位置称之为
Slot
,分配数据需要分配一个
Slot
,获得和修改数据
CThreadLocalObject::GetData
的实现如下:
CNoTrackObject* CThreadLocalObject::GetData( CNoTrackObject* (AFXAPI* pfnCreateObject)()) { ENSURE(pfnCreateObject); if (m_nSlot == 0) { if (_afxThreadData == NULL) { _afxThreadData = new(__afxThreadData) CThreadSlotData; ENSURE(_afxThreadData != NULL); } m_nSlot = _afxThreadData->AllocSlot(); ENSURE(m_nSlot != 0); } CNoTrackObject* pValue = static_cast<CNoTrackObject*>(_afxThreadData->GetThreadValue(m_nSlot)); if (pValue == NULL) { // allocate zero-init object pValue = (*pfnCreateObject)(); // set tls data to newly created object _afxThreadData->SetValue(m_nSlot, pValue); ASSERT(_afxThreadData->GetThreadValue(m_nSlot) == pValue); } return pValue; } |
首先判断
m_nSlot
,如果
m_nSlot == 0
,说明该
Thread State
未曾分配,
GetData
函数将会使用
_afxThreadData->AllocSlot
函数分配一个新的
TLS
的
Slot
,保存在
m_nSlot
之中,然后调用
GetThreadValue
检查
pValue
是否为
NULL
,如果是,则创建一个新的对象然后调用
SetValue
把
pValue
设置到该
Slot
之中。
_afxThreadData
的类型为
CThreadSlotData
,是对
TLS API
的一个简单的封装。
_AFX_THREAD_STATE
是一个很常用的
Thread State
,每个
Thread
,都会有自己的一份
_AFX_THREAD_STATE
。
MFC
提供了一个函数
AfxGetThreadState
来获得当前进程的
Thread State
,如果当前的线程还没有
Thread State
,该函数会创建一个新的
Thread State
。
_AFX_THREAD_STATE* AFXAPI AfxGetThreadState() { _AFX_THREAD_STATE *pState =_afxThreadState.GetData(); ENSURE(pState != NULL); return pState; } |
中保存着下列信息:
1.
当前的
m_pModuleState
,每个线程都知道它当前的
Module State
,这个信息被用来获得当前的
Module State
,
AfxGetModuleState
正是这么做的:
AFX_MODULE_STATE* AFXAPI AfxGetModuleState() { _AFX_THREAD_STATE* pState = _afxThreadState; ENSURE(pState); AFX_MODULE_STATE* pResult; if (pState->m_pModuleState != NULL) { // thread state's module state serves as override pResult = pState->m_pModuleState; } else { // otherwise, use global app state pResult = _afxBaseModuleState.GetData(); } ENSURE(pResult != NULL); return pResult; } |
之前的
m_pModuleState
,用来保存之前的
Module State
,用于
Module State
切换,可参考
AFX_MANAGE_STATE
3.
其他信息,具体可以参考
_AFX_THREAD_STATE
的定义
4.
Module State
Module State保存着和
Module
相关的状态信息。
Module
是
Windows
的术语,代表任何一个可执行的代码文件,
EXE
和
DLL
都是
Module
的一种。
Module State
有下面几种:
1.
AFX_MODULE_STATE
,保存
MODULE
的信息,是
_AFX_BASE_MODULE_STATE
和
_AFX_DLL_MODULE_STATE
的基类
2.
_AFX_BASE_MODULE_STATE
,保存
MFC Module
的状态信息,没有定义其他的成员
3.
_AFX_DLL_MODULE_STATE
,保存
DLL
的状态信息,没有定义其他的成员
4.
AFX_MODULE_THREAD_STATE
,保存主线程的有关状态信息,虽然
AFX_MODULE_THREAD_STATE
是保存的线程的状态信息,但是它只保存
Module
的主线程的状态信息,所以可以看作是
Module State
的一种。
这些
Module State
保存了
MFC
中的大量重要信息:
1.
CWinApp
指针
2.
实例句柄
3.
资源
Module
的句柄
4.
句柄表
5.
OLE
相关信息
6.
窗口过程
7.
Activation Context
8.
……
4.1
AFX_MODULE_STATE
AFX_MODULE_STATE的定义如下:
// AFX_MODULE_STATE (global data for a module) class AFX_MODULE_STATE : public CNoTrackObject { public: #ifdef _AFXDLL AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion, BOOL bSystem = FALSE); #else explicit AFX_MODULE_STATE(BOOL bDLL); #endif ~AFX_MODULE_STATE(); CWinApp* m_pCurrentWinApp; HINSTANCE m_hCurrentInstanceHandle; HINSTANCE m_hCurrentResourceHandle; LPCTSTR m_lpszCurrentAppName; // …… 其他成员,从略 }; |
1.
AFX_MODULE_STATE
从
CNoTrackObject
继承。
CNoTrackObject
定义了自己的
new/delete
保证自己不会被各种调试版本的
new/delete
来
Track
,以免自己被错误的当作
Leak
。
2.
AFX_MODULE_STATE
在
DLL
和非
DLL
(也就是
EXE
)的情况下具有不同的构造函数(和成员)
3.
AFX_MODULE_STATE
在成员中保存了一些和
Module
相关的重要信息
实际上,
AFX_MODULE_STATE
并没有被直接使用,而是作为
_AFX_BASE_MODULE_STATE
和
_AFX_DLL_MODULE_STATE
的基类:
_AFX_BASE_MODULE_STATE
被用于
Module
,其定义如下:
class _AFX_BASE_MODULE_STATE : public AFX_MODULE_STATE { public: #ifdef _AFXDLL _AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcBase, _MFC_VER) #else _AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE) #endif { } }; PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState) |
和
_AFX_BASE_MODULE_STATE
类似,只是仅用于
DLL
:
class _AFX_DLL_MODULE_STATE : public AFX_MODULE_STATE { public: _AFX_DLL_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcDllStatic, _MFC_VER) { } }; static _AFX_DLL_MODULE_STATE afxModuleState; |
class
都没有定义额外的成员,比较简单,只是传入到基类
AFX_MODULE_STATE
的参数不同。此外,他们定义的方式不太一样,前者使用的是
PROCESS_LOCAL
宏,定义了一个变量
_afxBaseModuleState
。后者只是简单的定义了一个
static
变量
afxModuleState
。
下面这些函数可以用来获得
Module
的
State
:
1.
AfxGetModuleState
AfxGetModuleState
首先获得
_afxThreadState
的
m_pModuleState
,如果当前的
Thread State
的
m_pModuleState
返回
NULL
,说明当前的
Thread State
没有正确的初始化(通常的原因是创建线程的时候调用的是
CreateThread
函数而非
AfxBeginThread
),则使用
_afxBaseModuleState
。
AFX_MODULE_STATE* AFXAPI AfxGetModuleState() { _AFX_THREAD_STATE* pState = _afxThreadState; ENSURE(pState); AFX_MODULE_STATE* pResult; if (pState->m_pModuleState != NULL) { // thread state's module state serves as override pResult = pState->m_pModuleState; } else { // otherwise, use global app state pResult = _afxBaseModuleState.GetData(); } ENSURE(pResult != NULL); return pResult; } |
是用
PROCESS_LOCAL
定义的:
PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState) |
MFC Module
的
State
。当你的程序是动态链接到
MFC DLL
的时候,该
State
只有一份。如果你的程序是静态链接到
MFC
的话,有几个模块(
EXE/DLL
)静态链接到
MFC
,
MFC
的代码就有几份,那么
_afxBaseModuleState
也就有几份。
2.
AfxGetStaticModuleState
AfxGetStaticModuleState
在不同的
Project
下面有着不同的行为:在
DLL
项目中,
AfxGetSaticModuleState
返回
afxModuleState
,也就是定义好的
_AFX_DLL_MODULE_STATE
,而在非
DLL
项目中,
AfxGetStaticModuleState
直接调用
AfxGetModuleState
。可以看到,在
DLL
的情况下,必须使用
AfxGetStaticModuleState
才可以获得
DLL
本身的
Module State
。
#ifdef _AFXDLL static _AFX_DLL_MODULE_STATE afxModuleState; AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState() { AFX_MODULE_STATE* pModuleState = &afxModuleState; return pModuleState; } #else AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState() { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); return pModuleState; } #endif |
AfxGetAppModuleState
AfxGetAppModuleState
是最简单的,直接返回
_afxBaseModuleState
:
AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState() { return _afxBaseModuleState.GetData(); } |
MFC Module
的状态之中,返回的就是那个
MFC Module
所相关联的
CWinApp
对象。如果你有多个
Module
都是动态链接到
MFC DLL
的话,那么
AfxGetAppModuleState
返回的总是同一个
CWinApp
。
5.
AFX_MANAGE_STATE
AFX_MANAGE_STATE的作用切换到指定的
Module State
,当出了作用域的时候将
Module State
恢复到原来的值。是在不同的
Module State
之中切换,原因有
2
:
1.
在不同的
MFC DLL
和
MFC EXE
的
Module State
之间切换,保持正确的
AFX_MODULE_STATE
,最常见的问题是在
DLL
输出的函数之中无法获得
DLL
本身相关的资源,这就是没有正确维护
Module State
的原因造成的,因为当前
Resource DLL
的句柄就保存在
Module State
之中。
2.
切换
Activation Context
,不同的
Module
必然有着不同的
Activation Context
,需要切换。这是属于
Side By Side
的内容,以后我会专门写一篇文章来讲述
Side By Side
和
manifest
的相关信息。
一般的用法如下:
void SomeMFCDllFunction() { AFX_MANAGE_STATE(AfxGetStaticModuleState()) … |
AfxGetStaticModuleState
,而非
AfxGetModuleState
。原因是在
DLL
项目中,
AfxGetStaticModuleState
返回的是
DLL
本身的
Module State
,而
AfxGetModuleState
则是返回当前线程相关的
Module State
,由于一般
DLL
输出的函数是被其他
Module
调用,那么大部分情况下当前线程的
Module State
都是错误的,所以必须得使用
DLL
本身的
Module State
。
AFX_MANAGE_STATE
只是一个宏,如下:
struct AFX_MAINTAIN_STATE2 { explicit AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pModuleState) throw(); ~AFX_MAINTAIN_STATE2(); protected: #ifdef _AFXDLL AFX_MODULE_STATE* m_pPrevModuleState; _AFX_THREAD_STATE* m_pThreadState; #endif ULONG_PTR m_ulActCtxCookie; BOOL m_bValidActCtxCookie; }; #define AFX_MANAGE_STATE_NO_INIT_MANAGED(p) AFX_MAINTAIN_STATE2 _ctlState(p); #define AFX_MANAGE_STATE(p) _AfxInitManaged(); AFX_MANAGE_STATE_NO_INIT_MANAGED(p) |
AFX_MANAGE_STATE
声明了一个栈上的局部变量
_ctrlState
,类型为
AFX_MAINTAIN_STATE2
。这是一个很常用的
Pattern
,
AFX_MAINTAIN_STATE2
在构造函数的时候会将当前的
Module State
切换为参数中指定的
Module State
:
AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pNewState) throw() { #ifdef _AFXDLL m_pThreadState = _afxThreadState.GetData(); ASSERT(m_pThreadState); if(m_pThreadState) { m_pPrevModuleState = m_pThreadState->m_pModuleState; m_pThreadState->m_pModuleState = pNewState; } else { // This is a very bad state; we have no good way to report the error at this moment // since exceptions from here are not expected m_pPrevModuleState=NULL; m_pThreadState=NULL; } #endif if (AfxGetAmbientActCtx() && pNewState->m_hActCtx != INVALID_HANDLE_VALUE) { m_bValidActCtxCookie = AfxActivateActCtx(pNewState->m_hActCtx, &m_ulActCtxCookie); } else { m_bValidActCtxCookie = FALSE; } } |
// AFX_MAINTAIN_STATE2 functions _AFXWIN_INLINE AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2() { #ifdef _AFXDLL // Not a good place to report errors here, so just be safe if(m_pThreadState) { m_pThreadState->m_pModuleState = m_pPrevModuleState; } #endif if (m_bValidActCtxCookie) { BOOL bRet; bRet = AfxDeactivateActCtx(0, m_ulActCtxCookie); ASSERT(bRet == TRUE); } } |
AFX_MAINTAIN_STATE2
将当前
_afxThreadState
在
m_pThreadState
中存起来,然后将所指向的
Module State
保存在
m_pPrevModuleState
中。在析构函数中,则使用保存起来的
m_pPrevModuleState
恢复到
m_pThreadState
的
Module State
。除了保存恢复
Module state
之外,
AFX_MAINTAIN_STATE2
也会在切换
Activation Context
。这个
Activation Context
被用来查找
Side By Side Assemblies
,我以后会专门写一篇文章讲述
Side By Side
和
Manifest
相关的一些信息。这次就写到这里。
相关文章推荐
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:AfxGetApp()和AFX_MANAGE_STATE()
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- 转:MFC的模块状态(AfxGetApp()和AFX_MANAGE_STATE())
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态
- MFC模块状态(二)AFX_MANAGE_STATE(AfxGetStaticModuleState())