文章相关视频教程下载地址http://pan.baidu.com/s/1mhKxdbU
3.4编程实现模块切换
解决上述问题的方法是模块切换,即将资源模块句柄设置为DLL模块的起始地址,之后显示的对话框即为DLL模块中ID为5000的对话框了。
可以通过两种方法实现模块切换,一种是在DLL中实现切换,另一种是在调用DLL的程序中实现切换。
3.4.1 在DLL中实现模块切换
在DLL中,可以使用AFX_MANAGE_STATE宏或者AfxSetResourceHandle()函数实现模块切换。
(1)使用AFX_MANAGE_STATE宏
在MFC_Regular_Static_DLL_Test的导出函数ShowDialog()中加入如下代码
AFX_MANAGE_STATE(AfxGetStaticModuleState());
其中,AFX_MANAGE_STATE宏的作用是设置当前的有效模块状态。AfxGetStaticModuleState()函数的作用是获取DLL模块的状态。
重新生成MFC_Regular_Static_DLL_Test.dll并将其拷贝到调用该DLL的MFC程序源代码所在的路径下,运行MFC程序的效果如图8所示
图8 弹出对话框为DLL对话框资源
(2)使用AfxSetResourceHandle()函数
AfxSetResourceHandle()函数的作用是设置程序目前要使用的资源模块句柄。在动态库的导出函数ShowDialog()中将AFX_MANAGE_STATE宏注释掉,之后添加如下代码
HINSTANCE hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_hInstance);
CDllDialog dlg;
dlg.DoModal();
AfxSetResourceHandle(hInstance);
其中,AfxGetResourceHandle()的作用是获取当前资源模块的句柄,该句柄即为调用DLL的MFC程序的句柄;之后通过AfxSetResourceHandle()函数将当前资源模块的句柄设置为本模块即DLL模块的句柄,theApp是MFC规则动态库应用程序的对象,m_hInstance()是该应用程序的句柄;在显示了DLL中的对话框资源之后,再次调用AfxSetResourceHandle()函数将当前资源模块的句柄恢复为调用DLL的MFC程序的资源句柄。
将重新生成的MFC_Regular_Static_DLL_Test.dll拷贝到调用DLL的MFC程序源代码所在的文件夹中,运行该MFC程序,得到的效果与“(1)使用AFX_MANAGE_STATE宏”中的效果相同,如图8所示。
3.4.2 在调用DLL的MFC程序中实现切换
在调用DLL的MFC程序的按键消息响应函数中调用AfxSetResourceHandle()函数实现模块切换。
HINSTANCE exe_hHandle = GetModuleHandle(NULL);
HINSTANCE dll_hHandle = GetModuleHandle(_T("MFC_Regular_Share_DLL_Test.dll"));
AfxSetResourceHandle(dll_hHandle);
pShowDialog();
AfxSetResourceHandle(exe_hHandle);
其中,GetModuleHandle()函数的作用是获取模块的句柄,如果该函数的参数指定要获取句柄的模块,如果是NULL,则表示获取的是本模块的句柄。通过GetModuleHandle()函数获取到了MFC_Regular_Static_DLL_Test.dll的句柄之后,再通过AfxSetResourceHandle()函数实现模块切换。当前资源模块的句柄切换到动态库模块句柄后,调用动态库的导出函数ShowDialog(),显示动态库模块中的对话框资源,最后再将当前资源模块的句柄恢复成调用DLL的MFC程序的句柄。
将MFC_Regular_Static_DLL_Test.dll的导出函数ShowDialog()中关于环境切换的代码注释掉,只留下调用对话框资源的代码
CDllDialog dlg;
dlg.DoModal();
重新生成DLL文件后,将其拷贝到调用DLL的MFC程序源代码所在的文件夹中,运行MFC程序,得到的效果与“(1)使用AFX_MANAGE_STATE宏”中的效果相同,如图8所示。