5.2 设备环境

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

        开始绘图之前,首先让我们在第 4 章的基础上更严谨的讨论一下设备环境。

        如果希望在图形输出设备(比如屏幕或者打印机)上绘制图形,必须首先获取设备环境(即 DC)的句柄。当 Windows 把这个句柄交给你的程序,Windows 同时也就给予你使用这个设备的权限。接着,在 GDI 函数中将这个句柄作为一个参数,告诉 Windows 在哪个设备上进行绘图。

       设备环境包含许多决定 GDI 函数如何工作的属性。这些属性使得 GDI 函数只需要提供少量的参数(如起始坐标),而不需要提供 Windows 在设备上显示对象时需要的所有信息。例如,当你调用 TextOut 函数时,仅需要在函数中指定设备环境句柄、起始坐标、文本以及文本的长度,不需要指定字体、文本的颜色、文本背景的颜色或者字符间距。所有这些属性都是设备环境的一部分。当你想改变这些属性时,可以调用函数来执行。之后调用 TextOut 函数就会使用新的设备环境的属性。

5.2.1  获取设备环境句柄

        Windows 提供几种方法来获取设备环境句柄。如果在处理一条消息时获取了视频显示器的设备环境,则应当在退出当前窗口过程之前释放它。释放句柄以后,它将不再有效。对打印机设备环境句柄,规则并没有那么严格。

        获取和释放设备环境句柄最常用的方法是在处理 WM_PAINT 消息时使用 BeginPaint 函数和 EndPaint 函数:

hdc = BeginPaint (hwnd, &ps);
      [Other program lines]
EndPaint (hwnd, &ps);
其中,变量 ps 是一个类型为 PAINTSTRUCT 的结构。这个结构中的字段 hdc 和 BeginPaint 函数返回的设备环境句柄的值相同。PAINTSTRUCT 结构还包含一个名为 rcPaint 的矩形结构,该结构定义了一个包围窗口客户区无效范围的矩形。使用从 BeginPaint 函数获取的设备环境句柄,就只能在这个矩形区域内绘图。调用 BeginPaint 函数将使这个区域有效。

        设备环境句柄还可以在处理非 WM_PAINT 消息时由 Windows 程序获取:

hdc = GetDC (hwnd);
      [Other program lines]
ReleaseDC (hwnd);
其中,设备环境指的是窗口句柄为 hwnd 的窗口客户区。调用在这些函数和使用 BeginPaint、EndPaint 函数组合的主要差别是从 GetDC 函数返回的句柄可以在整个客户区内绘制。并且,GetDC 和 ReleaseDC 函数并不使任何客户区的无效区域变为有效。

        Windows 程序还可以获得用于整个窗口的,而不仅仅是窗口客户区的设备环境句柄:

hdc = GetWindowDC (hwnd);
      [Other program lines]
ReleaseDC (hwnd);
这里的设备环境除了包括客户区,还包含窗口标题栏、菜单、滚动条和客户区的外框。应用程序很少使用 GetWindowDC 函数。如果你想尝试使用它,则还应当捕获 WM_NCPAINT(nonclient paint,非客户区绘制)消息,Windows 使用这个消息在窗口的非客户区绘图。

        调用 BeginPaint、GetDC 和 GetWindowDC 函数可以获得在视频显示器上与一个特定的窗口相关联的设备环境。还有一个更通用的用于获取设备环境句柄的函数是 CreateDC:

hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData);
      [Other program lines]
DeleteDC (hwnd);
例如,你可以通过调用下面的函数获取当前整个屏幕的设备环境句柄:

hdc = CreateDC (TEXT("DISPLAY"), NULL, NULL, NULL);

 在窗口外输出文字或图像不是很好,但是对于一些特殊的应用还是有用的。(虽然在官方文档中并没有提到这种方法,但是你还是可以通过在调用 GetDC 时使用一个 NULL 参数来得到整个屏幕的设备环境。) 

        有时候,仅需要获取一些关于设备环境的信息,而不需要在上面绘制任何东西。在这些情况下,可以调用 CreateIC 函数获取一个“信息上下文”(Information Context)句柄。这个函数的参数和 CreateDC 函数的参数相同。例如:

hdc = CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL);

 但是,往设备上写东西时,不能使用信息上下文句柄。 

        处理位图时,有时可能会用到一个“内存设备环境”:

hdcMem = CreateCompatibleDC (hdc);
	[Other program lines]
DeleteDC (hdcMem);
可以把一个位图选入内存设备环境,并且调用 GDI 函数绘制这个位图。

        如前所述,图元文件是以二进制形式编码的 GDI 函数调用的集合。它可以通过获取一个图元文件的设备环境来创建:

