第4章,[标签 Win32] :绘制信息结构

专栏导航

上一篇:第4章,[标签 Win32] :获取设备环境句柄的第一个方法

回到目录

下一篇:无

本节前言

对于本节所讲解的知识,有可能,你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点,请你自行查阅。

我呢,也会提到一部分的参考课节。但是呢,你不应该依赖于我的主动提及。最好呢,你自己能够多去了解和查看本专栏目录。

本节内容,来自对佩措尔德教材内容的大段抄录。

我们开始。

一. 绘制信息结构体的定义

前面曾提到,Windows 将为每个窗口维护一个 "绘制信息结构" ,这便是 PAINTSTRUCT 。这个结构的定义代码如下。

复制代码
/***  此结构体定义在 WinUser.h 中 ***/
typedef struct tagPAINTSTRUCT {
  HDC  hdc;
  BOOL fErase;
  RECT rcPaint;
  BOOL fRestore;
  BOOL fIncUpdate;
  BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;

当程序调用 BeginPaint 函数时,Windows 将自动填充这个结构体中的字段。程序只能够使用前三个字段,其他的供 Windows 内部使用。

hdc 是设备环境句柄。BeginPaint 函数的返回值就是这个设备环境句柄的值。这里表现了 Windows 典型的冗余性。

关于 fErase 字段,大多数情况下,此字段将被设置为 FALSE,也就是 0 。这意味着,Windows 在先前的 BeginPaint 函数中已经擦除了无效区域的背景。如果想要在窗口过程中自定义背景擦除方式,必须自己处理 WM_ERASEBKGND 消息。在 WinMain 函数初始化时,用于注册窗口类的 WNDCLASS 结构中的 hbrBackground 字段指定了一个画刷,Windows 就使用这个画刷来擦除背景。

很多 Windows 程序指定了一个白色背景画刷。下面的语句可以完成这个任务。

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);

但是,当你的程序通过调用 InvalidateRect 函数使客户区中的一个矩形失效时,InvalidateRect 函数的最后一个参数将指定背景是否要被擦除。如果参数是 FALSE,也就是 0,Windows 将不会擦除背景。同时,在调用 BeginPaint 函数之后,PAINTSTRUCT 结构的 fErase 字段的值将是 TRUE (非 0)。

PAINTSTRUCT 结构的 rcPaint 字段将是一个 RECT 类型的结构。在第 3 章中,我们知道,RECT 结构使用 4 个字段,left, top, right 和 bottom 定义了一个矩形。PAINTSTRUCT 结构中的 rcPaint 字段定义了无效矩形的边界。这 4 个字段的值是以像素为单位的,并相对于客户区的左上角。该无效矩形就是用户程序需要进行重新绘制的区域。

PAINTSTRUCT 结构中的 rcPaint 矩形不仅仅是无效矩形,而且还是一个裁剪(Clipping)矩形。这意味着 Windows 将把绘制限制在这个矩形里。更确切地说,如果无效区域不是一个矩形,Windows 将把绘制限制在这个区域内。

在处理 WM_PAINT 消息时,在调用 BeginPaint 之前,调用以下的函数,可以在该更新矩形之外绘制。

InvalidateRect(hwnd, NULL, TRUE);

这个调用将整个客户区无效化,并使其后调用的 BeginPaint 擦除原有的背景。如果将最后的一个参数设置为 FALSE,则随后调用的 BeginPaint 函数将不会擦除背景。也就是说,原来的背景将被保留。

通常来说,对于 Windows 程序,最方便的做法是在收到 WM_PAINT 消息后,简单地重绘整个客户区,而不管 rcPaint 的值如何。例如,如果客户区的显示包括一个圆,但是只有一部分落在无效区域里时,只画这个圆的一部分并不实际。简单的做法是重画整个圆。

在使用从 BeginPaint 函数返回的设备环境句柄时,Windows 无论如何也不会在 rcPaint 定义的矩形之外绘制。

在第 3 章的 HelloWin 程序中,我们在处理 WM_PAINT 消息时,并没有理会无效区域。如果文本显示的地方正好落在无效区域里,DrawText 函数就恢复那块区域。如果没有,那么 Windows 在处理 DrawText 调用时,会发现,它不需要做任何事。但是这个过程要花时间。所以,关心程序运行效率和速度的程序员(我希望每个程序员都会如此)会在处理 WM_PAINT 消息时,使用无效矩形,以避免不必要的 GDI 函数调用。如果绘制时需要从磁盘中读取文件(例如位图文件),这一点尤其重要。

专栏导航

上一篇:第4章,[标签 Win32] :获取设备环境句柄的第一个方法

回到目录

下一篇:无

相关推荐
rjc_lihui5 小时前
Windows 运程共享linux系统的方法
windows
czhaii5 小时前
单片机最佳入门多线程示例讲解
c语言·单片机
失忆爆表症6 小时前
01_项目搭建指南:从零开始的 Windows 开发环境配置
windows·postgresql·fastapi·milvus
Yu_Lijing6 小时前
网络复习篇——网络基础(一)
网络·c++·笔记
Bella的成长园地6 小时前
为什么c++中的条件变量的 wait() 函数需要配合while 循环或谓词?
c++·面试
charlee446 小时前
为什么现代 C++ 库都用 PIMPL?一场关于封装、依赖与安全的演进
c++·智能指针·raii·pimpl·编译防火墙·封装设计
MSTcheng.6 小时前
CANN ops-math算子的跨平台适配与硬件抽象层设计
c++·mfc
code monkey.6 小时前
【Linux之旅】Linux 进程间通信(IPC)全解析:从管道到共享内存,吃透进程协作核心
linux·c++·ipc
薛定谔的猫喵喵6 小时前
基于C++ Qt的唐代诗歌查询系统设计与实现
c++·qt·sqlite
阿昭L6 小时前
C++异常处理机制反汇编(三):32位下的异常结构分析
c++·windows·逆向工程