C++:WNDCLASSEX 窗口类结构体
1. 定义与用途
在C++中,WNDCLASSEX是一个结构体,用于定义Windows窗口类的扩展属性。它是Windows API(应用程序编程接口)的一部分,主要用于创建具有自定义外观和行为的窗口。当你要在Windows环境下使用C++编写图形用户界面(GUI)程序时,需要通过这个结构体来注册窗口类,为后续创建窗口做准备。
2. 结构体成员
cbSize(UINT类型):
这是结构体的大小,以字节为单位。在使用WNDCLASSEX结构体之前,必须将这个成员设置为sizeof(WNDCLASSEX),这样Windows API函数才能正确地解析结构体中的其他成员。例如:
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
style(UINT类型):
用于指定窗口类的样式。可以使用预定义的窗口类样式常量来组合设置。例如,CS_HREDRAW | CS_VREDRAW表示当窗口的水平或垂直尺寸改变时,窗口将被重绘。常见的样式常量还有CS_OWNDC(为每个窗口实例分配一个独立的设备上下文)、CS_DBLCLKS(允许窗口接收双击消息)等。例如:
wcex.style = CS_HREDRAW | CS_VREDRAW;
lpfnWndProc(WNDPROC类型):
这是一个函数指针,指向窗口过程函数(WndProc)。窗口过程函数负责处理发送到窗口的所有消息,如鼠标点击、键盘按键、窗口大小改变等消息。例如:
wcex.lpfnWndProc = WndProc;
// WndProc是自定义的窗口过程函数,用于处理消息
cbClsExtra(int类型):
用于指定为窗口类分配的额外字节数。这些额外字节可以用于存储与窗口类相关的自定义数据。不过在实际应用中,这个成员不常使用。例如:
wcex.cbClsExtra = 0;
cbWndExtra(int类型):
用于指定为每个窗口实例分配的额外字节数。与cbClsExtra不同,它是为每个窗口实例(而不是窗口类)分配的额外空间,也可用于存储与窗口相关的自定义数据。例如:
wcex.cbWndExtra = 0;
hInstance(HINSTANCE类型):
这个成员保存应用程序实例的句柄。它通常是从WinMain函数的参数中获取的,用于加载与窗口类相关的资源,如图标、光标等。例如:
HINSTANCE hInstance;
// 假设hInstance已在WinMain函数中正确获取
wcex.hInstance = hInstance;
hIcon(HICON类型):
用于指定窗口类的大图标。这个图标将在窗口最小化或者在任务栏中显示。图标资源可以通过LoadIcon函数从可执行文件或其他资源文件中加载。例如:
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
// IDI_MAINICON是图标的资源标识符,假设已定义
hCursor(HCURSOR类型):
用于指定窗口类的光标形状。当鼠标指针移到这个窗口类创建的窗口上时,就会显示指定的光标。光标资源可以通过LoadCursor函数加载。例如:
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
// IDC_ARROW是标准箭头光标的标识符
hbrBackground(HBRUSH类型):
用于指定窗口的背景颜色或背景画刷。可以是一个纯色画刷,也可以是一个图案画刷。例如:
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
// 将窗口背景设置为系统默认的窗口颜色
lpszMenuName(LPCTSTR类型):
用于指定窗口类关联的菜单资源名称。如果窗口有菜单,这个成员就指向菜单资源的名称。在资源脚本文件(.rc文件)中定义菜单资源后,可以通过这个名称来关联菜单和窗口类。例如:
wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
// IDR_MENU1是菜单资源的标识符,假设已定义
lpszClassName(LPCTSTR类型):
这是窗口类的名称。这个名称是一个字符串,用于唯一标识这个窗口类。在注册窗口类时使用这个名称,并且在创建窗口时也需要指定这个窗口类的名称。例如:
wcex.lpszClassName = "MyWindowClass";
// 自定义的窗口类名称
hIconSm(HICON类型):
用于指定窗口类的小图标。这个小图标通常用于在任务栏等地方显示。同样可以通过LoadIcon函数加载小图标资源。例如:
wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALLICON));
// IDI_SMALLICON是小图标的资源标识符,假设已定义
3. 使用示例
以下是一个简单的示例,展示如何使用WNDCLASSEX结构体来注册一个窗口类:
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = NULL; wcex.lpszClassName = "MyWindowClass"; wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALLICON)); if (!RegisterClassEx(&wcex)) { return 0; } HWND hWnd = CreateWindow("MyWindowClass", "My Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, iCmdShow); UpdateWindow(hWnd); // 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
在这个示例中,首先在WinMain函数中填充WNDCLASSEX结构体的各个成员,然后使用RegisterClassEx函数注册窗口类。如果注册成功,就可以使用CreateWindow函数创建一个基于这个窗口类的窗口,之后通过ShowWindow和UpdateWindow函数显示和更新窗口,最后进入消息循环来处理窗口消息。WndProc函数是窗口过程函数,用于处理各种窗口消息,如WM_DESTROY消息,当窗口被销毁时,发送WM_DESTROY消息,在WndProc函数中通过PostQuitMessage函数来退出消息循环。