Операционная система Windows 95 для программиста

  d8ef8794     

Функция WinMain


В 11 томе "Библиотеки системного программиста", мы описывали функцию WinMain для приложений Win16 следующим образом:

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

Для приложений Win32 это описание немного изментися:

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

На первый взгляд, изменений немного - мы заменили PASCAL на APIENTRY . Однако есть и другие, невидимые невооруженным глазом изменения.

Прежде всего, вспомним определение типа int. Разрядность переменной этого типа зависит от системы. Для DOS и Microsoft Windows версии 3.1 эта разрядность равна 16 бит, для Microsoft Windows 95 и Microsoft Windows NT - 32 бит. Если вы собираетесь составлять программу таким образом, чтобы она работала в разных системах (или даже на разных платформах), не следует делать никаких предположений относительно разрядности переменных типа int.

Что же касается типов PASCAL и pascal, то в 32-разрядной системе разработки Microsoft Visual C++ версии 2.0 они не рекомендуются для использования, хотя и определены для совместимости следующим образом:

#define PASCAL __stdcall #define pascal __stdcall

Вместо этих типов вы должны указывать типы APIENTRY, WINAPI, CALLBACK (последний используется в функциях обратного вызова, например, в функции окна):

#define CALLBACK __stdcall #define WINAPI __stdcall #define APIENTRY WINAPI

Согласно документации, ключевое слово __stdcall определяет функцию, аргументы которой помещаются в стек справа налево.

Займемся теперь параметрами функции WinMain.

Приложениям Win16 через первые два параметра передаются, соответственно, идентификатор приложения hInstance и идентификатор предыдущей копии приложения hPrevInstance, если в системе одновременно работает несколько копий одного приложения. Если же запущена только одна копия приложения, параметр hPrevInstance имеет значение NULL.

Последнее обстоятельство часто используется приложениями Win16 для того чтобы разрешать пользователю запускать только одну копию приложения.


Приложения Win32 работают в разных адресных пространствах, поэтому они не могут воспользоваться идентификатором своей предыдущей копии, как приложения Win16. Более того, такое приложение вообще никак не сможет использовать параметр hPrevInstance , так как его значение для 32-разрядных приложений Microsoft Windows 95 и Microsoft Windows NT всегда равно NULL.

Сказанное, однако, не означает, что теперь вы не сможете запретить пользователям запускать несколько копий вашего приложения. Просто для этого потребуются другие средства (например, семафоры или прямой поиск окон функцией FindWindow). Соответствующие примеры приложений будет приведены ниже.

Другое новшество касается не только идентификаторов приложений, но и всех других идентификаторов в 32-разрядных версиях Microsoft Windows. Идентификаторы теперь стали 32-разрядными. И если раньше вы могли определять переменные для хранения идентификаторов как int, unsigned и т. п., то теперь необходимо пользоваться специально предназначенными для этого типами (HINSTANCE, HICON, HBRUSH и т. д.). Впрочем, так нужно было поступать и раньше, при создании приложений Win16.

Что же касается параметров lpCmdLine и nCmdShow, то здесь практически ничего не изменилось.

Параметр lpCmdLine по-прежнему указывает на строку параметров, а параметр nCmdShow содержит их количество. Однако теперь тип LPSTR соответствует 32-разрядному смещению переменной типа CHAR, а не дальнему указателю на эту переменную в формате <селектор:смещение>.

Параметр nCmdShow определяет способ отображения окна (минимизированное SW_MINIMIZE, нормальное SW_SHOW и т. д.). Мы уже рассказывали об использовании этого параметра в 11 томе "Библиотеки системного программиста".


Содержание раздела