使用Windows API进行编程时,我总是立即将HINSTANCE
从WinMain
作为全局变量。如果我想制作一个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上没有被表达为自己的问题。
答案 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;
}