现在的位置: 首页 > 综合 > 正文

MFC扩展dll里导出函数时资源切换的问题

2013年06月29日 ⁄ 综合 ⁄ 共 1837字 ⁄ 字号 评论关闭

在MFC扩展dll里导出函数时应该也进行资源的切换。

在共享的(动态链接的)MFC规则dll里,在每一个导出函数前都需进行资源的切换,在扩展dll里同样也需要,因为它们都是动态链接到MFC库
的,在调用导出函数时,若要加载对应的资源,MFC会首先从应用程序模块里查找,找不到时才从dll中查找,所以若存在同名的资源,则可能会加载错误。

例子:
dll:
MFCExtDll,它里边存在一个对话框资源IDD_DIALOG2,它对应的编号是2000,在resource.h里有如下定义
#define IDD_DIALOG2   2000

该dll有一个导出函数如下所示:
extern "C" __declspec(dllexport) void ShowDlg(void)

{

   //HINSTANCE save_hInstance = AfxGetResourceHandle();
   //AfxSetResourceHandle(theInstance);

   CDialog dllDialog(IDD_DIALOG2);
   dllDialog.DoModal();

//AfxSetResourceHandle(save_hInstance);
}

调用dll的应用程序:
MFCExtDllCall,它里边有一个对话框资源IDD_DIALOG1,编号也是2000,在resource.h里有如下定义
#define IDD_DIALOG1   2000

调用导出函数处如下:
void CMFCExtDllCallDlg::OnButton1()

{

// TODO: Add your control notification handler code here
typedef void (*lpFun)(void);

HINSTANCE hDll;   //DLL句柄
hDll = LoadLibrary("MFCExtDll.dll");
if (NULL==hDll)
{
   MessageBox("DLL加载失败");
}

lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");
if (NULL==pShowDlg)
{
   MessageBox("DLL中函数寻找失败");
}
pShowDlg();
}

此时,弹出的对话框不是dll中定义的对话框资源DIALOG2,而是应该程序中的DIALOG1,即由于它们的id重复造成了加载资源时的错误。

解决办法:
若dll是规则dll,则方法有三种,详见“VC++动态链接库(DLL)编程深入浅出(全)【三】”;现在是MFC扩展dll,也可借鉴其方法,如下:
1、在dll加载时,即DllMain函数处获得该dll的句柄:
HINSTANCE theInstance;

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);

if (dwReason == DLL_PROCESS_ATTACH)
{
   TRACE0("MFCEXTDLL.DLL Initializing!/n");
  
   // Extension DLL one-time initialization
   if (!AfxInitExtensionModule(MFCExtDllDLL, hInstance))
    return 0;

   new CDynLinkLibrary(MFCExtDllDLL);

   theInstance = hInstance;

}
else if (dwReason == DLL_PROCESS_DETACH)
{
   TRACE0("MFCEXTDLL.DLL Terminating!/n");
   // Terminate the library before destructors are called
   AfxTermExtensionModule(MFCExtDllDLL);
}
return 1;   // ok
}
2、在导出函数处进行资源的切换:
extern HINSTANCE theInstance;
ExportFun
{
HINSTANCE save_hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theInstance);

···

AfxSetResourceHandle(save_hInstance);
}

抱歉!评论已关闭.