win32 - 内部.dll对话框

Jar*_*lár 1 c++ dll winapi dialog

我想要一个创建.dll,它显示了一些对话框.

在我的.dll中我有这段代码:

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

ShowError调用消息框,GetLastErrorAsString()只调用标准GetLastError并转换为字符串.
我有这个输出:

无法在映像文件中找到指定的资源类型.

然后我有一个标准的win32 Window应用程序,我调用方法,调用上面提到的代码.

DialogTest test;
test.showDialog(); // calls functionality from .dll
Run Code Online (Sandbox Code Playgroud)

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

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

IIn*_*ble 6

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

hInstance [in,optional]

类型:HINSTANCE

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

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

简单的解决方案:选择传递给DllMainhInstance并将其存储在全局变量中供以后使用.

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;
}
Run Code Online (Sandbox Code Playgroud)

强大的解决方案:此解决方案可以在任何地方,DLL,EXE或静态LIB中使用.只有缺点:它依赖于微软链接器的无证功能.不过不用担心,它不会无声地失败.

EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISMODULE ((HINSTANCE)&__ImageBase)
Run Code Online (Sandbox Code Playgroud)

HINST_THISMODULE无论在何处使用,都将始终保持正确的值.1)

使用官方接口(GetModuleHandleEx)也可以实现同样的目的.以下解决方案也可以从EXE,DLL或静态LIB中使用,只要您确保将函数编译并链接到相应的模块中:

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

    return hModule;
}
Run Code Online (Sandbox Code Playgroud)

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


1)静态库访问当前模块的HINSTANCE

2) HINSTANCE和HMODULE有什么区别?