Как использовать main() вместо WinMain?
Я хочу написать GUI приложение для Windows, но мне не нравится что MS Visual Studio для этого надо писать WinMain
. Хочу писать привычную main()
или main(argc, argv)
- как это сделать?
Я хочу написать GUI приложение для Windows, но мне не нравится что MS Visual Studio для этого надо писать WinMain
. Хочу писать привычную main()
или main(argc, argv)
- как это сделать?
Прежде всего надо понимать, что ни main()
, ни WinMain()
- не являются "точками входа" .exe файла. Точкой входа (entry point) является некоторая функция, которая будет вызвана операционной системой при старте приложения. В С++ это функция рантайма (CRT), которая проводит инициализацию CRT, вызывает конструкторы глобальных объектов, и затем уже вызывает main
или WinMain
.
Линкеру передается параметр /subsystem
, который задает тип приложения, например /SUBSYSTEM:WINDOWS
для GUI приложений, или /SUBSYSTEM:CONSOLE
для консольных приложений. В первую очередь это нужно операционной системе - тип приложения прописывается в заголовке .exe файла, и по нему ОС понимает надо ли создавать окно консоли, или нет. Также, при помощи этого параметра линкер выбирает точку входа, которая будет использована по-умолчанию:
mainCRTStartup
(илиwmainCRTStartup
) - при использовании /SUBSYSTEM:CONSOLE
. Вызывает main
(или wmain
)WinMainCRTStartup
(или wWinMainCRTStartup
) - при использовании /SUBSYSTEM:WINDOWS
. Вызывает WinMain
(или wWinMain
).Точку входа можно переопределить, передав линкеру параметр /entry
. Для того чтобы использовать main
в GUI приложении, мы должны вызвать линкер с параметрами /SUBSYSTEM:WINDOWS
и /ENTRY:mainCRTStartup
. Тогда ОС не будет создавать окно консоли, а CRT будет вызывать функцию main
.
Значение параметра /entry
можно переопределить в опциях проекта MSVS (linker > advanced > entry point). Либо его можно написать прямо в коде программы, с помощью pragma comment
:
#include <Windows.h>
#pragma comment(linker, "/entry:mainCRTStartup")
int main() {
::MessageBoxW(nullptr, L"(^._.^)", L"Important message", MB_OK);
}