第016讲:各种获得设备环境句柄的方法(课文解读)
以下解读来自《Windows 程序设计》(第5版 珍藏版)P103~105设备环境
如果想希望在图形输出设备(诸如屏幕或者打印机)上绘制图形,必须首先获得一个设备环境(即 DC)句柄。将句柄传回给程序时,Windows 就给了你使用设备的权限。接着,在 GDI 函数中将这个句柄作为一个参数,告诉 Windows 你将要在哪个设备上进行绘图。
设备环境包含了许多决定 GDI 函数如何工作的属性。这些属性使得 GDI 函数只需要提供少量的参数(如绘制的起始坐标),而不需要提供 Windows 在设备上显示对象时需要的所有其它信息。例如,调用 TextOut 函数时,你只需要在函数中给出设备环境句柄(hdc)、起始坐标、文字和文字的长度。你不需要指定字体、文字颜色、文字后面的背景色彩以及字符间距,因为这些属性都是设备环境的一部分。当你想改变这些属性之一时,你可以通过调用指定函数来实现,此后针对该设备环境的 TextOut 函数就会使用改变后的新属性。
小甲鱼解读:这其实很好理解,设备环境句柄(hdc)其实就是一张通行证,这张通行证上有该设备的信息(DC),有了它,你才被允许使用该设备。
获取设备环境句柄
Windows 提供了几种取得设备内容句柄的方法。如果在处理一个消息时取得了设备环境句柄,应该在退出窗口函数之前释放它(或者删除它)。一旦释放了句柄,它就不再有效了。对于打印机设备内容句柄,规则就没有这么严格(我们将在后边的教程中讨论)。
方法一:
最常用的取得并释放设备内容句柄的方法是,在处理 WM_PAINT 消息时,使用 BeginPaint 和 EndPaint 函数:
hdc = BeginPaint(hwnd, &ps);
// 其他代码
EndPaint(hwnd, &ps);
涉及的 API 函数:
[*]【API档案】BeginPaint
[*]【API档案】EndPaint
[*]【API档案】PAINTSTRUCT 结构
其中,变量 ps 是一个类型为 PAINTSTRUCT 的结构。这个结构中的字段 hdc 和 BeginPaint 函数返回的设备环境句柄的值相同。PAINTSTRUCT 结构还包含了一个名为 rcPaint 的矩形结构(【API档案】RECT 结构),该结构定义了一个包围窗户区无效范围的矩形。使用从 BeginPaint 函数获取的设备环境句柄,就只能在这个矩区域内绘图。调用 BeginPaint 函数将使这个区域有效。
方法二:
设备环境句柄还可以在处理非 WM_PAINT 消息时由 Windows 程序获取:
hdc = GetDC(hwnd);
// 其他代码
ReleaseDC(hwnd, hdc);
涉及的 API 函数:
[*]【API档案】GetDC
[*]【API档案】ReleaseDC
其中,设备环境指的是窗口句柄为 hwnd 的窗口客户区。调用这些函数和使用 BeginPaint、EndPaint 函数组合的主要差别是从 GetDC 函数返回的句柄可以在整个客户区内绘制。并且,GetDC 和 ReleaseDC 函数并不使任何客户区的无效区域变为有效。
方法三:
Windows 程序还可以获得用于整个窗口的,而不仅仅是窗口客户区的设备环境句柄:
hdc = GetWindowDC(hwnd);
// 其他代码
ReleaseDC(hwnd, hdc);
涉及的 API 函数:
[*]【API档案】GetWindowDC
[*]【API档案】ReleaseDC
这里的设备环境除了包括客户区,还包含窗口标题栏、菜单、滚动条和客户区的外框。应用程序很少使用 GetWindowDC 函数。如果你想尝试使用它,则还应当捕获 WM_NCPAINT(nonclient paint,非客户区绘制)消息,Windows 使用这个消息在窗口的非客户区绘图。
方法四:
调用 BeginPaint、GetDC 和 GetWindowDC 函数可以获得在视频显示器上与一个特定的窗口相关联的设备环境。还有一个更通用的用于获取设备环境句柄的函数是 CreateDC:
hdc = CreateDC(pszDriver, pszDevice, pszOutput, pData);
// 其他代码
DeleteDC(hdc);
涉及的 API 函数:
[*]【API档案】CreateDC
[*]【API档案】DeleteDC
例如,你可以通过调用下面的函数获取当前整个屏幕的设备环境句柄:
hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
在窗口外输出文字或图像不是很好,但是对于一些特殊的应用还是有用的。(虽然在官方文档中并没有提到这种方法,但是你还是可以通过在调用 GetDC 时使用一个 NULL 参数来得到整个屏幕的设备环境。)在后边的教学中,打印机的设备环境句柄就是使用 CreateDC 函数来获取的。
方法五:
有时候,仅需要获取一些关于设备环境的信息,而不需要在上面绘制任何东西。在这些情况下,可以调用 CreateIC 函数获取一个“信息上下文”(Information Context)句柄。这个函数的参数和 CreateDC 函数的参数相同:
hdc = CreateIC(pszDriver, pszDevice, pszOutput, pData);
// 其他代码
DeleteDC(hdc);
涉及的 API 函数:
【API档案】CreateIC
【API档案】DeleteDC
但是,往设备上写东西时,不能使用信息上下文句柄。
方法六:
处理位图时,有时可能会用到一个“内存设备环境”:
hdcMem = CreateCompatibleDC(hdc);
// 其他代码
DeleteDC(hdcMem);
涉及的 API 函数:
[*]【API档案】CreateCompatibleDC
[*]【API档案】DeleteDC
可以把一个位图选入内存设备环境,并且调用 GDI 函数绘制这个位图。我们将在后边的视频中介绍这些技术。
方法七:
前边讲过,图元文件是以二进制形式编码的 GDI 函数调用的集合。它可以通过获取一个图元文件的设备环境来创建:
hdcMeta = CreateMetaFile(pszFilename);
// 其他代码
hmf = CloseMetaFile(hdcMeta);
涉及的 API 函数:
[*]【API档案】CreateMetaFile
[*]【API档案】CloseMetaFile
在图元文件设备环境有效时,使用 hdcMeta 所做的任何 GDI 调用都不会被直接显示出来,它们都会变成图元文件的一部分。当你调用 CloseMetaFile 时,图元文件设备环境句柄变为无效,该函数返回一个图元文件句柄(hmf)。
WinSDK PAINTSTRUCT 结构还包含了一个名为 rcPaint 的矩形结构(【API档案】RECT 结构),该结构定义了一个包围窗户区无效范围的矩形。使用从 BeginPaint 函数获取的设备环境句柄,就只能在这个矩区域内绘图。调用 BeginPaint 函数将使这个区域有效。 很好的资料 自学的好帮手,好老师, 辛苦了,老师 小甲鱼,你对 设备区域的比方好难哦、好费解哦;给你个更好的比方: 各种不同的DC就好比各种不同的画家,画家要在窗口的客户区作图,画家作图需要各种画笔啦、画刷啦、位图啦。。。,所以,每次作图之前,需要将这些画图工具放到画家(设备句柄)的手里。 晕,这马多啊!
页:
[1]