在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); }