绘制窗口

你已创建窗口。 现在,你想要在其中显示一些内容。 在 Windows 术语中,这称为绘制窗口。 混合使用隐喻,窗口是一个空白画布,等待你填充它。

有时,程序会启动绘制以更新窗口的外观。 在其他时候,操作系统会通知你必须重新绘制窗口的一部分。 发生这种情况时,操作系统会向窗口发送 WM_PAINT 消息。 必须绘制的窗口部分称为 更新区域

首次显示窗口时,必须绘制窗口的整个工作区。 因此,在显示窗口时,始终会收到至少一 条WM_PAINT 消息。

显示窗口更新区域的插图

你只负责绘制工作区。 周围的框架(包括标题栏)由操作系统自动绘制。 完成绘制工作区后,清除更新区域,这会告知操作系统,在发生更改之前,它不需要发送另一条 WM_PAINT 消息。

现在,假设用户移动了另一个窗口,使其遮挡了窗口的一部分。 当遮挡部分再次变为可见时,该部分将添加到更新区域,并且窗口将收到另一 条WM_PAINT 消息。

显示当两个窗口重叠时更新区域如何更改的插图

如果用户拉伸窗口,更新区域也会更改。 在下图中,用户向右拉伸窗口。 窗口右侧的新公开区域将添加到更新区域:

显示调整窗口大小时更新区域如何更改的插图

在我们的第一个示例程序中,绘制例程非常简单。 它只用纯色填充整个工作区。 不过,此示例足以演示一些重要概念。

switch (uMsg)
{
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // All painting occurs here, between BeginPaint and EndPaint.

        FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

        EndPaint(hwnd, &ps);
    }
    return 0;
}

通过调用 BeginPaint 函数启动绘制操作。 此函数使用有关重画请求的信息填充 PAINTSTRUCT 结构。 当前更新区域在 PAINTSTRUCTrcPaint 成员中提供。 此更新区域是相对于工作区定义的:

显示工作区源的插图

在绘制代码中,有两个基本选项:

  • 绘制整个工作区,而不考虑更新区域的大小。 任何不属于更新区域的内容都已剪切。 也就是说,操作系统会忽略它。
  • 通过仅绘制更新区域内窗口的部分进行优化。

如果始终绘制整个工作区,则代码将更简单。 但是,如果你有复杂的绘制逻辑,则跳过更新区域以外的区域会更有效。

以下代码行使用系统定义的窗口背景色 (COLOR_WINDOW) 使用 单一颜色填充更新区域。 COLOR_WINDOW指示的实际颜色取决于用户的当前配色方案。

FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

FillRect 的详细信息对于此示例并不重要,但第二个参数提供要填充的矩形的坐标。 在本例中,我们将整个更新区域 (PAINTSTRUCT) 的 rcPaint 成员传入。 在第一 个WM_PAINT 消息中,需要绘制整个工作区,因此 rcPaint 将包含整个工作区。 在后续 WM_PAINT 消息中, rcPaint 可能包含一个较小的矩形。

FillRect 函数是图形设备接口 (GDI) 的一部分,该接口长期以来一直为 Windows 图形提供支持。 在 Windows 7 中,Microsoft 引入了名为 Direct2D 的新图形引擎,该引擎支持高性能图形操作,例如硬件加速。 Direct2D 还可通过 Windows Vista 的平台更新对 Windows Vista 和 Windows Server 2008 的 Windows Server 2008 平台更新使用。 仍完全支持 (GDI。)

完成绘制后,调用 EndPaint 函数。 此函数清除更新区域,向 Windows 发出窗口已完成绘制本身的信号。

下一步

关闭窗口