- WinMain
-
WinMain — функция, в которой программист пишет основной код, который будет выполнять программа под Windows для подсистемы GUI. Эта функция вызывается из функции WinMainCRTStartup (находящейся в CRT), которая по умолчанию является точкой входа в программу на C и выполняет необходимые для подготовки запуска программы действия, например производит разбор аргументов командной строки (аналогичная WinMain функция для консольных приложений - main(), роль WinMainCRTStartup там играет функция mainCRTStartup) [1]
Содержание
Прототип
Прототип функции WinMain выглядит следующим образом:
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow);
исключительно для Windows CE прототип:
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, // UNICODE int nCmdShow);
Параметры
hInstance
хендл текущего экземпляра приложения. Фактически, базовый адрес загрузки основного EXE модуля.
hPrevInstance
устарел, не используется в настоящее время. Раньше представлял собой предыдущий экземпляр приложения. Win32-приложения должны использовать CreateMutex для определения множественного запуска.
lpCmdLine
строка с параметрами командной строки. Для Windows CE - строка в UNICODE, в остальных случаях - в SW_SHOWNORMALВозвращаемое значение
Если программа завершается при получении сообщения WM_QUIT, то WinMain должна возвратить аргумент wParam сообщения. Если программа завершается без входа в цикл сообщений, то WinMain должна возвратить 0.
Пример программы под Win32 на C
/* * программа, выводящая сообщение входных параметров функции WinMain */ #include <windows.h> #include <stdio.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { char buffer[1024]; // буфер для формирования строки сообщения /* формирование строки */ _snprintf( buffer, sizeof(buffer)-1, "WinMain(\n" " hInstance = 0x%08x,\n" " hPrevInstance = 0x%08x,\n" " lpCmdLine = '%s',\n" " nCmdShow = %d\n" " )", hInstance, hPrevInstance, lpCmdLine, nCmdShow ); /* Вывод сообщения */ MessageBox( HWND_DESKTOP, buffer, "Параметры WinMain", MB_OK | MB_ICONINFORMATION ); /* Выход */ return 0; }
Реальная точка входа в программу
Реальная точка входа в программу - WinMainCRTStartup, которая выглядит приблизительно так (изменено для наглядности, оригинал в исходных кодах CRT CRT\src\crt0.c):
/* * From crt0.c * * Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved. * */ void WinMainCRTStartup( void ) { int mainret; char *lpszCommandLine; STARTUPINFO StartupInfo; /* Получение версии Windows (пропущено) */ /* Инициализация CRT */ if ( !_heap_init(0) ) /* инициализация кучи */ fast_error_exit(_RT_HEAPINIT); __try { _ioinit(); /* инициализация ввода-вывода для CRT */ /* Чтение Startup Info */ StartupInfo.dwFlags = 0; GetStartupInfo( &StartupInfo ); /* Чтение аргументов командной строки, в конце концов через GetCommandLine */ lpszCommandLine = _wincmdln(); /* Вызов WinMain */ mainret = WinMain( GetModuleHandleA(NULL), /* hInstance */ NULL, /* hPrevInstance */ lpszCommandLine, /* lpCmdLine */ StartupInfo.dwFlags & STARTF_USESHOWWINDOW /* nCmdShow */ ? StartupInfo.wShowWindow : SW_SHOWDEFAULT ); /* Выход с кодом возврата, возвращенным WinMain */ exit(mainret); } __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) ) { /* Возникло исключение */ _exit( GetExceptionCode() ); } }
Возможность не использовать WinMainCRTStartup() из crt0.c
При попытке генерации бинарного файла, не использующего библиотеки по умолчанию, в том числе те, в которых содержится функция WinMainCRTStartup() — msvcrt.lib, libc.lib, libcmt.lib и объявлении опции линкера /NODEFAULTLIB
//... #pragma comment(linker,"/NODEFAULTLIB") //...
Будет сгенерировано сообщение об ошибке (LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup). Однако, существует возможность не использовать эти библиотеки. Для этого необходимо заменить библиотечную функцию WinMainCRTStartup() функцией Мэта Питрека (Matt Pietrek) добавив её в код.
/* * Based mainly on CRT0TWIN.C by Matt Pietrek 1996 * */ int WINAPI WinMainCRTStartup(void) { STARTUPINFO StartupInfo={sizeof(STARTUPINFO),0}; int mainret; char *lpszCommandLine = GetCommandLine(); // skip past program name (first token in command line). if( *lpszCommandLine == '"' ) // check for and handle quoted program name { // scan, and skip over, subsequent characters until another // double-quote or a null is encountered while( *lpszCommandLine && (*lpszCommandLine != '"') ) lpszCommandLine++; // if we stopped on a double-quote (usual case), skip over it. if( *lpszCommandLine == '"' ) lpszCommandLine++; } else { // first token wasn't a quote while ( *lpszCommandLine > ' ' ) lpszCommandLine++; } // skip past any white space preceeding the second token. while ( *lpszCommandLine && (*lpszCommandLine <= ' ') ) lpszCommandLine++; GetStartupInfo(&StartupInfo); mainret = WinMain( GetModuleHandle(NULL), NULL, lpszCommandLine, StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? StartupInfo.wShowWindow : SW_SHOWDEFAULT ); ExitProcess(mainret); return mainret; }
Источники
См. также
- Win32
- CRT
Wikimedia Foundation. 2010.