MFC中DLL的创建

可创建的MFC DLL有三种:

①  Regular DLLusing shared MFC DLL MFC动态链接常规DLL需要MFC动态链接库。该类型DLL既可以被MFC程序使用也可以被一般的Win32程序使用

②  Regular DLLwith MFC statically linkedMFC静态链接常规DLL。这种DLL将要使用的MFC的类代码直接加入到DLL中,从而使得DLL增大。但这样可以使得程序无需依赖MFC环境,不需要具有MFC动态链接库。该类型DLL既可以被MFC程序使用也可以被一般的Win32程序使用

③  MFCextension DLLMFC扩展DLL。该种类型的DLL要求可以链接到MFC动态链接库。故MFC扩展DLL是在MFC动态链接库基础上创建的。也就是说,要使用该DLL,首先要有MFC动态链接库,并且只能被MFC程序使用

 

第三种MFC DLL工程创建后,会有一个DllMain函数,但前两种DLL工程没有:

DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	……
}
一般来说,不用对该函数做改动。

 

封装自定义代码

常用的封装有两种:纯函数封装类封装

无论是哪一种封装,编译后,都会在Debug或Release文件夹下生成许多文件。其中需要用到的只有.DLL文件与.lib文件,除此之外还有相关的.h文件。

使用自定义DLL需要三个文件:.h.DLL.lib

①  将这三个文件复制到新工程的根目录下。

②  在新工程中将.h文件导入工程并在需要的地方#include。

③  在需要调用DLL中自定义类的地方

#pragma  comment(lib,"MyDll.lib")

然后就可以正常使用DLL中封装的类了。

lib文件是DLL文件的一个代理,记录了DLL中的函数名,但不含实现代码。exe程序会与lib文件进行链接,从而调用DLL中的具体函数。

要将一个纯函数封装到DLL中,则:

1.      纯函数的声明与实现一定要分开。声明在.h文件中,实现在.cpp文件中。

2.      将.h与.cpp正常加入到工程中,然后修改.h中的类声明:

bool  MyFunction();

修改为:

extern "C" _declspec(dllexport) bool  MyFunction();

编译即可。

要将一个自定义类封装到DLL中,则:

1.      将该类的.h与.cpp正常加入到工程中,然后修改.h中的类声明:

class CYuEdit :public CEdit

修改为:

class AFX_EXT_CLASS CYuEdit : public CEdit

AFX_EXT_CLASS关键字用于导出DLL中的函数。只有这样才能使exe程序调用DLL中的函数。

编译即可。

要将一个资源封装到MFC  DLL,则:

1.      若将一个对话框封装在DLL里,首先添加一个对话框资源,然后为该对话框添加类。该类中会绑定该对话框:

 enum { IDD = IDD_DIALOG_TEST};

注意该对话框资源是存在于DLL工程中的,所以在exe中无法识别该资源。可以在DLL中写一个纯函数用于显示对话框,而不要将对话框类的.h直接导入引用工程中。

2.      若需要将.BMP与Icon等资源封装到DLL中,那么直接将相应资源添加进DLL工程,编译即可。比如添加了一个BMP,在DLL的Resource.h该BMP定义为:

#define IDB_BITMAP_TEST     2001

使用资源时,将DLL与lib导入后,新工程依然不能识别上面的BMP的ID。为了可以正确识别,首先要在新工程的Resource.h中定义需要使用的资源,也就是将

#define IDB_BITMAP_TEST     2001

添加到新工程的Resource.h中。

然后就可以引用了。

特别注意两个Resource.h中的BMP资源定义必须相同。

HMODULE等同于HINSTANCE 

HINSTANCE hDllModule;	//DLL句柄
hDllModule = LoadLibrary(_T("DLL_TEST.dll"));
if (hDllModule)
{
	//执行某些操作
	FreeLibrary(hDllModule);
}

上面代码用于获取DLL的句柄以及释放DLL。注意LoadLibrary ()FreeLibrary()是对应的。

根据DLL句柄,可以用两种方法获取DLL中的资源(推荐使用第二种):

①  使用FindResource()LoadResource()配合。该方法可以获取所有类型资源。注意FindResource()要求传入一个HMODULE,而HMODULEHINSTANCE 是相同的,直接传入HINSTANCE 即可。

②  使用各种资源相应的Load函数。如BITMAP的函数为LoadBitmap()。

示例代码:

①  使用FindResource()LoadResource()配合。

HRSRC hRsrc = FindResource(hDllModule, MAKEINTRESOURCE(IDB_BITMAP_TEST), RT_BITMAP);
if (NULL == hRsrc)
{
	return FALSE;
}

//获取资源的大小
DWORD dwSize = SizeofResource(NULL, hRsrc);
if (0 == dwSize)
{
	return FALSE;
}

//加载资源
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
if (NULL == hGlobal)
{
	return FALSE;
}

//锁定资源
LPVOID pBuffer = LockResource(hGlobal);
if (NULL == pBuffer)
{
	return FALSE;
}

//执行某些操作

//释放资源
FreeResource(hGlobal);

注意LockResource()FreeResource()是对应的。

②  使用各种资源相应的Load函数。

    HBITMAP hBitmap=LoadBitmap(hDllModule,MAKEINTRESOURCE(IDB_BITMAP_TEST));        //从DLL中读取BITMAP资源

 

四.纯资源DLL

若要将所有的资源封装进一个DLL中,然后为所有程序共享,那么就需要编写纯资源DLL。纯资源DLL内部只含纯资源。资源DLL使用的是Win32 DLL。

创建项目时,选择Win32Project,在后续的Application Setting页面的Application Type中选择DLL。

然后直接将相应资源添加进DLL工程。

为了避免编译出现错误“: error LNK2001:unresolved external symbol __DllMainCRTStartup@12,在project右键选则properties,Linker->Input->AdditionalDependencies填入:
Debug:加入 msvcrtd.lib
Release:加入 msvcrt.lib

其中Debug与Release的选择在左上角。也可直接选择All Configurations。

编译即可。

纯资源DLL用法跟上面三中2一样。但纯资源DLL没有lib文件,只有DLL文件。

 

对于上面的三与四来说,要引用DLL中的资源就必须保证DLL中的Resource.h与新工程中的Resource.h有相同的资源定义。

但这样是很不方便的,使用者是无法知道DLL中Resource.h的定义的。所以,一般都使用另一种方法:

①   创建DLL工程并添加一个资源。比如:

#define IDB_BITMAP1    1001

②   找到该资源在Resource.h中的定义,也就是上面的代码。然后为该资源修改一个别名:

#define IDB_BITMAP_TEST     1001

③   新建一个.h文件。该文件用于定义所有共享函数与共享资源。然后将上面的代码复制到该.h文件中。

④   将DLL及lib加入新工程后,也要将.h加入新工程。这样,当需要使用DLL中的资源时,就可以通过.h文件得知资源名称与ID。

但该方法依然需要在新工程的Resource.h中再次定义,或者在新工程使用函数前定义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值