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

ОпределениеWinMain является:

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

Что я понимаю, это:

  • hInstance является дескриптором экземпляра приложения и может, когда не DLL, быть восстановлена ​​сGetModuleHandle(NULL)
  • szCmdLine аргументы командной строки и могут быть повторены с GetCommandLine()
  • nCmdShowобычноSW_SHOW

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

1 ответ

Решение

Это наследие. Раймонд Чен дает хорошее объяснение "Старому новому" (от 15 июня 2004 г.). Вот оно (с исправленными ссылками):

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

Конечно, сделал.

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

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

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

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

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

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

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