创建窗口

本文介绍如何创建和显示窗口。

窗口类

窗口类定义多个窗口可能共有的一组行为。 例如,在一组按钮中,当用户选择按钮时,每个按钮都有类似的行为。 当然,按钮并不完全相同。 每个按钮都显示自己的文本字符串,并具有自己的屏幕坐标。 每个窗口唯一的数据称为 实例数据

每个窗口都必须与一个窗口类相关联,即使程序曾经只创建该类的一个实例。 窗口类不是 C++ 意义上的类。 相反,它是操作系统内部使用的数据结构。 窗口类在运行时向系统注册。 若要注册新窗口类,请填写 WNDCLASS 结构:

// Register the window class.
const wchar_t CLASS_NAME[]  = L"Sample Window Class";

WNDCLASS wc = { };

wc.lpfnWndProc   = WindowProc;
wc.hInstance     = hInstance;
wc.lpszClassName = CLASS_NAME;

必须设置以下结构成员:

  • lpfnWndProc 是指向应用程序定义的函数(称为 窗口过程窗口过程)的指针。 窗口过程定义窗口的大部分行为。 目前,此值是函数的向前声明。 有关详细信息,请参阅 编写窗口过程
  • hInstance 是应用程序实例的句柄。 从 的 hInstance 参数 wWinMain获取此值。
  • lpszClassName 是标识窗口类的字符串。

类名是当前进程的本地名称,因此该名称只需在进程中是唯一的。 但是,标准 Windows 控件也有类。 如果使用这些控件中的任何一个,则必须选取与控件类名称不冲突的类名。 例如,按钮控件的窗口类名为 Button

WNDCLASS 结构包含此处未显示的其他成员。 可以将它们设置为零,如本示例所示,也可以填充它们。 有关详细信息,请参阅 WNDCLASS

接下来,将 WNDCLASS 结构的地址传递给 RegisterClass 函数。 此函数将窗口类注册到操作系统。

RegisterClass(&wc);

创建窗口

若要创建窗口的新实例,请调用 CreateWindowEx 函数:

HWND hwnd = CreateWindowEx(
    0,                              // Optional window styles.
    CLASS_NAME,                     // Window class
    L"Learn to Program Windows",    // Window text
    WS_OVERLAPPEDWINDOW,            // Window style

    // Size and position
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

    NULL,       // Parent window    
    NULL,       // Menu
    hInstance,  // Instance handle
    NULL        // Additional application data
    );

if (hwnd == NULL)
{
    return 0;
}

有关详细的参数说明,请参阅 CreateWindowEx。 下面是一个快速摘要:

  • 第一个参数允许指定窗口的一些可选行为,例如,透明窗口。 将默认行为的此参数设置为零。
  • CLASS_NAME 是窗口类的名称。 此名称定义要创建的窗口的类型。
  • 不同类型的窗口以不同的方式使用窗口文本。 如果窗口具有标题栏,则文本将显示在标题栏中。
  • 窗口样式是一组标志,用于定义窗口的一些外观。 常 量WS_OVERLAPPEDWINDOW 实际上是与按位 OR组合的多个标志。 这些标志共同为窗口提供标题栏、边框、系统菜单以及 “最小化” 和“ 最大化 ”按钮。 这组标志是顶级应用程序窗口最常见的样式。
  • 对于位置和大小,常 量CW_USEDEFAULT 表示使用默认值。
  • 下一个参数为新窗口设置父窗口或所有者窗口。 如果 要创建子窗口,则设置父窗口。 对于顶级窗口,请将此值设置为 NULL
  • 对于应用程序窗口,下一个参数定义窗口的菜单。 此示例不使用菜单,因此值为 NULL
  • hInstance 是实例句柄,如前所述。 请参阅 WinMain:应用程序入口点
  • 最后一个参数是指向 类型 void*为 的任意数据的指针。 可以使用此值将数据结构传递到窗口过程。 有关使用此参数的一种可能方法,请参阅 管理应用程序状态

CreateWindowEx 返回新窗口的句柄,如果函数失败,则返回零。 若要显示窗口,即使窗口可见,请将窗口句柄传递给 ShowWindow 函数:

ShowWindow(hwnd, nCmdShow);

hwnd 参数是 CreateWindowEx 返回的窗口句柄。 nCmdShow 参数可用于最小化或最大化窗口。 操作系统通过 wWinMain 函数将此值传递给程序。

下面是用于创建窗口的完整代码。 请记住, WindowProc 仍只是函数的向前声明。

// Register the window class.
const wchar_t CLASS_NAME[]  = L"Sample Window Class";

WNDCLASS wc = { };

wc.lpfnWndProc   = WindowProc;
wc.hInstance     = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

// Create the window.

HWND hwnd = CreateWindowEx(
    0,                              // Optional window styles.
    CLASS_NAME,                     // Window class
    L"Learn to Program Windows",    // Window text
    WS_OVERLAPPEDWINDOW,            // Window style

    // Size and position
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

    NULL,       // Parent window    
    NULL,       // Menu
    hInstance,  // Instance handle
    NULL        // Additional application data
    );

if (hwnd == NULL)
{
    return 0;
}

ShowWindow(hwnd, nCmdShow);

恭喜,你创建了一个窗口!

现在,窗口不包含任何内容或与用户交互。 在实际的 GUI 应用程序中,窗口将响应来自用户和操作系统的事件。 下一部分介绍窗口消息如何提供这种交互性。

请参阅

继续转到 “窗口消息” 以继续本模块。