Windows 下的 WinMain 和标准的 main 函数有几个关键区别。
函数签名
// 标准 main
int main(int argc, char* argv[])
// Windows GUI 程序的 WinMain
int WINAPI WinMain(
_In_ HINSTANCE hInstance, // 当前实例句柄
_In_opt_ HINSTANCE hPrevInstance, // 总是 NULL,已废弃
_In_ LPSTR lpCmdLine, // 命令行参数
_In_ int nCmdShow // 窗口显示状态
)
// Windows Console 程序的 main
int main(int argc, char* argv[])应用程序类型
- main(): 通常用于控制台应用程序 (Console Application)
- WinMain(): 用于 Windows GUI 应用程序
参数传递
- main() 通过 argc/argv 接收命令行参数
- WinMain() 通过 lpCmdLine 接收命令行字符串,需要自行解析
- 如果需要在 WinMain 中获取类似 argc/argv 的参数,可以使用:
int argc;
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);窗口与入口点
- main() 默认会创建控制台窗口
- WinMain() 不会创建控制台窗口,需要自行创建应用程序窗口
- 控制台程序默认使用 main 作为入口点
- GUI 程序需要在链接器设置中指定 /SUBSYSTEM:WINDOWS,使用 WinMain 作为入口点
编译设置
// 控制台程序
#pragma comment(linker, "/subsystem:console")
// GUI 程序
#pragma comment(linker, "/subsystem:windows")实际使用示例
// GUI 程序基本框架
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// 注册窗口类
WNDCLASSEX wc = {0};
// 设置窗口类属性...
// 创建窗口
HWND hwnd = CreateWindowEx(
// 窗口参数...
);
// 消息循环
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}如何选择
选择使用哪个入口点主要取决于你的应用程序类型:
- 如果开发控制台应用程序,使用 main()
- 如果开发 GUI 应用程序,使用 WinMain()
- 如果需要同时支持控制台和 GUI,可以在 main() 中创建窗口