Windows API 窗口程序设计-实验一
Win32 窗口程序设计实验总结
课程:Windows API 与网络通信程序设计
实验:Windows API 窗口程序设计
小组:第 10 组 | 日期:2026.9.22
一句话总结:用 Win32 API 完成窗口创建、消息循环、GDI 绘制、风格切换、光标切换与背景音乐播放。
目录
实验概览
本次实验完成一个 Win32 窗口程序:灰色背景,客户区正中显示“大家好,这是我的第一个 Windows API 程序!”,循环播放背景音乐,并支持把窗口切成“只有标题栏”、把鼠标指针改成手型。功能入口收进菜单、右键菜单和快捷键,客户区保持简洁。
实验环境
| 项目 | 内容 |
|---|---|
| 操作系统 | Windows 10 / Windows 11 x64 |
| 编程环境 | Visual Studio 2022 Community(MSVC v143);也可用 MinGW-w64 GCC |
| 头文件与库 | windows.h、windowsx.h、mmsystem.h;user32.lib、gdi32.lib、winmm.lib |
| 辅助工具 | VerifyTool.cs 自动验证、PlagCheck.cs 源码查重 |
程序结构
wWinMain 负责四步:注册窗口类 → 创建菜单与窗口 → 显示更新 → 消息循环。窗口过程用 switch-case 分流消息,不处理的消息交给 DefWindowProcW。所有状态放进 APP_STATE,菜单、右键、快捷键三条入口统一走 DoMenuCommand,避免改一处漏两处。
while (GetMessageW(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
核心实现
窗口与消息循环
注册窗口类时把 WndProc 地址交给系统,窗口类画刷设为 (HBRUSH)(COLOR_3DFACE + 1),得到贴合系统主题的灰色背景。消息循环负责“取消息 → 翻译 → 分发”,窗口过程只处理关心的事件,其余默认处理。
客户区绘制
WM_PAINT 中 BeginPaint,取客户区矩形,选入问候语字体,设透明背景,用 DrawTextW 居中输出,最后 EndPaint。灰色背景同时由窗口类画刷和 WM_ERASEBKGND 配合完成,减少闪烁。
DrawTextW(hdc, GREET_TEXT, -1, &rcClient,
DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
窗口风格切换
“只有标题栏”使用 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,并 SetMenu(hWnd, NULL) 摘掉菜单;标准窗口再挂回菜单并 DrawMenuBar 刷新。改 GWL_STYLE 时必须补 WS_VISIBLE,并用 SetWindowPos(... SWP_FRAMECHANGED) 让非客户区重算。
鼠标指针切换
不只在 WM_SETCURSOR 里 SetCursor,而是直接改窗口类光标:
SetClassLongPtrW(hWnd, GCLP_HCURSOR, (LONG_PTR)hWanted);
SetCursor(hWanted);
这样同一窗口类立即生效,再在 WM_SETCURSOR 兜底,避免指针离开客户区再回来时闪烁。
背景音乐播放
使用相对路径 background.wav,先找 exe 同目录,再找当前工作目录。播放必须加 SND_ASYNC | SND_LOOP,否则阻塞消息循环,窗口会“假死”。
PlaySoundW(pApp->szWavePath, NULL,
SND_FILENAME | SND_ASYNC | SND_LOOP);
调试与验证
| 现象 | 原因 | 解决 |
|---|---|---|
| 切“只有标题栏”后窗口消失 | 漏写 WS_VISIBLE |
新风格或上 WS_VISIBLE |
| 边框没变化 | 非客户区未重算 | 补 SWP_FRAMECHANGED |
| 窗口位置乱跳 | 客户区尺寸变化 | 先记外框,再按原外框设置 |
| 音乐一响就卡死 | 未异步播放 | 加 SND_ASYNC | SND_LOOP |
| 换机器没声音 | 绝对路径 | 改相对路径 |
| 中文乱码 | 编码不一致 | UTF-8 + /utf-8 + 宽字符 API |
自动验证工具启动真实 exe 后检查:窗口可见、标准窗口可缩放、标题栏模式无粗边框/无最大化、菜单已摘掉、类光标为 IDC_HAND、背景色 #F0F0F0、文字居中、功能可逆。最近一次全部通过。
效果照片展示
图1 标准窗口:

图2 改变窗口显示风格:

图3 鼠标指针形状改为手型:

| 截图 | 展示要点 | 验证结果 |
|---|---|---|
| 图1 | 标准窗口、灰色背景、居中文字、音乐播放 | 通过 |
| 图2 | 只有标题栏、无菜单、无粗边框 | 通过 |
| 图3 | 手型指针、可还原为标准箭头 | 通过 |
团队分工
| 成员 | 负责内容 |
|---|---|
| 058 | 整体架构、窗口类注册、消息循环、窗口过程分流 |
| 057 | 客户区绘制、字体回退、文字居中、灰色背景 |
| 043 | 窗口风格切换、菜单栏、命令统一分发 |
| 044 | 鼠标指针切换、快捷键处理 |
| 046 | 背景音乐、编译脚本、自动验证与查重工具 |
总结收获
这次实验把“事件驱动 + 消息机制 + 窗口过程 + 消息循环”真正串了一遍。窗口虽小,但注册窗口类、创建窗口、GDI 绘制、菜单、光标、音频播放都覆盖到了。最深的体会是:不要在消息循环里做阻塞操作;SetWindowLongPtrW 改风格、SetClassLongPtrW 改光标、PlaySoundW 异步播放,都是“知道 API 名字”和“真正会用”之间的差距。后续做 Winsock 编程时,服务端一边收数据一边响应界面,这次理解的“不能阻塞消息循环”会直接派上用场。
标签:
Win32 API消息循环GDIPlaySound实验总结

浙公网安备 33010602011771号