GetModuleHandle(NULL)vs hInstance

时间:2014-02-12 03:31:28

标签: c++ winapi visual-c++

使用Windows API进行编程时,我总是立即将HINSTANCEWinMain作为全局变量。如果我想制作一个OK按钮,我就这样做(给定全局HINSTANCE g_hInstance):

return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, g_hInstance, NULL);

但是最近我一直看到实例句柄已确定,无需通过调用GetModuleHandle(NULL) *来作为参数传递或堵塞全局命名空间。所以,上面的例子看起来像这样:

return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, GetModuleHandle(NULL), NULL);

*如果您的编译器支持它,您可以编写GetModuleHandle(nullptr)并且该语句将具有相同的结果。

调用GetModuleHandle(NULL)而不是显式指定实例句柄的优点(如果有的话)是什么?

精细打印:我知道这有一个答案,但它在StackOverflow上没有被表达为自己的问题。

4 个答案:

答案 0 :(得分:27)

在EXE中,它没有任何区别,来自hInstance的{​​{1}}和WinMain()都引用相同的GetModuleHandle(NULL)(.exe文件的模块) 。但是如果你在DLL中创建窗口确实会有所不同,因为你必须使用DLL的HINSTANCE,但hInstance仍会返回加载了它的EXE的GetModuleHandle(NULL) DLL。

答案 1 :(得分:2)

HMODULE WINAPI GetModuleHandle( _In_opt_  LPCTSTR lpModuleName );

传递模块名称的模块句柄。如果传递NULL,则获取当前正在运行的EXE的模块句柄。 如果您专门命名模块名称,则会获得映射到进程地址空间的该DLL的模块句柄。 用法是当你试图调用由dll导出的函数,或者试图在dll那边使用对话框模板时。如果你使用HMODULE返回的表格GetMoudleHandle(NULL)那么你的代码将不起作用。

答案 2 :(得分:1)

通过使用GetModuleHandle(NULL)而不是直接使用WinMain HINSTANCE获得的潜在收益来自体系结构。如果要提供一个在linux / windows /上运行的与平台无关的系统,则可以有一个执行平台相关翻译的层。如果是这种情况,您不希望在主应用程序代码中显示依赖于平台的对象,例如HINSTANCE。因此,为避免平台依赖性,我将GetModuleHandle(NULL)放入平台依赖性类的构造函数中,该构造函数具有与直接使用WinMain HINSTANCE相同的作用,但是从主代码库本身中提取了该特定功能。 / p>

答案 3 :(得分:0)

只需在这些答案中加上两美分即可。如果您需要从DLL中获取模块句柄(并且不想或无法通过DllMain调用将其保存在全局变量中),则可以使用以下函数来获取它:

HMODULE getThisModuleHandle()
{
    //Returns module handle where this function is running in: EXE or DLL
    HMODULE hModule = NULL;
    ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 
        GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 
        (LPCTSTR)getThisModuleHandle, &hModule);

    return hModule;
}