2015-08-26 43 views
0

我想创建一个.dll文件,它会显示一些对话框。win32 - 对话框里面的.dll

在我的.dll我有这样的代码:

HWND hDlg = CreateDialogParam(NULL, MAKEINTRESOURCE(IDD_RANKING_DIALOG), NULL, msgProc, NULL); 
if (!hDlg) { 
    ShowError(GetLastErrorAsString().c_str()); 
    return false; 
} 

ShowError调用消息框,GetLastErrorAsString()只是调用标准GetLastError,并将其转换为字符串。
我有这样的输出:

在图像文件中找不到指定的资源类型。

然后我有一个标准的win32窗口应用程序,在那里我调用方法,它调用上述代码。

DialogTest test; 
test.showDialog(); // calls functionality from .dll 

我在做什么错了?我需要将资源文件链接到.dll吗?

我正在使用Visual Studio 2010和dialog在我的资源文件(.rc)中指定。

+4

您在'hInstance'参数传递'NULL'到'CreateDialogParam()'。这意味着对话资源将被加载到已加载DLL的可执行文件中,而不是在DLL本身中查找。您应该传递与您的DLL相关的'HINSTANCE'。 –

+0

我曾尝试使用GetModuleHandle(0)而不是NULL,但它并没有帮助。那么我怎么才能得到DLL的HINSTANCE。 –

+1

它作为第一个参数传递给你的'DllMain()'。 –

回答

2

您指定了NULL作为CreateDialogParam的第一个参数。不过,如果你想从DLL本身加载

HWND hDlg = CreateDialogParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_RANKING_DIALOG), NULL, msgProc, NULL); 

,你应该用HINSTANCE替换第一个参数:如果要加载从Win32窗口应用程序的对话框资源文件,你应该使用这个参数来自DLL的DllMain入口点函数。

+1

不,'GetModuleHandle(NULL)'返回与当前可执行文件相关的模块,而不是DLL。 –

+0

@FrédéricHamidi感谢您指出这一点,我相信我已更正了答案 –

+1

是的,但不需要调用GetModuleHandle()。如果要从当前可执行文件的模块加载资源,只需将'NULL'传递给'CreateDialogParam()'。 –

5

错误代码和消息是准确的:在指示系统去查找资源的位置找不到资源:用于启动进程的可执行映像,而不是您的DLL。该行为被记录在案(见CreateDialogParam):

的hInstance [中,可选]

类型:HINSTANCE

句柄包含对话框模板模块。如果此参数为NULL,则使用当前的可执行文件。

由于您将对话框模板存储在您的DLL中,因此您必须通过标识您的DLL的HINSTANCE。有很多方法可以获得正确的值,但通过NULLGetModuleHandle(NULL)将不起作用。这两个都将模块句柄返回到启动进程的可执行映像(而不是您的DLL)。

最简单的办法:挑的hInstance传递到您的DllMain并将其储存在供以后使用全局变量。

HINSTANCE g_hInst = NULL; 

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 
    switch (fdwReason) { 
    case DLL_PROCESS_ATTACH: 
     g_hInst = hinstDLL; 
     break; 
    default: 
     break; 
    } 
    return TRUE; 
} 

强大的解决方案:该解决方案可以在任何地方,DLL,EXE或静态LIB中使用。唯一的缺点:它依赖于微软链接器的未公开的特性。不过不要担心,它不会默默地失败。

EXTERN_C IMAGE_DOS_HEADER __ImageBase; 
#define HINST_THISMODULE ((HINSTANCE)&__ImageBase) 

HINST_THISMODULE将始终保持正确的值,不管它是用来在何处。 1)

同样可以使用官方接口(GetModuleHandleEx)来实现。以下解决方案可以从EXE,DLL中,或静态库使用为好,只要你确保编译和功能链接到相应的模块:

HMODULE GetCurrentModuleHandle() { 
    HMODULE hModule = NULL; 
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
         (LPCTSTR)GetCurrentModuleHandle, 
         &hModule); 

    return hModule; 
} 

这将返回HMODULE,不一个HINSTANCE。但这不是问题,因为它们是相同的东西2)


1)Accessing the current module's HINSTANCE from a static library

2)What is the difference between HINSTANCE and HMODULE?

+0

谢谢,所有的解决方案看起来都正确,但我尝试了这一点,它的工作原理。 –

相关问题