VC++动态链接库编程之MFC扩展DLL

2006-03-16 10:34:55 来源: 天极网(重庆) 举报
0
分享到:
T + -

前文我们对非MFC DLL和MFC规则DLL进行了介绍,现在开始详细分析DLL的最后一种类型――MFC扩展DLL。

6.1概论

MFC扩展DLL与MFC规则DLL的相同点在于在两种DLL的内部都可以使用MFC类库,其不同点在于MFC扩展DLL与应用程序的接口可以是MFC的。MFC扩展DLL的含义在于它是MFC的扩展,其主要功能是实现从现有MFC库类中派生出可重用的类。MFC扩展DLL使用MFC 动态链接库版本,因此只有用共享MFC 版本生成的MFC 可执行文件(应用程序或规则DLL)才能使用MFC扩展DLL。

从前文可知,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 APIENTRY

DllMain( 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!\ " );

// 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!\ " );

// 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类被导出。

gigi_miao 本文来源:天极网 责任编辑:王晓易_NE0011
分享到:
跟贴0
参与0
发贴
为您推荐
  • 推荐
  • 娱乐
  • 体育
  • 财经
  • 时尚
  • 科技
  • 军事
  • 汽车
+ 加载更多新闻
×

"上985我发现,读书是多数的捷径"

热点新闻

态度原创

精彩推荐
海淘品牌
阅读下一篇

返回网易首页 返回科技首页