Windows 编程/GDI 和绘图
此页面为Windows 编程书籍中的一个存根。您可以通过扩展它来提供帮助。
本页将讨论使用 Windows GDI 库进行图形和绘图。
GDI 是 Windows 的原始图形 API。但是,DirectX 图形基础架构 现在推荐用于其改进的 GPU 函数使用、alpha 混合 和 抗锯齿[1]。
里面有什么?以及它们的默认值
GDI 对象(每种类型一个) | Windows 版本 | 设置函数 | 获取函数 | |
画笔 | 零宽度黑色画笔(表示在任何缩放比例下 1 像素宽度) | 2 | SelectObject(SelectPen、SelectBrush、SelectFont) | GetCurrentObject |
画刷 | 白色实心画刷 | 2 | ||
字体 | 系统默认字体 | 2 | ||
调色板 | 系统默认调色板(见下文) | 3 | SelectPalette | |
颜色空间 | ? | 4 | SetColorSpace | |
目标位图(不适用于元文件上下文) | 取决于创建 DC 的函数 | 2 | SelectObject(SelectBrush) | |
裁剪区域 | 取决于创建 DC 的函数 | 2 | GetClipRgn(GetClipBox) | |
数字 | ||||
映射模式、缩放和偏移量 | 1 单位 = 1 像素,原点 = 左/上 | 2 | Get/Set MapMode、WindowOrgEx、WindowExtEx、ViewportOrgEx、ViewportExtEx | |
变换矩阵(旋转、剪切、缩放、偏移量) | 平等 | 4 | SetWorldTransform、ModifyTransform | GetWorldTransform |
文本颜色,也用于涉及 blt 操作的黑白 | 黑色 | 2 | SetTextColor | GetTextColor |
背景颜色,用于文本 / 网格画刷 / 虚线背景和一些 blt 操作 | 白色 | 2 | SetBkColor | GetBkColor |
斜接限制(锐利多边形角的裁剪) | 10.0F(线宽的十倍) | 4 | SetMiterLimit | GetMiterLimit |
画刷原点(用于对齐图案画刷) | 0/0 | 2 | SetBrushOrgEx | GetBrushOrgEx |
枚举和布尔开关 | ||||
启用高级 GDI 函数 | 否 | 4 | SetGraphicsMode | GetGraphicsMode |
复杂多边形内或外(PolyFillMode) | 交替规则 | 2 | SetPolyFillMode | GetPolyFillMode |
文本对齐 | 顶部/左侧 | 2 | SetTextAlign | GetTextAlign |
文本 / 网格画刷 / 虚线输出是否具有不透明背景颜色 | 有背景 | 2 | SetBkMode | GetBkMode |
位图在 blt 操作中如何拉伸 | ? | 3 | SetStretchBltMode | GetStretchBltMode |
画笔 / 画刷和表面如何组合(布尔运算) | 复制画笔 | 2 | SetROP2 | GetROP2 |
其他 | ||||
路径(准备好的线) | 空路径 | 4 | BeginPath、EndPath ... | - |
上下文堆栈 | 空 | 2 | SaveDC | RestoreDC |
待续...
Windows 使用画刷来绘制颜色并使用预定义的图案填充区域。画刷的最小尺寸为 8X8 像素,并且与画笔类似,具有三个基本特征:大小、图案和颜色。由于其 8X8 像素的最小尺寸,画刷被认为具有图案,而不是像画笔那样的样式。图案可以是实色、网格、对角线或任何其他用户定义的组合,甚至是位图图案。
case WM_PAINT: { /* This will paint a red rectangle */ HDC holdBrush; HDC hdc = BeginPaint(hwnd, &ps); HBRUSH hBrush = CreateSolidBrush(RGB(255,0,0)); holdBrush = SelectObject(hdc, hBrush); Rectangle(hdc, 10, 10, 100, 100);
DeleteObject(hBrush); /* Memory management has been omitted for brevity */ EndPaint(hwnd, &ps); break; }
画刷对象背后是什么?
在创建时,请参见 LOGBRUSH 结构 | 修改 |
---|---|
颜色(RGB 颜色,可以在实现时进行抖动) | SetDCBrushColor |
样式(实心、网格或位图) | - |
位图(对于位图样式) | - |
实现时的隐藏字段 | |
引用设备上下文(跟踪实现是否仍然有效) | UnrealizeObject |
设备相关,可能是抖动的位图,通常为 8x8 尺寸 | - |
请注意,位图图案画刷的行为与网格画刷不同,即使位图看起来像网格。网格画刷是透明的,而位图画刷是不透明的。如果使用黑白位图,黑色将被替换为设备上下文的文本颜色,白色将被替换为背景颜色。(这正是 BitBlt() 的行为。)SetBkMode() 不会起作用。但是,DC 的 ROP2 会起作用。
画笔用于创建绘制的形状周围的边框。
可见字段,请参见 LOGPEN 结构 | Windows 版本 | 修改 |
---|---|---|
宽度,以水平(!) 逻辑单位表示,0 = 1 像素 | 2 | - |
样式(实心或某种点线) | 2 | - |
用户点线样式(对于用户选择的样式) | 4 | - |
颜色 | 2 | SetDCPenColor |
画刷(内容:见上文) | 4 | - |
几何/装饰标志 | 4 | - |
提示如何绘制线端 | 4 | - |
提示如何绘制线连接 | 4 | - |
隐藏字段 | ||
引用设备上下文(跟踪其他隐藏字段的有效性) | 2 | UnrealizeObject? |
以设备像素表示的宽度 | 2 | - |
给定颜色的调色板索引 | 2 | - |
用于填充宽线的设备相关位图 | 2 | - |
导致宽度大于 1 设备像素(而不是逻辑单位)的线将作为具有绕线规则的多边形绘制。线颜色永远不会进行抖动,除非使用具有实心画刷的 ExtCreatePen。
字体用于以各种样式和尺寸显示文本和符号。Windows 2(非常基本)、3.1(引入 TrueType)和 4+(Unicode;世界变换旋转和镜像;倾斜度可能与旋转不同)之间的字体管理存在内部较大差异。
请参见 LOGFONT 结构以了解可见字段。
隐藏字段包括
- 引用设备上下文
- 设备相关位图字体表示
因此,将字体选择到设备上下文(SelectObject)可能很耗时,尤其是对于大型亚洲字体和大型字体尺寸,需要从 TrueType 模板中“绘制”所有字形到位图中。此外,与所有 GDI 对象一样,最好不要在一个上下文之间选择一个对象,因为使隐藏文件失效可能是一个耗时的过程。请注意,任何 GDI 对象都不能选择到多个 DC 中。
在 Windows 中,绘图通常由 WM_PAINT 消息处理。以下是绘制红色正方形的示例
case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); // RECT defines the upper-left and lower-right corners of a rectangle RECT rectangle = {50, 50, 250, 250}; HBRUSH hbr = CreateSolidBrush(RGB(125, 0, 0)); FillRect(ps.hdc, &rectangle, hbr); DeleteObject(hbr); EndPaint(hwnd, &ps); } break;
首先,我们创建 PAINTSTRUCT 变量 ps。这是一个包含有关绘画操作的信息的数据结构。下一行调用 BeginPaint。这将初始化 ps,然后用相关信息填充它。对于此示例,我们只需要 ps 的 hdc 成员。这是一个指向我们窗口设备上下文的句柄。接下来,我们创建一个矩形。这包含我们要绘制此矩形的左上角和右下角坐标。坐标相对于窗口客户区的左上角。我们还必须创建一个画刷,否则 Windows 将不知道要使用什么颜色来绘制矩形。最后,我们调用 FillRect,并传递参数 ps.hdc、指向 rectangle 的指针和 hbr(我们的画刷)。这会将矩形直接绘制到我们窗口的设备上下文,然后从那里绘制到屏幕上。在每次绘画操作后,都需要清理我们使用的任何 GDI 对象,在本例中为 hbr 和 ps。
由于 Windows 应该响应 WM_PAINT 和 WM_PRINTCLIENT,因此编写 WM_PAINT 处理程序的一般规则如下
case WM_PRINTCLIENT: OnPaint((HDC)wParam, NULL); break;
case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); OnPaint(ps.hdc, &ps.rcPaint); // It's a good idea to manage the update area. Other PAINTSTRUCT fields are of less usefulness. EndPaint(hwnd, &ps); }break;
// Somewhere else void OnPaint(HDC dc, RECT* rcUpdate) { ... }
- ↑ QuinnRadich. "Windows 图形架构概述 - Win32 应用". learn.microsoft.com. 检索于 2023-04-11.