Какова цель hPrevInstance в WinMain

Определение WinMain:

int CALLBACK WinMain(
    _In_ HINSTANCE hInstance,
    _In_ HINSTANCE hPrevInstance,
    _In_ LPSTR     lpCmdLine,
    _In_ int       nCmdShow
);

Я понимаю:

Тем не менее, я никогда не сталкивался с каким-либо использованием hPrevInstance, даже в книгах конца 1990-х годов. Итак, что, если есть, является использование hPrevInstance, и что это такое?

Ответ 1

Это наследие. Raymond Chen дает хорошее объяснение The Old New Thing (датировано 15 июня 2004 г.). Вот он (с исправленными ссылками):

Как только ваша средняя программа GUI выберет себя с земли, управление начнется с вашей функции WinMain. Второй параметр, hPrevInstance, всегда равен нулю в программах Win32. Конечно, в какой-то момент это имело смысл?

Конечно, да.

В 16-битной Windows появилась функция GetInstanceData. Эта функция взяла HINSTANCE, указатель и длину, и скопировала память из этого экземпляра в ваш текущий экземпляр. (Это своего рода 16-разрядный эквивалент ReadProcessMemory с ограничением того, что второй и третий параметры должны быть одинаковыми.)

(Так как 16-разрядная версия Windows имела общее адресное пространство, функция GetInstanceData была действительно не более чем hmemcpy, и многие программы полагались на это и только что использовали raw hmemcpy вместо использования документального API. Win16 был фактически разработан с возможность наложения отдельных адресных пространств в будущую версию - соблюдать такие флаги, как GMEM_SHARED, - но распространенность трюков, таких как hmemcpy'ing вашего предыдущего экземпляра, уменьшила этот потенциал до нереализованного сна.)

Это была причина для параметра hPrevInstance для WinMain. Если hPrevInstance не был NULL, то это был дескриптор экземпляра программы, которая уже запущена. Вы можете использовать GetInstanceData для копирования данных из него, быстрее сесть с земли. Например, вы можете скопировать дескриптор главного окна из предыдущего экземпляра, чтобы вы могли общаться с ним.

Было ли hPrevInstance NULL или не указано, была ли вы первой копией программы. В 16-битной Windows только первый экземпляр программы зарегистрировал свои классы; второй и последующие экземпляры продолжали использовать классы, которые были зарегистрированы первым экземпляром. (Действительно, если они попытались, регистрация потерпит неудачу, так как класс уже существует.) Поэтому все 16-разрядные программы Windows пропустили регистрацию класса, если hPrevInstance не был NULL.

Люди, которые разработали Win32, оказались немного исправлены, когда пришло время переносить WinMain: что передать для hPrevInstance? В конце концов, весь модуль/экземпляр не существовал в Win32, а отдельные адресные пространства означали, что программы, которые перешли на повторную инициализацию во втором экземпляре, больше не будут работать. Таким образом, Win32 всегда пропускает NULL, заставляя все программы полагать, что они являются первыми.

И удивительно, что это действительно сработало.