下载本文示例代码
从前文可知,MFC规则DLL被MFC向导自动添加了一个CWinApp的对象,而MFC扩展DLL则不包含该对象,它只是被自动添加了DllMain 函数。对于MFC扩展DLL,开发人员必须在DLL的DllMain函数中添加初始化和结束代码。 从下表我们可以看出三种DLL对DllMain入口函数的不同处理方式:
DLL类型
入口函数
非 MFC DLL
编程者提供DllMain函数
MFC规则 DLL
CWinApp对象的InitInstance 和 ExitInstance
MFC扩展 DLL
MFC DLL向导生成DllMain 函数 对于MFC扩展DLL,系统会自动在工程中添加如下表所示的宏,这些宏为DLL和应用程序的编写提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA这样的宏,在DLL和应用程序中将具有不同的定义,这取决于_AFXEXT宏是否被定义。这使得在DLL和应用程序中,使用统一的一个宏就可以表示出输出和输入的不同意思。在DLL中,表示输出(因为_AFXEXT被定义,通常是在编译器的标识参数中指定/D_AFXEXT);在应用程序中,则表示输入(_AFXEXT没有定义)。
宏
定义
AFX_CLASS_IMPORT
__declspec(dllexport)
AFX_API_IMPORT
__declspec(dllexport)
AFX_DATA_IMPORT
__declspec(dllexport)
AFX_CLASS_EXPORT
__declspec(dllexport)
AFX_API_EXPORT
__declspec(dllexport)
AFX_DATA_EXPORT
__declspec(dllexport)
AFX_EXT_CLASS
#ifdef _AFXEXT AFX_CLASS_EXPORT#else AFX_CLASS_IMPORT
AFX_EXT_API
#ifdef _AFXEXT AFX_API_EXPORT#else AFX_API_IMPORT
AFX_EXT_DATA
#ifdef _AFXEXT AFX_DATA_EXPORT#else AFX_DATA_IMPORT 6.2 MFC扩展DLL导出MFC派生类 在这个例子中,我们将产生一个名为“ExtDll”的MFC扩展DLL工程,在这个DLL中导出一个对话框类,这个对话框类派生自MFC类CDialog。 使用MFC向导生成MFC扩展DLL时,系统会自动添加如下代码:
static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };extern "C" int APIENTRYDllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ){ // Remove this if you use lpReserved UNREFERENCED_PARAMETER( lpReserved ); //说明:lpReserved是一个被系统所保留的参数,对于隐式链接是一个非零值,对于显式链接值是零 if (dwReason == DLL_PROCESS_ATTACH) { TRACE0( "EXTDLL.DLL Initializing!\n" ); // Extension DLL one-time initialization if ( !AfxInitExtensionModule( ExtDllDLL, hInstance )) return 0; // Insert this DLL into the resource chain new CDynLinkLibrary( ExtDllDLL ); } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0( "EXTDLL.DLL Terminating!\n" ); // Terminate the library before destructors are called AfxTermExtensionModule( ExtDllDLL ); } return 1; // ok} 这一段代码含义晦涩,我们需要对其进行解读: (1)上述代码完成MFC扩展DLL的初始化和终止处理; (2)初始化期间所创建的 CDynLinkLibrary 对象使MFC扩展 DLL 可以将 DLL中的CRuntimeClass 对象或资源导出到应用程序; (3)AfxInitExtensionModule函数捕获模块的CRuntimeClass 结构和在创建 CDynLinkLibrary 对象时使用的对象工厂(COleObjectFactory 对象); (4)AfxTermExtensionModule函数使 MFC 得以在每个进程与扩展 DLL 分离时(进程退出或使用AfxFreeLibrary卸载DLL时)清除扩展 DLL; (5)第一条语句static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };定义了一个AFX_EXTENSION_MODULE类的静态全局对象,AFX_EXTENSION_MODULE的定义如下:
struct AFX_EXTENSION_MODULE{ BOOL bInitialized; HMODULE hModule; HMODULE hResource; CRuntimeClass* pFirstSharedClass; COleObjectFactory* pFirstSharedFactory;}; 由AFX_EXTENSION_MODULE的定义我们可以更好的理解(2)、(3)、(4)点。 在资源编辑器中添加一个如图15所示的对话框,并使用MFC类向导为其添加一个对应的类CExtDialog,系统自动添加了ExtDialog.h和ExtDialog.cpp两个头文件。
图15 MFC扩展DLL中的对话框 修改ExtDialog.h中CExtDialog类的声明为:
class AFX_EXT_CLASS CExtDialog : public CDialog{ public: CExtDialog( CWnd* pParent = NULL ); enum { IDD = IDD_DLL_DIALOG }; protected: virtual void DoDataExchange( CDataExchange* pDX ); DECLARE_MESSAGE_MAP()}; 这其中最主要的改变是我们在class AFX_EXT_CLASS CExtDialog语句中添加了“AFX_EXT_CLASS”宏,则使得DLL中的CExtDialog类被导出。共3页。 1 2 3 :
从前文可知,MFC规则DLL被MFC向导自动添加了一个CWinApp的对象,而MFC扩展DLL则不包含该对象,它只是被自动添加了DllMain 函数。对于MFC扩展DLL,开发人员必须在DLL的DllMain函数中添加初始化和结束代码。 从下表我们可以看出三种DLL对DllMain入口函数的不同处理方式:
DLL类型
入口函数
非 MFC DLL
编程者提供DllMain函数
MFC规则 DLL
CWinApp对象的InitInstance 和 ExitInstance
MFC扩展 DLL
MFC DLL向导生成DllMain 函数 对于MFC扩展DLL,系统会自动在工程中添加如下表所示的宏,这些宏为DLL和应用程序的编写提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA这样的宏,在DLL和应用程序中将具有不同的定义,这取决于_AFXEXT宏是否被定义。这使得在DLL和应用程序中,使用统一的一个宏就可以表示出输出和输入的不同意思。在DLL中,表示输出(因为_AFXEXT被定义,通常是在编译器的标识参数中指定/D_AFXEXT);在应用程序中,则表示输入(_AFXEXT没有定义)。
宏
定义
AFX_CLASS_IMPORT
__declspec(dllexport)
AFX_API_IMPORT
__declspec(dllexport)
AFX_DATA_IMPORT
__declspec(dllexport)
AFX_CLASS_EXPORT
__declspec(dllexport)
AFX_API_EXPORT
__declspec(dllexport)
AFX_DATA_EXPORT
__declspec(dllexport)
AFX_EXT_CLASS
#ifdef _AFXEXT AFX_CLASS_EXPORT#else AFX_CLASS_IMPORT
AFX_EXT_API
#ifdef _AFXEXT AFX_API_EXPORT#else AFX_API_IMPORT
AFX_EXT_DATA
#ifdef _AFXEXT AFX_DATA_EXPORT#else AFX_DATA_IMPORT 6.2 MFC扩展DLL导出MFC派生类 在这个例子中,我们将产生一个名为“ExtDll”的MFC扩展DLL工程,在这个DLL中导出一个对话框类,这个对话框类派生自MFC类CDialog。 使用MFC向导生成MFC扩展DLL时,系统会自动添加如下代码:
static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };extern "C" int APIENTRYDllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ){ // Remove this if you use lpReserved UNREFERENCED_PARAMETER( lpReserved ); //说明:lpReserved是一个被系统所保留的参数,对于隐式链接是一个非零值,对于显式链接值是零 if (dwReason == DLL_PROCESS_ATTACH) { TRACE0( "EXTDLL.DLL Initializing!\n" ); // Extension DLL one-time initialization if ( !AfxInitExtensionModule( ExtDllDLL, hInstance )) return 0; // Insert this DLL into the resource chain new CDynLinkLibrary( ExtDllDLL ); } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0( "EXTDLL.DLL Terminating!\n" ); // Terminate the library before destructors are called AfxTermExtensionModule( ExtDllDLL ); } return 1; // ok} 这一段代码含义晦涩,我们需要对其进行解读: (1)上述代码完成MFC扩展DLL的初始化和终止处理; (2)初始化期间所创建的 CDynLinkLibrary 对象使MFC扩展 DLL 可以将 DLL中的CRuntimeClass 对象或资源导出到应用程序; (3)AfxInitExtensionModule函数捕获模块的CRuntimeClass 结构和在创建 CDynLinkLibrary 对象时使用的对象工厂(COleObjectFactory 对象); (4)AfxTermExtensionModule函数使 MFC 得以在每个进程与扩展 DLL 分离时(进程退出或使用AfxFreeLibrary卸载DLL时)清除扩展 DLL; (5)第一条语句static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };定义了一个AFX_EXTENSION_MODULE类的静态全局对象,AFX_EXTENSION_MODULE的定义如下:
struct AFX_EXTENSION_MODULE{ BOOL bInitialized; HMODULE hModule; HMODULE hResource; CRuntimeClass* pFirstSharedClass; COleObjectFactory* pFirstSharedFactory;}; 由AFX_EXTENSION_MODULE的定义我们可以更好的理解(2)、(3)、(4)点。 在资源编辑器中添加一个如图15所示的对话框,并使用MFC类向导为其添加一个对应的类CExtDialog,系统自动添加了ExtDialog.h和ExtDialog.cpp两个头文件。
图15 MFC扩展DLL中的对话框 修改ExtDialog.h中CExtDialog类的声明为:
class AFX_EXT_CLASS CExtDialog : public CDialog{ public: CExtDialog( CWnd* pParent = NULL ); enum { IDD = IDD_DLL_DIALOG }; protected: virtual void DoDataExchange( CDataExchange* pDX ); DECLARE_MESSAGE_MAP()}; 这其中最主要的改变是我们在class AFX_EXT_CLASS CExtDialog语句中添加了“AFX_EXT_CLASS”宏,则使得DLL中的CExtDialog类被导出。共3页。 1 2 3 :
下载本文示例代码
VC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLLVC 动态链接库编程之MFC扩展 DLL
阅读(279) | 评论(0) | 转发(0) |