信息学实验室作业(七)
更新: 2025/3/15 字数: 0 字 时长: 0 分钟
一、实验目的
本次实验旨在运用Win32 API在Mac系统开发环境中创建一个具备图形绘制和用户交互功能的应用程序。通过在窗口中绘制房子图案,并利用按钮实现图形显示、清除和显示开发者姓名等操作,深入理解和掌握Win32 API在窗口编程、消息处理、图形绘制以及控件使用方面的应用。
二、实验环境
本次实验在Mac系统上,借助(如CrossOver、WineBottler等支持在Mac上进行Win32开发的工具)作为开发环境进行开发。
三、实现思路
- 项目创建与初始化:在选定的开发工具中创建Win32项目,选择空项目模板,添加源文件。在
WinMain
函数中完成窗口类的注册和窗口的创建,为后续操作奠定基础。 - 控件创建:在窗口创建过程中,通过
CreateWindow
函数创建三个按钮控件,分别用于显示图形、清除图形和显示开发者姓名。每个按钮都指定了相应的文本、位置、大小和唯一的ID标识。 - 图形绘制:在
WM_PAINT
消息处理函数中,根据标志变量的状态绘制房子图形。利用CreatePen
和CreateSolidBrush
函数创建画笔和画刷,设置不同的颜色来绘制屋顶(红色)、墙壁(蓝色)和烟囱(绿色)。通过Polygon
和Rectangle
等绘图函数完成图形的绘制。 - 按钮事件处理:在
WM_COMMAND
消息处理函数中,根据按钮的ID判断用户点击的是哪个按钮。针对不同按钮的点击,修改相应的标志变量,然后调用InvalidateRect
函数触发窗口重绘,以实现对应的功能。 - 开发者姓名显示:当点击显示开发者姓名的按钮时,在
WM_PAINT
消息处理函数中,通过TextOut
函数在窗口指定位置显示开发者姓名“叶蓝骅”。
四、代码实现
cpp
#include <windows.h>
// 全局变量,用于控制图形显示和姓名显示
BOOL bShowHouse = FALSE;
BOOL bShowName = FALSE;
const char* developerName = "叶蓝骅";
// 窗口过程函数,处理窗口消息
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
// 创建显示图形按钮
CreateWindow("BUTTON", "显示图形", WS_VISIBLE | WS_CHILD, 10, 10, 100, 30, hwnd, (HMENU)1, NULL, NULL);
// 创建清除图形按钮
CreateWindow("BUTTON", "清除图形", WS_VISIBLE | WS_CHILD, 120, 10, 100, 30, hwnd, (HMENU)2, NULL, NULL);
// 创建显示姓氏按钮
CreateWindow("BUTTON", "显示姓名", WS_VISIBLE | WS_CHILD, 230, 10, 100, 30, hwnd, (HMENU)3, NULL, NULL);
break;
}
case WM_COMMAND: {
switch (LOWORD(wParam)) {
case 1:
bShowHouse = TRUE;
bShowName = FALSE;
// 触发窗口重绘
InvalidateRect(hwnd, NULL, TRUE);
break;
case 2:
bShowHouse = FALSE;
bShowName = FALSE;
// 触发窗口重绘
InvalidateRect(hwnd, NULL, TRUE);
break;
case 3:
bShowHouse = FALSE;
bShowName = TRUE;
// 触发窗口重绘
InvalidateRect(hwnd, NULL, TRUE);
break;
}
break;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if (bShowHouse) {
// 创建红色画笔和画刷用于绘制屋顶
HPEN hRedPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
HBRUSH hRedBrush = CreateSolidBrush(RGB(255, 0, 0));
SelectObject(hdc, hRedPen);
SelectObject(hdc, hRedBrush);
// 定义屋顶的顶点坐标
POINT roofPoints[] = { {200, 100}, {100, 200}, {300, 200} };
// 绘制屋顶
Polygon(hdc, roofPoints, 3);
// 删除画笔和画刷
DeleteObject(hRedPen);
DeleteObject(hRedBrush);
// 创建蓝色画笔和画刷用于绘制墙壁
HPEN hBluePen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
HBRUSH hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBluePen);
SelectObject(hdc, hBlueBrush);
// 绘制墙壁
Rectangle(hdc, 100, 200, 300, 300);
// 删除画笔和画刷
DeleteObject(hBluePen);
DeleteObject(hBlueBrush);
// 创建绿色画笔和画刷用于绘制烟囱
HPEN hGreenPen = CreatePen(PS_SOLID, 2, RGB(0, 255, 0));
HBRUSH hGreenBrush = CreateSolidBrush(RGB(0, 255, 0));
SelectObject(hdc, hGreenPen);
SelectObject(hdc, hGreenBrush);
// 绘制烟囱
Rectangle(hdc, 250, 50, 270, 150);
// 删除画笔和画刷
DeleteObject(hGreenPen);
DeleteObject(hGreenBrush);
}
if (bShowName) {
// 设置文本颜色为黑色
SetTextColor(hdc, RGB(0, 0, 0));
// 设置文本背景模式为透明
SetBkMode(hdc, TRANSPARENT);
// 在窗口中显示开发者姓名
TextOut(hdc, 200, 200, developerName, strlen(developerName));
}
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
// 发送退出消息,结束程序
PostQuitMessage(0);
break;
default:
// 调用默认的窗口过程处理其他消息
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
// 主函数,程序入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
// 定义窗口类
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = "HouseDrawing";
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
// 注册窗口类
RegisterClass(&wc);
// 创建窗口
HWND hwnd = CreateWindow(wc.lpszClassName, "房子绘制", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 400, NULL, NULL, hInstance, NULL);
// 显示窗口
ShowWindow(hwnd, iCmdShow);
// 更新窗口
UpdateWindow(hwnd);
// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
五、代码解释
- 全局变量:
bShowHouse
和bShowName
是布尔型全局变量,分别用于控制房子图形和开发者姓名是否显示。developerName
是一个常量字符串,存储开发者姓名“叶蓝骅”。 WndProc
函数:WM_CREATE
消息处理:在窗口创建时,使用CreateWindow
函数创建三个按钮,每个按钮的参数包括按钮类型、显示文本、窗口样式、位置、大小、父窗口句柄、菜单ID等。WM_COMMAND
消息处理:通过LOWORD(wParam)
获取触发消息的控件ID。根据不同的ID,修改bShowHouse
和bShowName
的值,并调用InvalidateRect
函数,该函数会向窗口发送WM_PAINT
消息,触发窗口重绘。WM_PAINT
消息处理:首先通过BeginPaint
获取设备上下文hdc
,根据bShowHouse
和bShowName
的值进行相应绘制。若bShowHouse
为真,创建不同颜色的画笔和画刷绘制房子的各个部分;若bShowName
为真,设置文本颜色和背景模式后,使用TextOut
函数显示开发者姓名。最后通过EndPaint
结束绘制。WM_DESTROY
消息处理:当窗口接收到销毁消息时,调用PostQuitMessage
函数,向消息队列发送退出消息,结束程序的消息循环。- 默认情况:对于其他未处理的消息,调用
DefWindowProc
函数,由系统默认的窗口过程进行处理。
WinMain
函数:- 窗口类定义与注册:定义
WNDCLASS
结构体wc
,设置窗口过程函数、实例句柄、类名和背景颜色等属性,然后使用RegisterClass
函数注册窗口类。 - 窗口创建与显示:调用
CreateWindow
函数创建窗口,指定窗口类名、标题、样式、位置、大小等参数。创建完成后,通过ShowWindow
显示窗口,并使用UpdateWindow
更新窗口内容。 - 消息循环:通过
GetMessage
函数从消息队列中获取消息,使用TranslateMessage
和DispatchMessage
函数进行消息转换和分发,直到获取到退出消息,结束程序。
- 窗口类定义与注册:定义
六、编译与运行
- 编译:将上述代码保存为
.cpp
文件,在Mac系统的开发工具中进行编译。由于是在Mac系统上模拟Win32开发环境,可能需要特别注意开发工具的设置,如确保正确链接Win32库文件等。编译过程中,若出现错误,根据错误提示信息仔细检查代码和开发环境配置,进行相应修改,直至编译成功。 - 运行:编译成功后,运行生成的可执行文件。程序启动后,会弹出一个窗口,窗口中包含三个按钮。点击“显示图形”按钮,窗口中会绘制出带有红色屋顶、蓝色墙壁和绿色烟囱的房子图形;点击“清除图形”按钮,窗口中的图形会被清除;点击“显示姓名”按钮,窗口中会显示“叶蓝骅”。
七、实验总结
通过本次在Mac系统上基于Win32 API的开发实验,成功实现了窗口绘图和用户交互功能。在实验过程中,不仅加深了对Win32 API相关知识的理解和运用,还掌握了在Mac系统中搭建Win32开发环境的方法。遇到了开发环境配置、图形绘制细节等问题,通过查阅资料、调试代码,逐步解决了这些问题,提升了自己的问题解决能力。后续可以进一步优化程序,如改进图形绘制的细节、增加更多交互功能等,以提高程序的实用性和用户体验。