原创作品,请大家指教:如何使用动态链接库中的资源

DentistryDoctor 2004-08-21 12:41:21
近来在论坛上很有多帖子问到如何使用DLL中的资源(包括对话框,图标等)的问题,现在笔者就来就此问题谈谈,包含在DLL内部使用资源,DLL中使用其它DLL中的资源和在应用程序中使用资源。
我们先以图标为例说起(其它的资源与此图标的加载原理大致相同),我们要加载图标,一般是调用AfxGetApp()->LoadIcon(…);下面是CWinApp::LoadIcon的实现(afxwin2.inl):
_AFXWIN_INLINE HICON CWinApp::LoadIcon(LPCTSTR lpszResourceName) const
{ return ::LoadIcon(AfxFindResourceHandle(lpszResourceName,
RT_GROUP_ICON), lpszResourceName); }
_AFXWIN_INLINE HICON CWinApp::LoadIcon(UINT nIDResource) const
{ return ::LoadIcon(AfxFindResourceHandle(MAKEINTRESOURCE(nIDResource),
RT_GROUP_ICON), MAKEINTRESOURCE(nIDResource)); }
可以看到CWinApp::LoadIcon实际上调用了API .LoadIcon,下面是API LoadIcon的原型:
HICON LoadIcon(

HINSTANCE hInstance,
LPCTSTR lpIconName
);

hInstance
[in] Handle to an instance of the module whose executable file contains the icon to be loaded. This parameter must be NULL when a standard icon is being loaded.
hInstance是我们要加载ICON的模块实例,这个实例从何来,当然我们可以直接传入DLL的实例,对于通过LoadLibrary动态加载的DLL我们可以很容易的得到其句柄,但对于我们直接链接的DLL得到其句柄则要费一番周折。可以看到CWinApp::LoadIcon是通过AfxFindResouceHandle找到此句柄的。下面是AfxFindResourceHandle的定义(afxwin.h):
#ifndef _AFXDLL
#define AfxFindResourceHandle(lpszResource, lpszType) AfxGetResourceHandle()
#else
HINSTANCE AFXAPI AfxFindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType);
#endif
我们先讨论在静态链接库中使用MFC DLL的情况。可以看到,我们如果在静态库中使用MFC DLL的话(#ifndef _AFXDLL),实际上就是调用的AfxGetResourceHandle,MSDN中的说明是
AfxGetResourceHandle
This function accesses the application’s resources directly by using the HINSTANCE handle returned, for example, in calls to the Windows function FindResource.
HINSTANCE AfxGetResourceHandle( );
Return Value
An HINSTANCE handle where the default resources of the application are loaded.
函数返回的应用程序加载的缺省资源的HINSTANCE句柄,HINSTANCE相当于HMODULE,也就是资源所在的模块句柄。显然在此,我们使用的是DLL中的资源,那么我们就应该返回此DLL中的HINSTANCE了,如果让AfxGetResourceHandle返回DLL的HINSTANCE呢?答案是通过AfxSetResourceHandle设置。MSDN中AfxSetResouceHandle的说明如下:
AfxSetResourceHandle
This function sets the HINSTANCE handle that determines where the default resources of the application are loaded.
void AfxSetResourceHandle(
HINSTANCE hInstResource );
Parameters
hInstResource
Specifies the instance or module handle to an .EXE or DLL file from which the application’s resources are loaded.
我们只需将DLL的HINSTANCE传入AfxSetResouceHanle就行了。如何得到DLL的HINSTANCE呢,我们可以通过DLL声明一个接口HINSTANCE GetInstance获得,也可以通过EnumProcessMoudules找到(详细的过程见MSDN中EnumProcessModules的说明和示例)。
我们使用完DLL中的资源要使用EXE中的资源的资源怎么办呢?我们需要在使用完成后用AfxSetResource重新将资源模块的句柄设置为原来的值,如果来保证在资源使用完成后完成这一个工作呢,即使在使用过程中发生异常了,为此我们利C++类的构造和析构机制创建了这一类:
class CLocalResource
{
public:
CLocalResource(HINSTANCE hInstance)
{
m_hInstOld=AfxGetInstanceHandle();
AfxSetInstanceHandle(hInstance);
}
virtual ~CLocalResource()
{
AfxSetInstanceHandle(m_hInstOld);
}
protected:
HINSTANCE m_hInstOld;
};
我们只需在使用DLL的资源之前构造一个CLocalInstance就行了。
void CXXXX::LoadResouceFromDLL(HINSTANCE hInst,UINT nResID,…)
{
CLocalResouce localRes(hInst);

}
下面来讨论在动态库中使用MFC DLL的情况(也就是定义了_AFXDLL的情况)
来看看AfxGetInstanceHandle ,AfxGetResourceHandle和AfxSetResouceHandle的实现(afxwin1.inl中):
_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetInstanceHandle()
{ ASSERT(afxCurrentInstanceHandle != NULL);
return afxCurrentInstanceHandle; }
_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle()
{ ASSERT(afxCurrentResourceHandle != NULL);
return afxCurrentResourceHandle; }
_AFXWIN_INLINE void AFXAPI AfxSetResourceHandle(HINSTANCE hInstResource)
{ ASSERT(hInstResource != NULL); afxCurrentResourceHandle = hInstResource; }
实际上访问的就是afxCurrentInstanceHandle,afxCurrentResourceHandle。
/////////////////////////////////////////////////////////////////////////////
// Global functions for access to the one and only CWinApp

#define afxCurrentInstanceHandle AfxGetModuleState()->m_hCurrentInstanceHandle
#define afxCurrentResourceHandle AfxGetModuleState()->m_hCurrentResourceHandle
….
AFX_MODULE_STATE* AFXAPI AfxGetModuleState()
{
_AFX_THREAD_STATE* pState = _afxThreadState;
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();
}
ASSERT(pResult != NULL);
return pResult;
}
其中的_AFX_THREAD_STATE在此我们就不讨论了,有兴趣的读者可以阅读(afxstat_.h和afxstate.cpp)。
那AfxGetModuleState()->m_hCurrentResourceHandle又是在哪初始化的呢?
...全文
1302 27 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
yamyuyang 2005-08-29
  • 打赏
  • 举报
