书籍:《windows程序设计(第五版)》的开始->编写第一个WINDOWS程序

环境:visual studio 2022

内容:编写第一个WINDOWS程序

说明:以下内容大部分来自腾讯元宝。

wWinMain 是 Windows 程序的入口点函数,专为 Unicode 编码设计,现代 Windows 开发中推荐优先使用。以下是其详细解析:


一、函数原型与参数解析

int APIENTRY wWinMain(
    HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    PWSTR lpCmdLine, 
    int nCmdShow
);
参数 作用 备注
hInstance 当前应用程序实例的唯一标识符,用于加载资源(如图标、位图)。 多实例程序可通过此句柄区分不同实例。
hPrevInstance 前一个实例句柄,现代 Windows 中始终为 NULL已弃用 若需检测实例是否存在,应使用 CreateMutex 创建唯一互斥体。
lpCmdLine 包含命令行参数的 Unicode 字符串(PWSTR 类型),不包含程序自身路径。 若需完整命令行,需调用 GetCommandLineW;若需参数数组,使用 CommandLineToArgvW
nCmdShow 控制主窗口初始显示状态,如 SW_SHOW(正常显示)、SW_MINIMIZE(最小化)等。 常见取值包括 SW_HIDESW_RESTORESW_SHOWMAXIMIZED 等。

二、函数核心作用

  1. 初始化程序

    • 分配内存、初始化全局变量、注册窗口类等。
    • 示例:通过 hInstance 加载程序图标(LoadIcon)或位图(LoadBitmap)。
  2. 创建主窗口

    • 调用 CreateWindowEx 创建窗口,并通过 ShowWindow 和 UpdateWindow 显示窗口。
    • 示例:
      HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, ...);
      ShowWindow(hWnd, nCmdShow);
  3. 消息循环

    • 进入 GetMessage/DispatchMessage 循环,处理窗口消息(如 WM_PAINTWM_QUIT)。
    • 当收到 WM_QUIT 消息时,函数返回 wParam(退出码)。

三、关键注意事项

  1. 字符编码与兼容性

    • wWinMain 使用 Unicode,而 WinMain 使用 ANSI。若需兼容旧代码,可显式调用 MultiByteToWideChar 转换参数
    • 编译时需指定 /SUBSYSTEM:WINDOWS,否则链接器可能选择 main 或 WinMain 作为入口点。                
  2. 实例句柄与多实例检测

    • hPrevInstance 已弃用,多实例检测应通过 CreateMutex 实现:
      HANDLE hMutex = CreateMutex(NULL, TRUE, L"UniqueMutexName");
      if (GetLastError() == ERROR_ALREADY_EXISTS) {
          // 另一实例已存在
      }
  3. 错误处理与返回值

    • 若函数在消息循环前退出,需显式返回 0
    • 返回值通常用于传递程序退出状态(如 ERROR_SUCCESS 或自定义代码)。
  4. 调用约定与链接器设置

    • WINAPI 宏定义为 __stdcall,确保参数正确入栈。
    • 链接时需包含 WinMainCRTStartup(或 wWinMainCRTStartup),由 C 运行时库(CRT)完成初始化。

四、典型代码框架

#include <windows.h>

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR lpCmdLine, int nCmdShow) {
    // 初始化
    const wchar_t CLASS_NAME[] = L"SampleWindowClass";
    WNDCLASSEX wcex = {0};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszClassName = CLASS_NAME;
    RegisterClassExW(&wcex);

    // 创建窗口
    HWND hWnd = CreateWindowExW(
        0,                              // 扩展样式
        CLASS_NAME,                     // 窗口类名
        L"Sample Window",              // 窗口标题
        WS_OVERLAPPEDWINDOW,            // 窗口样式
        CW_USEDEFAULT, CW_USEDEFAULT,   // 初始位置
        CW_USEDEFAULT, CW_USEDEFAULT,   // 初始大小
        NULL,                           // 父窗口
        NULL,                           // 菜单
        hInstance,                      // 实例句柄
        NULL                            // 附加参数
    );

    if (!hWnd) return FALSE;

    // 显示窗口
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    // 消息循环
    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

五、与 WinMain 的对比

特性 wWinMain WinMain
字符编码 Unicode(PWSTR ANSI(LPSTR
推荐使用 现代开发首选 兼容性场景
命令行处理 需显式转换或使用 GetCommandLineW 可直接使用 lpCmdLine
入口点选择 需链接器指定 /SUBSYSTEM:WINDOWS 同上

通过上述机制,wWinMain 实现了 Windows 程序的初始化、窗口创建及消息处理,是 Windows GUI 应用的核心入口点。

相关内容

/SUBSYSTEM:WINDOWS-CSDN博客https://blog.csdn.net/qq_20725221/article/details/146253392?sharetype=blogdetail&sharerId=146253392&sharerefer=PC&sharesource=qq_20725221&spm=1011.2480.3001.8118

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