目录
一、实验目的
利用 C++编写两个窗口切换。
二、实验环境
Vc++ 6.0、Windows10
三、实验内容
实现多窗口的创建。
四、实验步骤
1)相关知识
由于对话框是一个特殊的窗口,所以该类是从 CWnd 类中派生出来的。对话框子层次
结构包括通用对话框类 CDialog 以及支持文件选择、颜色选择、字体选择、打印、替换文本
的公共对话框子类。
2)编程要求
实现多窗口的创建。
3)测试说明
4)实验结果:
截图:

代码
cpp
#include <windows.h>
#include <commctrl.h>
// 链接 comctl32.lib 库
#pragma comment(lib, "comctl32.lib")
// 定义常量
#define IDR_MENU1 101
#define IDM_SHOW 1001
#define IDM_RED 1002
#define IDM_GREEN 1003
#define IDM_BLUE 1004
#define IDC_TOOLBAR1 1005
// 全局变量
HFONT hFont;
COLORREF textColor = RGB(0, 0, 0);
HWND hToolbar;
const wchar_t* text = L"2252705郑道源";
// 窗口过程函数
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// 创建窗口类
void create(WNDCLASSEXW* wcex, HINSTANCE hInstance, const wchar_t lpszClassName[]) {
wcex->cbSize = sizeof(WNDCLASSEXW);
wcex->style = 0;
wcex->lpfnWndProc = WndProc;
wcex->cbClsExtra = 0;
wcex->cbWndExtra = 0;
wcex->hInstance = hInstance;
wcex->hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_APPLICATION));
wcex->hCursor = LoadCursorW(NULL, IDC_ARROW);
wcex->hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex->lpszMenuName = MAKEINTRESOURCEW(IDR_MENU1);
wcex->lpszClassName = lpszClassName;
wcex->hIconSm = LoadIconW(wcex->hInstance, MAKEINTRESOURCEW(IDI_APPLICATION));
}
// 创建工具条
void CreateToolbar(HWND hWnd, HINSTANCE hInstance) {
hToolbar = CreateWindowExW(
0, TOOLBARCLASSNAMEW, NULL,
WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_ALTDRAG,
0, 0, 0, 0, hWnd, (HMENU)IDC_TOOLBAR1, hInstance, NULL
);
// 添加按钮
TBBUTTON tbButtons[] = {
{ STD_FILENEW, IDM_SHOW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0, (INT_PTR)L"显示" },
{ STD_FILENEW, IDM_RED, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0, (INT_PTR)L"红色" },
{ STD_FILENEW, IDM_GREEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0, (INT_PTR)L"绿色" },
{ STD_FILENEW, IDM_BLUE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0, (INT_PTR)L"蓝色" }
};
SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessageW(hToolbar, TB_ADDBUTTONS, (WPARAM)4, (LPARAM)tbButtons);
SendMessageW(hToolbar, TB_AUTOSIZE, 0, 0);
// 设置工具条可停靠
SendMessageW(hToolbar, TB_SETEXTENDEDSTYLE, 0, (LPARAM)TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_MIXEDBUTTONS);
RECT rc;
GetClientRect(hWnd, &rc);
SetWindowPos(hToolbar, HWND_TOP, 0, 0, rc.right, 0, SWP_SHOWWINDOW);
}
// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow) {
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
WNDCLASSEXW wcex;
HWND hWnd;
MSG msg;
const wchar_t lpszClassName[] = L"window";
const wchar_t lpszTitle[] = L"My_Windows";
create(&wcex, hInstance, lpszClassName);
// 注册窗口类
if (!RegisterClassExW(&wcex)) {
MessageBoxW(NULL, L"窗口类注册失败!", L"窗口注册", NULL);
return 1;
}
// 创建窗口
hWnd = CreateWindowExW(
0, lpszClassName, lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL,
hInstance, NULL
);
if (!hWnd) {
MessageBoxW(NULL, L"窗口创建失败!", L"窗口创建", NULL);
return 1;
}
// 创建工具条
CreateToolbar(hWnd, hInstance);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// 消息循环
while (GetMessageW(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
// 窗口过程函数实现
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE:
hFont = CreateFontW(24, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, L"Arial");
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_SHOW:
InvalidateRect(hwnd, NULL, TRUE);
break;
case IDM_RED:
textColor = RGB(255, 0, 0);
InvalidateRect(hwnd, NULL, TRUE);
break;
case IDM_GREEN:
textColor = RGB(0, 255, 0);
InvalidateRect(hwnd, NULL, TRUE);
break;
case IDM_BLUE:
textColor = RGB(0, 0, 255);
InvalidateRect(hwnd, NULL, TRUE);
break;
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, hFont);
SetTextColor(hdc, textColor);
SetBkMode(hdc, TRANSPARENT);
RECT rect;
GetClientRect(hwnd, &rect);
DrawTextW(hdc, text, -1, &rect, DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
DeleteObject(hFont);
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, message, wParam, lParam);
}
return 0;
}
代码解释
工具条创建时添加样式:在创建工具条的 CreateWindowExW 函数中添加了 TBSTYLE_ALTDRAG 样式,该样式允许工具条被拖动停靠。
设置工具条扩展样式:使用 SendMessageW 函数设置工具条的扩展样式,通过 TB_SETEXTENDEDSTYLE 消息设置为 TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_MIXEDBUTTONS,增强工具条的功能和外观。
初始化公共控件:在 WinMain 函数中添加了 InitCommonControlsEx 函数调用,初始化公共控件类,确保工具条等控件能正常工作。
工具提示功能:之前代码中已经通过 TBSTYLE_TOOLTIPS 样式启用了工具提示功能,当鼠标悬停在工具条按钮上时,会显示按钮的提示信息。
实验心得
本次MFC菜单和工具栏实验,核心任务是利用C++实现多窗口创建及菜单、工具栏的功能开发,通过亲手编写代码、调试程序、验证功能,我不仅掌握了MFC相关的基础编程方法,更对Windows窗口程序的运行机制有了系统认知,在实操能力和问题解决能力上得到了显著提升,同时也深刻认识到程序设计中规范与细节的重要性。
实验开始前,我先系统回顾了对话框与窗口的相关理论知识,了解到对话框作为特殊的窗口,由CWnd类派生而来,而CDialog类及其子类则支持多种公共对话框功能。起初,我对窗口类的注册、创建流程,以及菜单、工具栏的关联方法理解较为模糊,尤其是工具条的样式设置、消息循环的作用,始终存在抽象难懂的问题。但随着实验的推进,我结合代码逐行分析,逐渐理清了核心逻辑,明白窗口程序的运行离不开窗口类注册、窗口创建、消息循环这三个关键步骤,而菜单和工具栏的功能实现,本质上是通过消息响应机制完成用户操作与程序功能的联动。
本次实验的核心是实现多窗口创建、菜单功能和工具栏功能,看似简单的需求,实际编程过程中却遇到了不少难点。在编写代码时,我最初忘记调用InitCommonControlsEx函数初始化公共控件,导致工具条无法正常显示,程序运行后只有窗口框架,没有预期的工具按钮。经过排查资料和反复调试,我意识到公共控件的初始化是工具条、菜单等控件正常工作的前提,缺少这一步会导致控件创建失败。此外,在设置工具条样式时,我曾因遗漏TBSTYLE_TOOLTIPS样式,导致工具条按钮的提示功能无法实现,后来通过补充样式设置,成功解决了这一问题。这些挫折让我明白,Windows窗口编程对规范性要求极高,每一个函数调用、每一个样式设置都有其作用,稍有遗漏就会影响程序功能的正常实现。
在解决各类问题后,我成功完成了程序调试,验证了所有功能:窗口能够正常创建,工具栏上的"显示""红色""绿色""蓝色"按钮可正常响应,点击颜色按钮能切换窗口内文本颜色,点击"显示"按钮可刷新文本显示,菜单功能与工具栏按钮实现联动,程序运行稳定,无报错退出。通过分析代码结构,我对实验核心知识点有了更清晰的掌握:窗口类的创建通过WNDCLASSEXW结构体定义,包含窗口过程函数、图标、光标、背景等属性;工具条的创建通过CreateWindowExW函数实现,添加按钮、设置样式和停靠功能,需借助SendMessageW函数传递消息;消息循环则负责接收和分发用户操作消息,窗口过程函数处理各类消息,实现功能响应。
通过本次实验,我不仅熟练掌握了MFC菜单和工具栏的基本开发方法,掌握了窗口类注册、窗口创建、工具条初始化的核心步骤,还学会了排查Windows编程中的常见错误,比如公共控件未初始化、控件样式设置遗漏等,提升了自身的实操能力和问题解决能力。同时,我也认识到自己的不足:对消息响应机制的理解还不够深入,难以灵活处理复杂的消息交互;对MFC高级功能的了解较少,比如多窗口切换的进阶实现、菜单的多级设置等,还需要进一步学习和实践。此外,在代码编写的规范性上还有提升空间,比如代码注释不够详细、变量命名的逻辑性有待加强,这些细节都需要在今后的实验中加以改进。
本次实验让我深刻体会到,Windows窗口编程是一个注重逻辑、强调规范的过程,每一个步骤都环环相扣,每一个细节都可能影响程序的最终效果。实验不仅巩固了我所学的C++编程知识,更让我认识到理论与实践结合的重要性------脱离实操的理论学习只能停留在表面,只有亲手编写代码、调试错误,才能真正理解窗口程序的运行原理。在今后的学习中,我将更加注重积累Windows编程的相关知识,多动手、多思考、多总结,不断提升自己的编程能力,为后续更复杂的MFC开发和窗口编程打下坚实的基础,同时培养自己严谨细致的编程习惯,写出高效、规范、稳定的程序。