Windows原生开发

26 阅读4分钟

Windows原生窗口创建全流程(代码+说明)

#include <Windows.h>

// 窗口过程函数声明
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(
    HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    PSTR szCmdLine, 
    int iCmdShow) 
{
    static TCHAR szAppName[] = TEXT("Win32Window");
    
    // 1. 窗口类注册
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = szAppName;
    wcex.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

    if (!RegisterClassEx(&wcex)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 2. 创建窗口
    HWND hWnd = CreateWindowEx(
        0,                              // 扩展样式
        szAppName,                     // 窗口类名
        TEXT("Windows原生窗口示例"),    // 窗口标题
        WS_OVERLAPPEDWINDOW,            // 窗口样式
        CW_USEDEFAULT, CW_USEDEFAULT,   // 初始位置
        800,                            // 宽度
        600,                            // 高度
        NULL,                           // 父窗口
        NULL,                           // 菜单
        hInstance,                      // 实例句柄
        NULL                            // 创建参数
    );

    if (!hWnd) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 3. 显示窗口
    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

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

    return (int)msg.wParam;
}

// 5. 窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        
        // 绘制文本
        RECT rect;
        GetClientRect(hWnd, &rect);
        DrawText(hdc, TEXT("Hello Windows!"), 14, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        
        EndPaint(hWnd, &ps);
        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

Windows原生窗口创建关键系统函数详解

1. 窗口类注册

函数/结构体作用关键参数说明
WNDCLASSEX定义窗口类属性- cbSize: 结构体大小
- style: 窗口样式(CS_HREDRAW|CS_VREDRAW)
- lpfnWndProc: 窗口过程函数指针
- hInstance: 应用程序实例句柄
- hbrBackground: 背景画刷(COLOR_WINDOW+1)
- lpszClassName: 注册类名
RegisterClassEx注册窗口类到系统接收WNDCLASSEX*指针,成功返回TRUE,失败返回FALSE
LoadIcon加载图标资源第一个参数为NULL时使用系统默认图标(如IDI_APPLICATION)
LoadCursor加载光标资源使用系统默认箭头光标(IDC_ARROW)

2. 窗口创建与显示

函数作用关键参数说明
CreateWindowEx创建窗口实例- 扩展样式(0为默认)
- 窗口类名(必须已注册)
- 窗口标题
- 窗口样式(WS_OVERLAPPEDWINDOW)
- 初始位置/尺寸(CW_USEDEFAULT表示默认)
- 父窗口句柄(NULL表示无父窗口)
- 菜单句柄(NULL表示无菜单)
ShowWindow控制窗口显示状态iCmdShow参数决定显示方式(SW_SHOW默认显示)
UpdateWindow强制重绘窗口发送WM_PAINT消息到消息队列,触发首次绘制

3. 消息循环系统

函数作用关键参数说明
GetMessage从消息队列获取消息参数:MSG结构体指针,窗口句柄(NULL接收所有窗口消息),消息范围(0,0表示所有消息)
TranslateMessage转换键盘消息将虚拟键消息转换为字符消息(如WM_KEYDOWN→WM_CHAR)
DispatchMessage分发消息到窗口过程将消息发送给目标窗口的WndProc函数处理

4. 窗口过程函数

函数作用关键参数说明
WndProc处理窗口消息- message: 消息类型(如WM_PAINT/WM_DESTROY)
- wParam/lParam: 消息附加参数
DefWindowProc默认消息处理未处理的消息由系统进行默认处理
PostQuitMessage发送退出消息退出消息循环时调用,设置MSG的wParam为退出码

Windows共享内存操作全指南(代码+说明)

核心函数与参数说明

函数名作用关键参数说明所属头文件
CreateFileMapping创建内存映射对象hFile:文件句柄(INVALID_HANDLE_VALUE表示使用页文件)
flProtect:内存保护属性(如PAGE_READWRITE)
lpName:共享内存名称(跨进程标识)
<windows.h>
OpenFileMapping打开已存在的内存映射对象dwDesiredAccess:访问模式(FILE_MAP_READ/WRITE)
lpName:共享内存名称
<windows.h>
MapViewOfFile映射内存到进程地址空间hFileMappingObject:映射对象句柄
dwDesiredAccess:访问模式
dwNumberOfBytesToMap:映射字节数
<windows.h>
UnmapViewOfFile解除内存映射lpBaseAddress:映射视图地址<windows.h>
CloseHandle关闭对象句柄hObject:要关闭的句柄<windows.h>

完整代码示例

#include <windows.h>
#include <iostream>
#include <cassert>

int main() {
    const char* sharedMemName = "Global\\MySharedMemory";
    const SIZE_T sharedMemSize = 1024; // 1KB

    // 创建共享内存
    HANDLE hMapping = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // 使用系统页文件
        NULL,                    // 默认安全属性
        PAGE_READWRITE,          // 可读写
        0,                       // 高位文件大小
        sharedMemSize,           // 低位文件大小
        sharedMemName            // 共享内存名称
    );

    if (!hMapping) {
        std::cerr << "创建共享内存失败!错误代码:" << GetLastError() << std::endl;
        return 1;
    }

    // 映射到进程地址空间
    LPVOID pSharedMem = MapViewOfFile(
        hMapping,               // 映射对象句柄
        FILE_MAP_ALL_ACCESS,    // 完全访问权限
        0,                      // 偏移高位
        0,                      // 偏移低位
        0                       // 映射整个区域
    );

    if (!pSharedMem) {
        std::cerr << "映射共享内存失败!错误代码:" << GetLastError() << std::endl;
        CloseHandle(hMapping);
        return 1;
    }

    // 写入数据到共享内存
    int* pData = static_cast<int*>(pSharedMem);
    pData[0] = 42; // 写入示例数据
    std::cout << "写入共享内存的值:" << pData[0] << std::endl;

    // 解除映射
    if (!UnmapViewOfFile(pSharedMem)) {
        std::cerr << "解除映射失败!错误代码:" << GetLastError() << std::endl;
    }

    // 关闭句柄
    CloseHandle(hMapping);

    // 示例:另一个进程打开已存在的共享内存
    HANDLE hExistingMapping = OpenFileMapping(
        FILE_MAP_ALL_ACCESS,    // 完全访问权限
        FALSE,                  // 不可继承
        sharedMemName           // 共享内存名称
    );

    if (hExistingMapping) {
        LPVOID pExistingMem = MapViewOfFile(
            hExistingMapping,
            FILE_MAP_ALL_ACCESS,
            0,
            0,
            0
        );

        if (pExistingMem) {
            int* pExistingData = static_cast<int*>(pExistingMem);
            std::cout << "从共享内存读取的值:" << pExistingData[0] << std::endl;
            assert(pExistingData[0] == 42); // 验证数据一致性

            UnmapViewOfFile(pExistingMem);
        }
        CloseHandle(hExistingMapping);
    } else {
        std::cerr << "打开共享内存失败!错误代码:" << GetLastError() << std::endl;
    }

    return 0;
}