回复
排版好点就完美了
v111v111 2005-08-25
  • 打赏
  • 举报
回复
仔细看看,在欣赏之前先支持一下楼主先!
snowbirdfly 2005-08-06
  • 打赏
  • 举报
回复
收藏,感谢楼主!
小蕊_claudia 2005-08-05
  • 打赏
  • 举报
回复
学习
亿云力科技 2005-08-05
  • 打赏
  • 举报
回复
mark
AntonlioX 2005-06-18
  • 打赏
  • 举报
回复
收藏
univer1 2005-06-14
  • 打赏
  • 举报
回复
m
gogowhy 2005-04-01
  • 打赏
  • 举报
回复
m
  • 打赏
  • 举报
回复
好贴,正好用的上,谢谢
blastzgd 2005-01-11
  • 打赏
  • 举报
回复
up
BaseCN_JW 2004-12-02
  • 打赏
  • 举报
回复
虽然结贴了,还是回得一下吧。这贴内容正是我现在要用的,找了一些资料讲得不太细。谢谢楼主
wangk 2004-11-24
  • 打赏
  • 举报
回复
mark
老夏Max 2004-10-21
  • 打赏
  • 举报
回复
Mark!!
DentistryDoctor 2004-08-27
  • 打赏
  • 举报
回复
THE END
yszmax 2004-08-25
  • 打赏
  • 举报
回复
收藏
阿馨 2004-08-25
  • 打赏
  • 举报
回复
收藏
tangshiping 2004-08-24
  • 打赏
  • 举报
回复
要不楼主的另一帖人气就大好呢?!
tangshiping 2004-08-24
  • 打赏
  • 举报
回复
其实很多人看此帖的,大家不发言还有一个原因,此帖无分,呵呵。唉,世态炎凉啊
tangshiping 2004-08-24
  • 打赏
  • 举报
回复
我始终支持,不是大家不支持,一是因为大家都忙,没有时间常上论坛,再者被楼主吓住了,高手面前不敢发言了,呵呵,至于斑竹吗,默默的支持你,不信你问
DentistryDoctor 2004-08-24
  • 打赏
  • 举报
回复
也许是小弟新来CSDN的原因吧,没人气!
加载更多回复(7)

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