GetModuleHandle (NULL) против hInstance
При программировании с использованием Windows API я всегда делал глобальную переменную HINSTANCE
from WinMain
. Если я хочу сделать кнопку ОК, я бы сделал это так (с учетом глобальной 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)
для явного указания дескриптора экземпляра?
Fine Print: Я знаю, что у этого есть ответ, но он не был сформулирован как его собственный вопрос в StackOverflow.
Ответы
Ответ 1
В EXE это не имеет никакого значения. hInstance
из WinMain()
и GetModuleHandle(NULL)
оба ссылаются на одно и то же HINSTANCE
(модуль файла .exe). Но это имеет значение, если вы вместо этого создаете окна внутри DLL, так как вам нужно использовать hInstance
DLL, но GetModuleHandle(NULL)
все равно вернет HINSTANCE
EXE- HINSTANCE
который загрузил DLL.
Ответ 2
HMODULE WINAPI GetModuleHandle( _In_opt_ LPCTSTR lpModuleName );
Отдайте дескриптор модуля имени модуля. Если вы передаете NULL, вы получите дескриптор модуля EXE, который в настоящее время запущен.
Если вы конкретно называете имя модуля, вы получаете дескриптор модуля этой DLL, который сопоставляется с адресным пространством процесса.
Использование заключается в том, что когда вы пытаетесь вызвать функцию, экспортируемую DLL, или пытаетесь использовать шаблон диалога со стороны dll. В это время, если вы используете возвращаемую форму HMODULE GetMoudleHandle (NULL), ваш код не будет работать.
Ответ 3
Одна потенциальная выгода, которую вы получаете от использования GetModuleHandle (NULL) по сравнению с прямым использованием WinMain HINSTANCE, связана с архитектурой. Если вы хотите предоставить независимую от платформы систему, которая работает на linux/windows/что угодно, у вас может быть слой, который выполняет зависящие от платформы переводы. В этом случае вы не хотите, чтобы зависимые от платформы объекты, такие как HINSTANCE, отображались в основном коде приложения. Итак, чтобы обойти эту зависимость от платформы, я поместил GetModuleHandle (NULL) в конструктор класса, зависящего от платформы, который имеет тот же эффект, что и прямое использование WinMain HINSTANCE, но абстрагирует эту специфическую функциональность от основной базы кода.
Ответ 4
Просто чтобы добавить мои два цента к этим ответам. В случае, если вам нужно получить дескриптор модуля из 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;
}