Win32 API 实战:从零构建窗口程序,5步完成消息循环与绘图

📅 2026/7/12 23:22:31
Win32 API 实战:从零构建窗口程序,5步完成消息循环与绘图
Win32 API 实战5步构建完整窗口程序与消息循环1. 环境准备与基础概念Windows图形界面程序开发的核心是Win32 API这是一组由微软提供的C语言函数库用于创建窗口、处理消息和绘制界面。与常见的控制台程序不同Win32程序采用事件驱动模型这意味着程序流程由用户操作和系统事件决定。开发环境要求Visual Studio 2019或更高版本Windows SDK通常随VS自动安装基础C/C知识关键术语解析HINSTANCE程序实例句柄标识当前运行的程序HWND窗口句柄唯一标识一个窗口消息循环Windows程序的核心机制用于接收和处理系统消息#include windows.h // 必须包含的核心头文件2. 窗口创建四部曲2.1 定义窗口处理函数每个窗口都需要一个处理函数来响应各种事件LRESULT CALLBACK WindowProc( HWND hwnd, // 窗口句柄 UINT uMsg, // 消息ID WPARAM wParam, // 附加信息 LPARAM lParam // 附加信息 ) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }2.2 注册窗口类向系统注册窗口的样式和行为WNDCLASS wc {0}; wc.lpfnWndProc WindowProc; // 设置窗口处理函数 wc.hInstance hInstance; // 程序实例句柄 wc.lpszClassName MyWindow; // 窗口类名 RegisterClass(wc); // 注册窗口类2.3 创建窗口实例HWND hwnd CreateWindowEx( 0, // 扩展样式 MyWindow, // 窗口类名 Win32 Demo, // 窗口标题 WS_OVERLAPPEDWINDOW, // 窗口样式 // 位置和大小 CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, // 父窗口 NULL, // 菜单 hInstance, // 实例句柄 NULL // 附加数据 );2.4 显示窗口ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 强制重绘窗口3. 消息循环实现Windows程序的核心是消息循环它不断从系统获取并分发消息MSG msg {0}; while (GetMessage(msg, NULL, 0, 0)) { TranslateMessage(msg); // 转换键盘消息 DispatchMessage(msg); // 分发到窗口处理函数 } return (int)msg.wParam;消息处理流程详解GetMessage从消息队列获取消息TranslateMessage转换键盘输入为字符消息DispatchMessage调用对应的窗口处理函数4. GDI绘图基础Windows图形设备接口(GDI)提供了基本的绘图功能4.1 基本绘图步骤case WM_PAINT: { PAINTSTRUCT ps; HDC hdc BeginPaint(hwnd, ps); // 绘制矩形 Rectangle(hdc, 100, 100, 300, 200); // 绘制文本 TextOut(hdc, 150, 150, Hello Win32, 11); EndPaint(hwnd, ps); return 0; }4.2 创建自定义画笔和画刷HPEN hPen CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); // 红色实线画笔 HBRUSH hBrush CreateSolidBrush(RGB(0, 0, 255)); // 蓝色实心画刷 // 选入设备上下文 HGDIOBJ hOldPen SelectObject(hdc, hPen); HGDIOBJ hOldBrush SelectObject(hdc, hBrush); // 绘制图形 Ellipse(hdc, 200, 200, 400, 300); // 恢复原有对象 SelectObject(hdc, hOldPen); SelectObject(hdc, hOldBrush); // 删除GDI对象 DeleteObject(hPen); DeleteObject(hBrush);5. 完整示例与调试技巧5.1 完整可编译代码#include windows.h LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc BeginPaint(hwnd, ps); // 绘制蓝色矩形 HBRUSH hBrush CreateSolidBrush(RGB(0, 0, 255)); FillRect(hdc, ps.rcPaint, hBrush); DeleteObject(hBrush); // 绘制白色文本 SetTextColor(hdc, RGB(255, 255, 255)); TextOut(hdc, 50, 50, Win32窗口程序示例, 12); EndPaint(hwnd, ps); return 0; } case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc {0}; wc.lpfnWndProc WindowProc; wc.hInstance hInstance; wc.lpszClassName MyWindowClass; RegisterClass(wc); // 创建窗口 HWND hwnd CreateWindowEx( 0, MyWindowClass, Win32示例, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL ); if (hwnd NULL) return 0; // 显示窗口 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 消息循环 MSG msg {0}; while (GetMessage(msg, NULL, 0, 0)) { TranslateMessage(msg); DispatchMessage(msg); } return (int)msg.wParam; }5.2 调试技巧输出调试信息AllocConsole(); // 创建控制台窗口 freopen(CONOUT$, w, stdout); // 重定向标准输出 printf(调试信息: %d\n, value); // 输出调试信息检查API调用结果if (!RegisterClass(wc)) { MessageBox(NULL, 窗口类注册失败!, 错误, MB_ICONERROR); return 0; }使用Visual Studio调试器设置断点观察消息处理流程查看窗口句柄和消息参数使用输出窗口查看调试信息