4.2.1 设备环境

        摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P66

        如前所述,句柄不过是一个数值,Windows 内部使用该数值确定一个对象。用户从 Windows 获取一个句柄,然后用于其他函数。设备环境句柄是程序窗口使用 GDI 函数的“通行证”。有了设备环境句柄,就可以随心所欲地绘制你的客户区。

        设备环境(也被简称为 DC)实际上是 GDI 内部维护的一个数据结构。设备环境与特定的显示设备(例如显示或打印机)相关联。对于视频显示,设备环境通常与屏幕上的一个特定的窗口相关联。

        设备环境中的某些值是图形“属性”。这些属性决定了 GDI 绘图函数的工作细节。例如在 TextOut 函数总, 设备环境的属性决定着文本的颜色、文本背景的颜色、函数的参数 x 和 y 如何映射到窗口的客户区,以及 Windows 用什么字体显示文本。

        程序在绘制前必须获取一个设备环境句柄。在获取句柄后,Windows 会在内部的设备环境结构中填入默认的属性值。在以后的章节中,你会学到有一些 GDI 函数可以改变这些默认值。有些 GDI 函数则能让你得到这些属性的当前值。当然,还有些 GDI 函数是让你真正在窗口的客户区进行绘图的。

        当程序完成了对客户区的绘制后,它必须释放设备环境句柄。在程序释放句柄之后,这个句柄不再有效并且不能再被使用。程序必须在处理同一条消息的过程获取句柄和释放句柄。你不能在两条消息中间传递一个设备环境句柄,唯一的例外是通过调用 CreateDC 函数创建的设备环境。

        Windows 应用程序需要在屏幕上绘图时,通常有两种方法获取设备环境句柄。

4.2.2    获取设备环境句柄:方法一

        这种方法可以在处理 WM_PAINT 消息时使用。这牵涉两个函数:BeginPaint 和 EndPaint。这两个函数需要两个参数:一个是窗口的句柄,这是窗口消息处理过程的参数;另一个是一个类型为 PAINTSTRUCT 结构的变量的地址。(PAINTSTRUCT 结构定义在 WINUSER.H 头文件中。)程序通常将这个变量命名为 ps,在窗口过程中定义如下:

PAINTSTRUCT ps;

        在处理 WM_PAINT 消息时,窗口过程首先调用 BeginPaint 函数。这个函数通常会擦去无效区域的背景以便绘图。它同时还会填充 ps 结构的各个字段。函数的返回值就是设备环境句柄。通常会将它保存在一个名为 hdc 的变量中。这个变量在窗口过程中定义如下:

HDC hdc ;
HDC 数据类型定义为 32 位无符号整数。此后,程序可以调用任何一个需要设备环境句柄的 GDI 函数了,例如 TextOut。调用一次 EndPaint 函数将释放设备环境句柄。

        通常处理 WM_PAINT 消息的代码如下所示:

 case WM_PAINT:
     hdc = BeginPaint (hwnd, &ps) ;
           [使用 GDI 函数]
     EndPaint (hwnd, &ps) ;
     return 0 ;
窗口过程在处理 WM_PAINT 消息时必须成对地调用 BeginPaint 和 EndPaint。如果窗口过程不处理 WM_PAINT 消息,WM_PAINT 消息就会被传送给 Windows 默认的窗口过程 DefWindowProc。在 DefWindowProc 中,WM_PAINT 消息处理的代码如下:

 case WM_PAINT:
     BeginPaint (hwnd, &ps) ;
     EndPaint (hwnd, &ps) ;
     return 0 ;
这里除了将原来的无效区域有效化意外,在 BeginPaint 和 EndPaint 的中间不包含其他的代码。

        以下的代码是错误的:

 case WM_PAINT:
     return 0 ; // WRONG !!!

由于部分客户区是无效的,Windows 才会在消息队列中放置一条 WM_PAINT 消息。除非调用 BeginPaint 和 EndPaint 函数对(或者 ValidateRect),否则 Windows 不会将那个区域有效化。因此,Windows 将会不停地发送 WM_PAINT 消息,直到永远。

4.2.4    获取设备环境句柄:方法二

        尽管最好让程序在处理 WM_PAINT 消息时才更新整个客户区,但有时也会发现在处理非 WM_PAINT 消息时绘制部分客户区也是很有用的。有些时候,还需要设备环境句柄用作其他用途,例如获取设备环境的信息。

        你可以调用 GetDC 函数来获得窗口客户区的设备环境句柄,在使用完以后,调用 ReleaseDC 函数将它释放:

hdc = GetDC (hwnd);
[使用 GDI 函数]
ReleaseDC (hwnd, hdc);

与 BeginPaint 和 EndPaint 类似,GetDC 和 ReleaseDC 必须成对使用。在处理一条消息时,当调用 GetDC 函数后,应该在退出窗口过程之前调用 ReleaseDC。不要在处理一条消息时调用 GetDC,然后在处理另一条消息时调用 ReleaseDC。

        与从 BeginPaint 函数返回的设备环境句柄不同,从 GetDC 返回的设备环境句柄中的裁剪矩形是整个客户区。这意味着你可以在客户区的任意部分绘制,而不仅仅是在无效矩形里,也就是说如果不存在无效矩形也没有关系。与 BeginPaint 不同,GetDC 不会将无效区域有效化。如果需要将整个客户区有效化,可以像下面这样调用函数:

validateRect (hwnd, NULL);
        通常,GetDC 和 ReleaseDC 函数用于处理键盘消息(例如在字处理程序中)或者鼠标消息(例如绘图程序中)。使用这两个函数,程序可以在收到用户的键盘或鼠标输入时及时地绘制客户区,而不必为了生成 WM_PAINT 消息去刻意使客户区的一部分无效化。但是,即使程序在处理非 WM_PAINT 消息时进行了绘制,它仍然必须收集足够的信息以便在收到 WM_PAINT 时能更新显示。

        另一个与 GetDC 类似的函数是 GetWindowDC。GetDC 返回的是窗口客户区的设备环境句柄,GetWindowDC 返回的则是整个窗口的设备环境句柄。例如,程序可以使用从 GetWindowDC 返回的设备环境句柄在窗口的标题栏输出,相应的,程序也必须要处理 WM_NCPAINT(非客户区绘制)消息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值