C++动态链接库DLL文件的资源切换

本文详细探讨了在MFC应用程序与规则DLL共享MFCDLL时,如何正确处理资源模块句柄切换和线程状态管理。方法包括在DLL接口函数中临时切换模块状态、通过AfxGetResourceHandle设置资源句柄以及由应用程序自身控制状态转换。

1、问题描述

// switch thread state back to application
_AFX_THREAD_STATE* pState = AfxGetThreadState();
AfxSetModuleState(pState->m_pPrevModuleState);

// do something with the application
AfxGetApp()->…

// switch thread state back to dll
AFX_MANAGE_STATE(AfxGetStaticModuleState())

我们知道,在MFC应用程序中CWinApp取代了SDK程序中WinMain的地位,SDK程序WinMain所完成的工作由CWinApp的三个函数完成:

virtual BOOL InitApplication( );
virtual BOOL InitInstance( );
virtual BOOL Run( ); //传说中MFC程序的“活水源头”

但是MFC规则DLL并不是MFC应用程序,它所继承自CWinApp的类不包含消息循环。这是因为,MFC规则DLL不包含 CWinApp::Run机制,主消息泵仍然由应用程序拥有。如果DLL 生成无模式对话框或有自己的主框架窗口,则应用程序的主消息泵必须调用从DLL 导出的函数来调用PreTranslateMessage成员函数。

另外,MFC规则DLL与MFC 应用程序中一样,需要将所有 DLL中元素的初始化放到InitInstance 成员函数中。

与非MFC DLL完全相同,我们可以使用__declspec(dllexport)声明或在.def中引出的方
式导出MFC规则DLL中的接口。

共享MFC DLL(或MFC扩展DLL)的规则DLL涉及到HINSTANCE句柄问题,HINSTANCE句柄对于加载资源特别重要。EXE和DLL都有其自己的 资源,而且这些资源的ID可能重复,应用程序需要通过资源模块的切换来找到正确的资源。如果应用程序需要来自于DLL的资源,就应将资源模块句柄指定为 DLL的模块句柄;如果需要EXE文件中包含的资源,就应将资源模块句柄指定为EXE的模块句柄。

2、解决方法

产生这个问题的根源在于应用程序与MFC规则DLL共享MFC DLL(或MFC扩展DLL)的程序总是默认使用EXE的资源,我们必须进行资源模块句柄的切换,其实现方法有三:

2.1 在DLL接口函数中使用:

AFX_MANAGE_STATE(AfxGetStaticModuleState()); 

void ShowDlg(void)
{ 
//方法1:在函数开始处变更,在函数结束时恢复
//作为接口函数的第一//条语句进行模块状态切换
//将AFX_MANAGE_STATE(AfxGetStaticModuleState());

AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog dlg(IDD_DLL_DIALOG);//打开ID为2000的对话框
dlg.DoModal();
}

2.2 在DLL接口函数中使用2:

AfxGetResourceHandle();
AfxSetResourceHandle(HINSTANCE xxx);

extern CSharedDllApp theApp; //需要声明theApp外部全局变量
void ShowDlg(void)
{ 
//方法2的状态变更
HINSTANCE save_hInstance = AfxGetResourceHandle(); 
AfxSetResourceHandle(theApp.m_hInstance); 

CDialog dlg(IDD_DLL_DIALOG);//打开ID为2000的对话框
dlg.DoModal();

//方法2的状态还原
AfxSetResourceHandle(save_hInstance);

//使用方法2后在此处再进行操作针对的将是应用程序的资源
CDialog dlg1(IDD_DLL_DIALOG); //打开ID为2000的对话框
dlg1.DoModal();
}

2.3 由应用程序自身切换

void CSharedDllCallDlg::OnCalldllButton() 
{
//方法3:由应用程序本身进行状态切换
//获取EXE模块句柄

HINSTANCE exe_hInstance = GetModuleHandle(NULL); 

//或者HINSTANCE exe_hInstance = AfxGetResourceHandle(); 
//获取DLL模块句柄

HINSTANCE dll_hInstance = GetModuleHandle("SharedDll.dll"); 
AfxSetResourceHandle(dll_hInstance); //切换状态
ShowDlg(); //此时显示的是DLL的对话框 
AfxSetResourceHandle(exe_hInstance); //恢复状态

//资源模块恢复后再调用ShowDlg
ShowDlg(); //此时显示的是EXE的对话框
}

后记

如果你觉得这些文字有一点点用处,可以给作者点个赞;╮( ̄▽ ̄)╭
如果你感觉作者写的不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
谢谢各位小伙伴们啦( ´ ▽ ‘)ノ ( ´ ▽ ` )っ!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值