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函数来退出消息循环。

C++编程API库