专栏导航上一篇Windows 编程基础 RECT 结构体回到目录下一篇第3章[标签 Win32] 处理 WM_DESTROY 消息本节前言对于本节所讲解的知识有可能你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点请你自行查阅。我呢也会提到一部分的参考课节。但是呢你不应该依赖于我的主动提及。最好呢你自己能够多去了解和查看本专栏目录。学习本节所讲的知识需要你事先了解过本章的完整代码。完整的代码请参考下述文章链接。参考课节第3章[标签 Win32] 本章程序代码本节我们来讲解本章代码是如何来处理 WM_PRINT 消息的。本节的讲解我会大段地抄录佩措尔德的教材。没办法他写得太好了我很难写出别的什么样子来。一. WM_PAINT 消息窗口过程函数 WndProc 所处理的另一条消息是 WM_PAINT 。这条消息在 Windows 编程中非常重要。当窗口的客户区部分或全部“无效”且必须“更新”时应用程序将得到此通知。这也就意味着窗口必须被“重绘”。何种情况下客户区会变为无效当窗口被首次创建时整个客户区都是无效的因为此时应用程序尚未在该窗口上绘制任何东西。第一条 WM_PAINT 消息将指示窗口过程在窗口客户区进行绘制。关于第一条 WM_PAINT 消息它通常在应用程序调用 WinMain 中的 UpdateWindow 时出现。我认为第一条 WM_PAINT 消息出现的时机大家应该把它给记下来。在之前讲解 WM_CREATE 消息的时候我讲解了它的产生时机。第一条 WM_CREATE 消息一般是在 Windows 程序的 WinMain 函数中调用 CreateWindow 函数来创建窗口时产生。产生 WM_CREATE 消息时程序正处在 CreateWindow 函数中尚未返回。而在这里我们需要记住第一条 WM_PRINT 消息的产生时机。为啥要记住呢因为以后我们很可能会需要去学习 WIndows 程序设计的一个重要的 C 类库MFC 。MFC包含了对 WIndows API 函数与相关数据结构的封装很多在 WIndows API 程序中会出现的东西在 MFC 中你都见不到了。为了在以后学习 MFC 的时候能够方便许多能够更好地理解 MFC 的运行机制此时你在学习 Windows API 程序设计的时候那就需要你尽量地理解好许多的基础知识了。此处 第一条 WM_PRINT 消息的产生时机这就是你需要去记住的。我们接着讲。在调整 HelloWin 窗口的尺寸时客户区也会变为无效。你可能还记得在前面程序中我们将 HelloWin 的 WNDCLASS 结构体变量 wndclass 的 style 字段设置成了【CS_HREDRAW | CS_VREDRAW】。这就表示当窗口的横向尺寸和纵向尺寸发生变化时整个窗口都应该宣布变为无效。在此之后窗口过程函数会接收到一条 WM_PRINT 消息。如果先最小化 HelloWin然后再将窗口恢复到原先的尺寸Windows 并不会保存客户区的内容。因为在图形环境中这需要保存的内容太多了。Windows 所采取的策略是宣布窗口无效。窗口过程接收到 WM_PRINT 消息以后会自行恢复窗口的内容。在屏幕中拖动窗口导致窗口之间发生重叠时WIndows 并不会负责保存被另一个窗口覆盖的区域。当被覆盖区域在后来不再被遮挡时窗口被标记为无效。窗口过程会接收到一条 WM_PRINT 消息并对窗口的内容进行重绘。对 WM_PRINT 消息的处理几乎总是从调用 BeginPaint 函数开始代码如下。hdc BeginPaint(hwnd, ps);而以 EndPaint 函数结束代码如下。EndPaint(hwnd, ps);在这两个函数调用中第一个参数均为程序的窗口句柄而第二个参数均为指向一个类型为 PAINTSTRUCT 结构体的指针。PAINTSTRUCT 结构体包含一些窗口过程用来对客户区进行绘制的信息。在下一章我们将介绍该结构体中的各个字段。而现在我们只管在 BeginPaint 和 EndPaint 函数中使用它。在 BeginPaint 调用期间如果客户区的背景尚未被擦除则 Windows 会对其进行擦除。擦除背景时使用的画刷是在用于注册窗口类的 WNDCLASS 结构体中的 hbrBackground 字段中指定的。在 HelloWin 中所使用的画刷是库存的白色画刷即 Windows 会将窗口的背景清除为白色。BeginPaint 调用将使整个客户区有效并返回一个“设备环境句柄”。设备环境其英文为 Device Context是指物理输出设备如视频显示器及其设备驱动程序。在 Prosise 的 MFC 教材中他将设备环境称作设备描述表并将设备环境句柄称作设备描述表句柄。在国内的许多的 Windows 程序设计教材中也将设备环境称作设备描述表。在本专栏中我在写作 Win32 章节时我会与佩措尔德先生的教材保持一致采用“设备环境”的翻译术语而在写作 MFC 章节时会与 Prosise 的教材保持一致采用“设备描述表”的翻译术语。我们需要设备环境句柄以在窗口的客户区显示文本和图形。使用由 BeginPaint 函数返回的设备环境句柄是无法在客户区以外的区域进行绘制的。EndPaint 函数用于释放设备环境句柄以使其无效。对资源的申请与释放这应该是成对出现的东西。在学习 WIndows 程序设计的时候你应该可以多次接触到申请资源与释放资源的操作。我认为这种申请与释放资源的机制算是编程中的一种难点了。这会儿我对此还掌握得不好。希望你在学习的时候能够逐渐地掌握申请与释放资源的知识吧。这种申请资源与释放资源的机制让 Windows 程序设计显得十分专业。学好这样的东西对于你的编程技能会是很好的一种锻炼与提升。如果一个窗口过程不对 WM_PRINT 消息进行处理这是极其罕见的则这类消息必须交给 DefWindowProc 来处理。DefWindowProc 所做的只是简单地依次调用 BeginPaint 和 EndPaint以使客户区变为有效。当 WndProc 调用完 BeginPaint 之后它对 GetClientRect 进行调用。GetClientRect(hwnd, rect);该函数的第一个参数是程序的窗口句柄。第二个参数为指向类型为 RECT 的矩形结构体的指针。该结构具有四个类型为 LONG 型的字段名称分别为 lefttoprightbottom 。关于 RECT 结构体类型我们之前有讲解过文章链接如下。参考课节Windows 编程基础 RECT 结构体GetClientRect 函数将依据窗口尺寸来对这四个字段进行设置。其中left 和 top 字段总会被设置为 0而 right 和 bottom 字段会分别被设置为客户区的宽度和高度单位是像素。WndProc 并未对该 RECT 结构体做任何处理而仅仅是将其赋给一个指针而作为 DrawText 函数的第四个参数。图1DrawText 函数所实现的功能与其名称一致即绘制文本。由于该函数完成的是绘制功能因此其第一个参数为由 BeginPaint 函数所返回的设备环境句柄。第二个参数是所要绘制的文本内容。第三个参数设为 -1表示该文本字符串以 0 作为结尾。DrawText 函数的最后一个参数是一组位标记这些标记的定义位于 WinUser.h 中。DrawText 函数完成的是输出显示文本的功能看起来DrawText 函数应该属于 GDI 函数。但是呢实际上它是一个相当高层的绘制函数因而属于用户模块。这些标记指示所显示的文本应在第四个参数所限定的矩形区域内单行显示并且水平和垂直居中。按照这种方式对该函数进行调用就会使字符串 Hello, Windows Program ! 显示在客户区的中央。在这里标记 DT_SINGLELINE 指示所显示的文本字符串 Hello, Windows Program ! 在第四个参数所限定的矩形区域内单行显示。标记 DT_CENTER 指示所显示的文本字符串 Hello, Windows Program ! 在第四个参数所限定的矩形区域内水平居中显示。标记 DT_VCENTER 指示所显示的文本字符串 Hello, Windows Program ! 在第四个参数所限定的矩形区域内垂直居中显示。无论何时当客户区变为无效时如调整窗口尺寸时WndProc 都将接收到一条新的 WM_PRINT 消息。WndProc 通过调用 GetClientRect 函数可以获得更新后的窗口尺寸并再次将这行文本显示在调整尺寸后的窗口客户区的中央。总 结这一节写得实在是没啥意思。因为我想不出要咋去组织语言来写。所以呢只好大段抄录了。单纯的抄录实在是没意思啊。专栏导航上一篇Windows 编程基础 RECT 结构体回到目录下一篇第3章[标签 Win32] 处理 WM_DESTROY 消息