绘制窗口
你已创建窗口。 现在,你想要在其中显示一些内容。 在 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 结构。 当前更新区域在 PAINTSTRUCT 的 rcPaint 成员中提供。 此更新区域是相对于工作区定义的:
在绘制代码中,有两个基本选项:
- 绘制整个工作区,而不考虑更新区域的大小。 任何不属于更新区域的内容都已剪切。 也就是说,操作系统会忽略它。
- 通过仅绘制更新区域内窗口的部分进行优化。
如果始终绘制整个工作区,则代码将更简单。 但是,如果你有复杂的绘制逻辑,则跳过更新区域以外的区域会更有效。
以下代码行使用系统定义的窗口背景色 (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 发出窗口已完成绘制本身的信号。