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 标准窗口:

c766e7abaa767fae9d225c517b059a80

图2 改变窗口显示风格:

cc413d893091219bcb33e0003b25fda7

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

267b7763bc2de7e9fdd7228d7df5b156

截图 展示要点 验证结果
图1 标准窗口、灰色背景、居中文字、音乐播放 通过
图2 只有标题栏、无菜单、无粗边框 通过
图3 手型指针、可还原为标准箭头 通过

团队分工

成员 负责内容
058 整体架构、窗口类注册、消息循环、窗口过程分流
057 客户区绘制、字体回退、文字居中、灰色背景
043 窗口风格切换、菜单栏、命令统一分发
044 鼠标指针切换、快捷键处理
046 背景音乐、编译脚本、自动验证与查重工具

总结收获

这次实验把“事件驱动 + 消息机制 + 窗口过程 + 消息循环”真正串了一遍。窗口虽小,但注册窗口类、创建窗口、GDI 绘制、菜单、光标、音频播放都覆盖到了。最深的体会是:不要在消息循环里做阻塞操作;SetWindowLongPtrW 改风格、SetClassLongPtrW 改光标、PlaySoundW 异步播放,都是“知道 API 名字”和“真正会用”之间的差距。后续做 Winsock 编程时,服务端一边收数据一边响应界面,这次理解的“不能阻塞消息循环”会直接派上用场。


标签:Win32 API 消息循环 GDI PlaySound 实验总结

posted @ 2026-09-23 12:40  Jbuckle  阅读(33)  评论(0)    收藏  举报