GetModuleHandle(NULL) против hInstance

При программировании с использованием Windows API я всегда делал HINSTANCE от 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: я знаю, что у этого есть ответ, но он не был сформулирован как собственный вопрос о Stackru.

2 ответа

Решение

В EXE это не имеет никакого значения, hInstance от WinMain() а также GetModuleHandle(NULL) оба относятся к одному и тому же HINSTANCE (модуль файла.exe). Но это имеет значение, если вы вместо этого создаете окна внутри DLL, так как вы должны использовать DLL hInstance но GetModuleHandle(NULL) все равно вернет HINSTANCE EXE, который загрузил DLL.

Просто чтобы добавить к этим ответам свои два цента. Если вам нужно получить дескриптор модуля из библиотеки DLL (и вы не хотите или не можете сохранить его в глобальной переменной изDllMain call) вместо этого вы можете использовать эту функцию:

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;
}
HMODULE WINAPI GetModuleHandle( _In_opt_  LPCTSTR lpModuleName );

Дайте дескриптор модуля переданного имени модуля. Если вы передаете NULL, вы получаете дескриптор модуля исполняемого файла EXE. Если вы конкретно дадите имя модулю, вы получите дескриптор модуля той библиотеки DLL, которая сопоставлена ​​с адресным пространством процесса. Дело в том, что когда вы пытаетесь вызвать функцию, экспортированную dll, или пытаетесь использовать шаблон диалога в той стороне dll. В это время, если вы используете возвращаемую форму HMODULE GetMoudleHandle(NULL), ваш код работать не будет.

Одна потенциальная выгода, которую вы получаете от использования GetModuleHandle(NULL) по сравнению с прямым использованием WinMain HINSTANCE, больше связана с архитектурой. Если вы хотите предоставить платформенно-независимую систему, работающую на linux/windows/ что угодно, у вас может быть слой, который выполняет платформенно-зависимые переводы. В этом случае вы не хотите, чтобы зависящие от платформы объекты, такие как HINSTANCE, отображались в основном коде приложения. Итак, чтобы обойти эту зависимость от платформы, я поместил GetModuleHandle(NULL) в конструктор зависимого от платформы класса, который имеет тот же эффект, что и прямое использование WinMain HINSTANCE, но абстрагирует эту конкретную функциональность от самой основной кодовой базы.

Другие вопросы по тегам