hdcMeta = CreateMetaFile (pszFilename);
	[Other program lines]
hmf = CloseMetaFile (hdcMeta);
在图元文件设备环境有效时,使用 hdcMeta 所做的任何 GDI 调用都不会被直接显示出来,它们都会变成图元文件的一部分。当你调用 CloseMetaFile 时,图元文件设备环境句柄变为无效,该函数返回一个图元文件句柄(hmf)。

5.2.2  获取设备环境的信息

        设备环境通常指的是物理的显示设备,如视频显示器或打印机。经常需要获取这些设备的某些信息,包括显示器的大小(以像素或者物理尺寸的方式)和它的色彩能力。这些信息可以通过调用 GetDeviceCaps(意思是获取设备的能力)函数来获取:

iValue = GetDeviceCaps(hdc, iIndex);
其中,参数 iIndex 是定义在 WINGDI.H 头文件中的 29 个标识符之一。例如,当 iIndex 的值为 HORZRES 时,GetDeviceCaps 函数以像素为单位返回设备的宽度;使用 VERTRES 参数值会以像素为单位返回设备的高度。如果 hdc 是一个屏幕设备环境的句柄,这里所获取的信息和从 GetSystemMetrics 函数获取的信息是一样的。如果 hdc 是一个打印机设备环境,那么 GetDeviceCaps 将以像素为单位返回打印机显示区域的高度和宽度。

        还可以使用 GetDeviceCaps 函数来确定设备处理各种类型图形的能力。通常这对于视频显示器并不重要,但是对于打印机却非常重要。例如,大多数的绘图仪不能绘制位图图像,通过调用 GetDeviceCaps 函数可以让你提前知道这一情况。

5.2.7  保存设备环境

        通常,当调用 GetDC 或者 BeginPaint 函数时,Windows 返回一个设备环境,它的所有属性都被设定为默认值。当设备环境调用 ReleaseDC 或者 EndPaint 函数时,对属性所做的任何改变都会丢失。如果程序需要使用非默认的设备环境属性,则必须在每次获取一个新的设备环境句柄时初始化这个设备环境:

case WM_PAINT:
    hdc = BeginPaint (hwnd, &ps);
          [initialize device context attributes]
          [point client area of window]    
    EndPaint (hwnd, &ps);
    return 0;

        尽管这种方法通常令人满意,但是你可能喜欢在释放设备环境时保存对属性做的改变,以便在下次调用 GetDC 或者 BeginPaint 函数时,这些属性仍然有效。为此,在注册窗口类时将 CS_OWNDC 标志作为窗口类样式的一部分即可:

wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
现在,每个基于这个窗口类创建的窗口都有它的私有的设备环境,当窗口被销毁时,这个设备环境继续存在。使用 CS_OWNDC 样式时,只需要初始化设备环境属性一次,例如,在处理 WM_CREATE 消息期间:

case WM_CREATE:
        hdc = GetDC (hwnd);
           [initialize device context attributes] 
        ReleaseDC(hwnd, hdc);
        return 0;
在再次改变这些属性值之前,他们会一直有效。

        CS_OWNDC 样式仅影响通过 GetDC 和 BeginPaint 函数获得的设备环境,通过其他函数(如 GetWindowDC 函数)获取的设备环境并不受影响。以前,CS_OWNDC 样式不提倡使用,因为它需要一定的内存开销。现在,在处理大量图形的 Windows NT 程序中,它可以改善性能。但是即使使用了 CS_OWNDC 样式,设备环境句柄在退出窗口过程前也应该被释放。

        在一些情况下,可能想改变某些设备环境属性,然后使用变更后的属性进行绘制,接着再恢复原来的设备环境。为了简化这个过程,可以调用下面的函数保存设备环境的状态:

idSaved = SaveDC(hdc);
现在,可以改变一些属性。而调用下面的函数则可以返回调用 SaveDC 函数之前存在的设备环境:

RestoreDC (hdc, idSaved);
可以在调用 RestoreDC 之前,多次调用 SaveDC。

        不过,大部分程序员会以一种不同的方式使用 SaveDC 和 RestoreDC 函数,这种方式非常类似于汇编语言中的 PUSH 和 POP 指令。调用 SaveDC 函数时,返回值可以不必保存:

SaveDC(hdc);
然后可以改变一些属性,并再次调用 SaveDC 函数。而为了将设备环境恢复到已保存的状态,则调用下面的函数:

RestoreDC (hdc, -1);
这会使设备环境恢复到最近一次由 SaveDC 函数保存的状态。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值