7.VC(custom)-解决DLL和主调程序的资源冲突及如何使用Dll的资源
来源:互联网 发布:js onclick 参数 编辑:程序博客网 时间:2024/05/13 04:21
工具:vs2005
在要导出的MFC类加上AFX_EXT_CLASS,即可形成导出类.
1.为什么引起资源冲突?
主调程序和每个DLL都有一个全局唯一的HINSTANCE句柄(HMODULE模块),不管是在主调程序还是DLL中,加载资源都要参考HINSTANCE。主调程序和DLL都可能包含自己的资源,这些资源的ID却不是全局的,可能出现主调程序和某个DLLHINSTANCE中资源ID号相同的情况而发生加载冲突。
2.资源冲突引起的后果?
使用了共享的MFC库之后,默认情况下使用主程序的句柄来加载资源,所以如果DLL和主调程序的资源ID相同的话,会默认调用主调程序的资源,表现为:EXE打算调用DLL中的对话框却显示的是EXE中的对话框,本来DLL要显示a图,由于主调程序上b图的ID和a相同,则实际显示的是b图。
3.函数介绍:
AfxGetResourceHandle:返回值:应用程序调入缺省资源的实例的HINSTANCE句柄(HMODULE模块),也就是资源所在的模块句柄,如使用的是DLL中的资源,那么就应该返回此DLL中的HINSTANCE了。在主调程序调用DLL时,返回的就是主调程序的HINSTANCE。
4.如何让AfxGetResourceHandle返回DLL的HINSTANCE呢?
AfxSetResourceHandle:对应于AfxGetResourceHandle,一个设置,一个获得,将DLL的HINSTANCE传入即可。
5.如何得到DLL的HINSTANCE呢?
Extension DLL的HINSTANCE可以从DLL的AFX_EXTENSION_MODULE结构里得到,在DLL的DllMain函数中new CDynLinkLibrary(XXXDLL);XXXDLL.hResource即为所求,不可用AfxGetInstanceHanle,它总是获得EXE模块句柄,这点要和AfxGetResourceHandle区分开。
我们使用完DLL中的资源要使用EXE中的资源的资源怎么办呢?我们需要在使用完成后用AfxSetResource重新将资源模块的句柄设置为原来的值,如果来保证在资源使用完成后完成这一个工作呢,我们利用C++类的构造和析构机制创建了以下类来解决这个问题:
#pragma onceclass LoadDllResource{HINSTANCE hResourceSaved;public:static HINSTANCE s_hDllResourceHandle;//dll的资源句柄LoadDllResource();~LoadDllResource();};
#include "StdAfx.h"#include "LoadDllResource.h"HINSTANCE LoadDllResource::s_hDllResourceHandle = NULL;LoadDllResource::LoadDllResource(){HINSTANCE hResource = AfxGetResourceHandle();if (hResource == s_hDllResourceHandle)//如果为dll自身调用,hResourceSaved为NULL{hResourceSaved = NULL;}else{hResourceSaved = hResource;//保存调用程序的HINSTANCEAfxSetResourceHandle(s_hDllResourceHandle);}}LoadDllResource::~LoadDllResource(){if (hResourceSaved != NULL){AfxSetResourceHandle(hResourceSaved);//调用完成后要切换回调用程序的HINSTANCE}}
在DllMain的 new CDynLinkLibrary(XXXDLL);
加入代码 LoadDllResource::s_hDllResourceHandle = XXXDLL.hResource;
使用方法:
在DLL类中加入LoadDllResource类(仅加入DLL类),需要加载资源的函数起始加上 LoadDllResource autoRes;//局部变量,函数开始调用构造函数,函数结构调用析构函数。
6.如何使用动态链接库中的资源?
个人使用的方法
把5中的 LoadDllResource声明为导出类,比如在DLL中有资源#define IDB_BUTTON_LEFT 2004,为了使用方便,可以在主调程序的rc中同样定义#define IDB_BUTTON_LEFT 2004,在主调程序中加载DLL的资源可以用如下代码
LoadDllResource autoRes ; m_bmpLeft.LoadBitampEx(MAKEINTRESOURCE(IDB_BUTTON_LEFT));/*IDB_BUTTON_LEFT可用2004替换*/
当然不是所有DLL都会有LoadDllResource类,所以也可以显式加载DLL
HMODULE hDll = ::LoadLibrary(_T("test.dll"));//最好在OnCreate调用LoadLibrary,hDll可以设为成员函数if (hDll){ HMODULE hExe = AfxGetResourceHandle(); AfxSetResourceHandle(hDll); m_bmpLeft.LoadBitampEx(MAKEINTRESOURCE(IDB_BUTTON_LEFT));/*IDB_BUTTON_LEFT可用2004替换*/ AfxSetResourceHandle(hExe); ::FreeLibrary(hDll);//最好在最后OnDestory时调用FreeLibrary}
7.函数介绍:
FindResource用来在一个指定的模块中定位所指定的资源
HRSRC FindResource(HMODULE hModule, //包含所需资源的模块句柄,如果是程序本身,可以置为NULLLPCTSTR lpName, //可以是资源名称或资源IDLPCTSTR lpType //资源类型,在这里也就是我们自己指定的资源类型); HGLOBAL LoadResource( HMODULE hModule, //模块句柄,同上 HRSRC hResInfo //需要加载的资源句柄,这里也就是FindResource的返回值 ); LPVOID LockResource( HGLOBAL hResData //指向内存中要锁定的资源数据块,这里也就是LoadResource的返回值);
LoadResource用来将所指定的资源加载到内存当中
LockResource用来锁定内存中的资源数据块,它的返回值也就是我们要使用的直系指向资源数据的内存指针,是lpvoid指针,也就是可以强制转换成任意需要的指针.另外我们还需要用SizeofResource来确定资源的尺寸,在资源使用完毕后我们不需要使用 UnlockResource和FreeResource来手动地释放资源,因为它们都是16位Windows遗留下来的,在Win32中,在使用完毕后系统会自动回收
下面代码是借鉴过来的,详细的表现了这些函数的使用
BOOL UseCustomResource(){//定位我们的自定义资源,这里因为我们是从本模块定位资源,所以将句柄简单地置为NULL即可HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(ID), TEXT("gif"));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;/*我们用刚才得到的pBuffer和dwSize来做一些需要的事情。可以直接在内存中使用,也可以写入到硬盘文件。这里我们简单的写入到硬盘文件,如果我们的自定义资源是作为嵌入DLL来应用,情况可能要复杂一些*/BOOL bRt = FALSE;FILE* fp = _tfopen(_T("demo.exe"), _T("wb"));if (fp != NULL){if (dwSize == fwrite(pBuffer, sizeof(char), dwSize, fp))bRt = TRUE;fclose(fp);}//FreeResource(hGlobal);return bRt;}
8.怎么做一个纯资源的DLL?(摘录)
纯资源的DLL就是只包含资源的DLL,例如:图标,位图,字符串,声音,视频, 对话框等。使用纯资源DLL可以节约可执行文件的大小,可以被所有的应用程序 所共享,从而提高系统性能。纯资源DLL的编写比普通的DLL要简单的多,首先
创建一个WIN32 DLL工程,不是MFC的DLL,然后创建一个资源文件*.RC,添加到资源DLL的工程中去。然后添加一个初始化DLL的原文件。
#include
extern "C "
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID )
return 1;
这是纯资源DLL所必须需的代码,保存这个文件为*.CPP。编译这个资源DLL。 在应用程序显示的调用这个DLL,使用LoadLibrary函数装入资源 DLL,FindResource和LoadResource来装入各种资源,或者使用下列的特定的
资源装入函数:
FormatMessage
LoadAccelerators
LoadBitmap
LoadCursor
LoadIcon
LoadMenu
LoadString
当资源使用结束,你的应用程序须调用FreeLibrary函数来释放资源。
首先在应用程序中声明一个DLL的句柄,HINSTANCE m_hLibrary;在OnCreate()函数中调用LoadLirbrary(),在OnDestory()中调用FreeLibrary()。
使用方法:
- 7.VC(custom)-解决DLL和主调程序的资源冲突及如何使用Dll的资源
- DLL导出资源问题的解决
- DLL导出资源问题的解决
- DLL导出资源问题的解决
- 资源Dll的应用
- 使用vc封装纯资源dll及调用
- VC纯资源DLL解决国际化问题
- vc纯资源dll解决国际化问题
- VC 纯资源DLL制作及调用
- VC 纯资源DLL制作及调用
- VC 纯资源DLL制作及调用
- VC 纯资源DLL制作及调用
- 在DLL中使用资源 - 主要是解决DLL的对话框导出问题
- 引用dll导致的资源id冲突解决方法
- 写DLL引起与主程序资源冲突的解决方法
- DLL中使用资源的笔记
- 使用DLL封装应用程序的资源
- 资源dll的制作与使用
- Android 自定义 View
- JSP/Servlet 中的汉字编码问题(转)
- set link for CAknMessageQueryDialog
- android progress bar的小实例
- Android.mk文件语法规范
- 7.VC(custom)-解决DLL和主调程序的资源冲突及如何使用Dll的资源
- 一些现象
- ORA-03135: connection lost contact;ORA-02068
- 汇编 各个 段
- Oracle RAC CRS-0184 --Cannot communicate with the CRS daemon
- Android2.2 API 中文文档系列(1) —— TextView
- nginx phases 详细介绍
- 2011_New_Out Ref 面试题举例说明
- 硬盘安装Ubuntu10.04与XP 双系统