前言:
学习笔记,随时更新。如有谬误,欢迎指正。
说明:
- 红色字体为较为重要部分。
- 绿色字体为个人理解部分。
原文链接:https://learn.microsoft.com/en-us/windows/win32/gdi/device-contexts
6 设备上下文
-
设备上下文是一种结构,用于定义一组图形对象及其关联属性,以及影响输出的图形模式。
-
图形对象包括用于线条绘制的笔、用于绘制和填充的画刷、用于复制或滚动部分屏幕的位图、用于定义可用颜色集的调色板、用于剪裁和其他操作的区域,以及用于绘制和绘制操作的路径。
6.1 关于设备上下文
-
设备独立性是微软 Windows 的主要特性之一。应用程序可以在各种设备上绘制和打印输出。支持这种设备独立性的软件包含在 两个动态链接库中。 第一个是 GDI.dll ,被称为图形设备接口( GDI );第二个被称为设备驱动程序。第二个库的名称取决于应用程序输出的设备。例如,如果应用程序在 VGA 显示器上的窗口的客户端区域绘制输出,则该库是 VGA.dll ;如果应用程序在爱普生 FX-80 打印机上打印输出,则此库为 Epson9.dll 。
-
一个应用程序必须通知 GDI 加载一个特定的设备驱动程序,一旦驱动程序被加载,就准备好了绘制操作(如选择线条颜色和宽度,画刷图案和颜色,字体字体,裁剪区域,等等)的设备。这些任务是通过创建和维护设备上下文( DC )来完成的。与大多数结构不同,应用程序永远不能直接访问 DC ;相反,它通过调用各种函数间接地对结构进行操作。
6.1.1 图形对象
-
与 DC 相关联的笔、画刷、位图、调色板、区域和路径称为它的图形对象。以下属性与每个对象相关联:
图形对象 关联的属性 位图( Bitmaps ) 大小,以字节为单位;尺寸,以像素为单位;颜色格式;压缩方案等等。 画刷( Brushes ) 样式、颜色、图案和原点。 字体( Fonts ) 字体名称、宽度、高度、粗细、字符集等。 逻辑调色板( Logical Palette ) 颜色和大小 (或颜色的数量) 。 路径( Paths ) 形状。 笔( Pens ) 样式、宽度和颜色。 区域( Regions ) 位置和尺寸。 -
当应用程序创建 DC 时,系统自动在其中存储一组默认对象(没有默认位图或路径)。应用程序可以通过调用 GetCurrentObject 和 GetObject 函数来检查默认对象的属性。应用程序可以通过创建新对象并调用 SelectObject 将其选择到 DC 中来更改这些默认值。
-
应用程序可以使用 SetDCBrushColor 将当前画刷颜色设置为指定的颜色值。 GetDCBrushColor 函数返回 DC 画刷颜色。
-
应用程序可以使用 SetDCPenColor 函数将笔的颜色设置为指定的颜色值。 GetDCPenColor 函数返回 DC 笔的颜色。
6.1.2 图形模式
-
Windows 支持五种图形模式,允许应用程序指定颜色的混合方式、输出的显示位置、输出的缩放方式等等。这些模式存储在 DC 中,如下表所示:
图形模式 说明 背景 定义背景颜色如何与位图和文本操作的现有窗口或屏幕颜色混合。 绘制 定义前景色如何与笔、画刷、位图和文本操作的现有窗口或屏幕颜色混合。 映射 定义图形输出如何从逻辑(或世界)空间映射到窗口、屏幕或打印纸上。 多边形填充 定义如何使用画刷图案填充复杂区域的内部。 拉伸 定义位图被压缩(或按比例缩小)时,位图颜色如何与现有窗口或屏幕颜色混合。 -
与图形对象一样,系统使用默认图形模式初始化 DC 。应用程序可以通过调用以下函数来查询和设置图形模式:
图形模式 查询函数 设置函数 背景 GetBkMode SetBkMode 绘制 GetROP2 SetROP2 映射 GetMapMode SetMapMode 多边形填充 GetPolyFillMode SetPolyFillMode 拉伸 GetStretchBltMode SetStretchBltMode
6.1.3 设备上下文类型
-
有四种类型的 DC :显示器、打印机、内存(或兼容)和信息。每种类型都有特定的用途,如下表所示:
设备上下文 说明 显示器 支持视频显示器上的绘制操作。 打印机 支持在打印机或绘图仪上进行绘制操作。 内存 支持对位图进行绘制操作。 信息 支持获取设备数据。
6.1.3.1 显示设备上下文
-
应用程序通过调用 BeginPaint 、 GetDC 或 GetDCEx 函数来获得显示 DC 。通常,应用程序只有在必须在客户端区域中绘制时才能获得显示 DC 。可以通过调用 GetWindowDC 函数来获得窗口设备上下文。当应用程序完成绘制时,必须通过调用 EndPaint 或 ReleaseDC 函数来释放 DC 。
-
视频显示器有五种类型的 DC :类设备上下文、通用设备上下文、私有设备上下文、窗口设备上下文、父设备上下文。
6.1.3.1.1 类设备上下文
- 系统严格支持类设备上下文以便与 16 位版本的 Windows 兼容。在编写应用程序时,避免使用类设备上下文,应使用私有设备上下文代替。
6.1.3.1.2 通用设备上下文
-
通用设备上下文是系统在特殊缓存中维护的显示 DC 。通用设备上下文用于执行不频繁绘制操作的应用程序。在系统返回 DC 句柄之前,它使用默认对象、属性和模式初始化通用设备上下文。应用程序执行的任何绘制操作都使用这些默认值,除非调用 GDI 函数之一来选择新对象、更改现有对象的属性或选择新模式。
-
因为只有有限数量的通用设备上下文存在,应用程序应该在完成绘制后释放它们。当应用程序释放通用设备上下文时,对默认数据的任何更改都将丢失。
6.1.3.1.3 私有设备上下文
-
私有设备上下文是与普通设备上下文不同的显示 DC ,即使在应用程序释放它们之后,它们依然保留对默认数据的任何更改。私有设备上下文用于执行大量绘制操作的应用程序,例如计算机辅助设计( CAD )应用程序、桌面发布应用程序、绘制和绘画应用程序等等。私有设备上下文不是系统缓存的一部分,因此在使用后不需要释放。在类的最后一个窗口被销毁后,系统会自动删除一个私有设备上下文。
-
应用程序在初始化 WNDCLASS 结构的样式成员并调用 RegisterClass 函数时,通过首先指定 CS_OWNDC 窗口类样式来创建私有设备上下文。(有关窗口类的更多信息,请参见窗口类。)
-
在用 CS_OWNDC 样式创建窗口之后,应用程序可以调用 GetDC 、 GetDCEx 或 BeginPaint 函数以来获得私有设备上下文的句柄。应用程序可以继续使用这个句柄(和关联的 DC ),直到用这个类创建的窗口被删除。在窗口被删除之前,系统会保留对图形对象及其属性或图形模式的任何更改。
6.1.3.1.4 窗口设备上下文
- 窗口设备上下文使应用程序能够在窗口的任何地方绘制,包括非客户端区域。窗口设备上下文通常由处理 WM_NCPAINT 和 WM_NCACTIVATE 消息的应用程序使用,这些消息用于具有自定义非客户端区域的窗口。不建议将窗口设备上下文用于任何其他目的。 有关详细信息,请参阅 GetWindowDC 。
6.1.3.1.5 父设备上下文
- 父设备上下文使应用程序能够最大限度地减少为窗口设置裁剪区域所需的时间。应用程序通常使用父设备上下文来加速控件窗口的绘制,而不需要私有或类设备上下文。例如,系统为按钮和编辑控件使用父设备上下文。父设备上下文仅用于子窗口,而不能用于顶级窗口或弹出窗口。 有关详细信息,请参阅父显示设备上下文。
6.1.3.2 打印机设备上下文
-
打印机 DC 可用于在点阵式打印机、喷墨打印机、激光打印机或绘图仪上进行打印。
-
应用程序通过调用 CreateDC 函数并提供适当的参数来创建打印机 DC 。当应用程序完成打印时,它通过调用 DeleteDC 函数删除打印机 DC 。应用程序必须删除(而不是释放)打印机DC ,当应用程序试图使用 ReleaseDC 函数释放打印机 DC 时,该函数将会失败。
-
有关详细信息,请参阅打印机输出。
6.1.3.3 内存设备上下文
-
为了使应用程序能够将输出放在内存中,而不是将其发送到实际设备,需要为位图操作使用一个称为内存设备上下文的特殊设备上下文。内存 DC 使系统能够将内存的一部分视为虚拟设备。它是内存中的位数组,应用程序可以临时使用它来存储在正常绘图面上创建的位图的颜色数据。由于位图与设备兼容,因此内存 DC 有时也被称为兼容设备上下文。
-
内存 DC 存储特定设备的位图图像。应用程序可以通过调用 CreateCompatibleDC 函数来创建内存 DC 。
-
内存 DC 中的原始位图只是一个占位符。它的尺寸是一个像素乘一个像素。在应用程序开始绘制之前,它必须通过调用 SelectObject 函数选择具有适当宽度和高度的位图到 DC 中。要创建适当尺寸的位图,请使用 CreateBitmap 、 CreateBitmapIndirect 或 CreateCompatibleBitmap 函数。位图被选择到内存 DC 后,系统用一个足够大的数组来存储指定矩形像素的颜色信息来替换单比特数组。
-
当应用程序将 CreateCompatibleDC 返回的句柄传递给绘制函数之一时,请求的输出不会出现在设备的绘图面上。相反,系统将生成的直线、曲线、文本或区域的颜色信息存储在位数组中。应用程序可以通过调用 BitBlt 函数将存储在内存中的图像复制回绘图面,将内存 DC 标识为源设备上下文,将窗口或屏幕 DC 标识为目标设备上下文。
-
在调色板设备上显示 DIB 或从 DIB 创建的 DDB 时,可以通过让逻辑调色板以匹配系统调色板的布局来提高绘制图像的速度。为此,使用 NUMRESERVED 值调用 GetDeviceCaps 以获得系统中保留颜色的数量。然后调用 GetSystemPaletteEntries ,用相应的系统颜色填充逻辑调色板的第一个和最后一个 NUMRESERVED/2 项。例如,如果 NUMRESERVED 为 20 ,你将用系统颜色填充逻辑调色板的前10项和最后10项。然后用来自 DIB 的颜色填充逻辑调色板的其余 256-NUMRESERVED 颜色(在我们的示例中是剩余的 236 种颜色),并在这些颜色上设置 PC_NOCOLLAPSE 标志。
6.1.3.4 信息设备上下文
- 信息 DC 用于查询默认设备数据。例如,应用程序可以调用 CreateIC 函数来为特定型号的打印机创建信息 DC ,然后调用 GetCurrentObject 和 GetObject 函数来查询默认的笔或画画刷属性。由于系统可以查询设备信息,而无需创建通常与其他类型的设备上下文相关联的结构,因此信息 DC 所涉及的开销要小得多,并且创建速度比任何其他类型都快得多。应用程序使用信息 DC 查询完数据后,必须调用 DeleteDC 函数。
6.1.4 设备上下文操作
-
应用程序可以在设备上下文中执行以下操作:
- 枚举现有图形对象。
- 选择新的图形对象。
- 删除现有图形对象。
- 保存当前图形对象及其属性和图形模式。
- 恢复以前保存的图形对象及其属性和图形模式。
此外,应用程序可以使用设备上下文来:
- 确定如何转换图形输出。
- 取消冗长的绘制操作(由多线程应用程序中的线程开启)。
- 将打印机重置为特定状态。
6.1.4.1 对图形对象的操作
-
在应用程序创建了显示器或打印机 DC 之后,它就可以开始在相关设备上绘制,或者在内存 DC 的情况下,它就可以开始在存储在内存中的位图上绘制。然而,在绘制开始之前,有时在绘制过程中,通常需要用新对象替换默认对象。
-
应用程序可以通过调用 GetCurrentObject 和 GetObject 函数来检查默认对象的属性。 GetCurrentObject 函数返回一个标识当前笔、画刷、调色板、位图或字体的句柄, GetObject 函数初始化一个包含该对象属性的结构。
-
有些打印机提供常驻笔、画刷和字体,可用于提高应用程序中的绘制速度。两个函数可用于枚举这些对象: EnumObjects 和 EnumFontFamilies 。如果应用程序必须枚举常驻笔或画刷,它可以调用 EnumObjects 函数来检查相应的属性。如果应用程序必须枚举常驻字体,它可以调用 EnumFontFamilies 函数(它也可以枚举 GDI 字体)。
-
一旦应用程序确定需要替换默认对象,它就通过调用以下创建函数之一来创建新对象:
图形对象 函数 位图( Bitmaps ) CreateBitmap 、 CreateBitmapIndirect 、 CreateCompatibleBitmap 、 CreateDiscardableBitmap 、 CreateDIBitmap 画刷( Brushes ) CreateBrushIndirect 、 CreateDIBPatternBrush 、 CreateDIBPatternBrushPt 、 CreateHatchBrush 、 CreatePatternBrush 、 CreateSolidBrush 字体( Fonts ) CreateFont 、 CreateFontIndirect 调色板( Palette ) CreatePalette 笔( Pens ) CreatePen 、 CreatePenIndirect 、 ExtCreatePen 区域( Regions ) CreateEllipticRgn 、 CreateEllipticRgnIndirect 、 CreatePolygonRgn 、 CreatePolyPolygonRgn 、 CreateRectRgn 、 CreateRectRgnIndirect 、 CreateRoundRectRgn
6.1.4.2 取消绘制操作
- 当复杂的绘图应用程序执行冗长的图形操作时,它们会消耗宝贵的系统资源。通过利用系统的多任务特性,应用程序可以使用线程和 CancelDC 函数来管理这些操作。例如,如果线程 A 执行的图形操作正在消耗所需的资源,线程 B 可以调用 CancelDC 函数来停止该操作。
6.1.4.3 查询设备数据
-
应用程序可以使用以下函数通过设备上下文查询设备数据: GetDeviceCaps 和 DeviceCapabilities 。
-
GetDeviceCaps 可以查询以下设备的通用设备数据:
- 光栅显示器
- 点阵打印机
- 喷墨打印机
- 激光打印机
- 矢量绘图仪
- 光栅相机
数据包括设备支持的功能,包括设备分辨率(用于视频显示)、颜色格式(用于视频显示和彩色打印机)、图形对象的数量、光栅功能、曲线绘制、线条绘制、多边形绘制和文本绘制。应用程序通过提供标识适当设备上下文的句柄以及指定函数要查询的数据类型的索引来查询此数据。
-
DeviceCapabilities 函数查询特定于打印机的数据,包括可用纸盒的数量、打印机的双工功能、打印机支持的分辨率、支持的最大和最小纸张尺寸,等等。应用程序通过提供指定打印机设备和端口的字符串以及指定函数要查询的数据类型的索引来查询此数据。
6.1.4.4 保存、还原和重置设备上下文
-
应用程序保存、恢复和重置设备上下文的功能包括: SaveDC 、 RestoreDC 和 ResetDC 。 SaveDC 函数在一个特殊的 GDI 堆栈上记录当前 DC 的图形对象及其属性和图形模式。绘图应用程序可以在用户开始绘制之前调用这个函数,并保存应用程序的原始状态,为用户提供一个干净的画板。为了返回到原始状态,应用程序可以调用 RestoreDC 函数。
-
ResetDC 用于重置打印机 DC 数据。应用程序调用此函数来重置纸张方向、纸张大小、输出比例因子、要打印的副本数、纸张源(或存储箱)、双工模式等。通常,应用程序在用户更改了打印机选项之一并且系统发出 WM_DEVMODECHANGE 消息后调用此函数。
6.1.5 已启用 ICM 的设备上下文函数
-
尽管设备之间的成像技术和色彩功能存在差异, Microsoft 的图像颜色管理( Image Color Management, ICM )也能确保彩色图像、图形对象或文本对象在任何设备上的呈现尽可能接近其原始意图。 (有关详细信息,请参阅 Windows 颜色系统。)
-
以下 DC 函数启用了对 ICM 的支持: CreateCompatibleDC 、 CreateDC 、 GetDCBrushColor 、 GetDCPenColor 、 ResetDC 、 SelectObject 、 SetDCBrushColor 、 SetDCPenColor 。
6.2 使用设备上下文函数
6.2.1 获取私有显示设备上下文
- 有关详细信息,请参阅获取私有显示设备上下文。
6.2.2 查询打印机的功能
- 有关详细信息,请参阅查询打印机的功能。
6.2.3 查询图形对象属性并选择新的图形对象
- 有关详细信息,请参阅查询图形对象属性并选择新的图形对象。
6.2.4 设置和查询设备上下文画刷颜色值
- 有关详细信息,请参阅设置和查询设备上下文画刷颜色值。
6.2.5 设置笔或画刷颜色
- 有关详细信息,请参阅设置笔或画刷颜色。
6.2.6 获取显示监视器上的信息
- 有关详细信息,请参阅获取显示监视器上的信息。
6.3 设备上下文参考
6.3.1 设备上下文函数
- 有关详细信息,请参阅设备上下文函数。
6.3.2 设备上下文结构体
- 有关详细信息,请参阅设备上下文结构体。
6.3.3 设备上下文消息
- 有关详细信息,请参阅设备上下文消息。