跳转到内容

Windows 编程/GDI 和绘图

来自维基教科书,开放世界中的开放书籍

此页面为Windows 编程书籍中的一个存根。您可以通过扩展它来提供帮助。


本页将讨论使用 Windows GDI 库进行图形和绘图。

GDI 是 Windows 的原始图形 API。但是,DirectX 图形基础架构 现在推荐用于其改进的 GPU 函数使用、alpha 混合抗锯齿[1]

设备上下文

[编辑 | 编辑源代码]

里面有什么?以及它们的默认值

GDI 对象(每种类型一个)Windows 版本设置函数获取函数
画笔零宽度黑色画笔(表示在任何缩放比例下 1 像素宽度)2SelectObject(SelectPen、SelectBrush、SelectFont)GetCurrentObject
画刷白色实心画刷2
字体系统默认字体2
调色板系统默认调色板(见下文)3SelectPalette
颜色空间?4SetColorSpace
目标位图(不适用于元文件上下文)取决于创建 DC 的函数2SelectObject(SelectBrush)
裁剪区域取决于创建 DC 的函数2GetClipRgn(GetClipBox)
数字
映射模式、缩放和偏移量1 单位 = 1 像素,原点 = 左/上2Get/Set MapMode、WindowOrgEx、WindowExtEx、ViewportOrgEx、ViewportExtEx
变换矩阵(旋转、剪切、缩放、偏移量)平等4SetWorldTransform、ModifyTransformGetWorldTransform
文本颜色,也用于涉及 blt 操作的黑白黑色2SetTextColorGetTextColor
背景颜色,用于文本 / 网格画刷 / 虚线背景和一些 blt 操作白色2SetBkColorGetBkColor
斜接限制(锐利多边形角的裁剪)10.0F(线宽的十倍)4SetMiterLimitGetMiterLimit
画刷原点(用于对齐图案画刷)0/02SetBrushOrgExGetBrushOrgEx
枚举和布尔开关
启用高级 GDI 函数4SetGraphicsModeGetGraphicsMode
复杂多边形内或外(PolyFillMode)交替规则2SetPolyFillModeGetPolyFillMode
文本对齐顶部/左侧2SetTextAlignGetTextAlign
文本 / 网格画刷 / 虚线输出是否具有不透明背景颜色有背景2SetBkModeGetBkMode
位图在 blt 操作中如何拉伸?3SetStretchBltModeGetStretchBltMode
画笔 / 画刷和表面如何组合(布尔运算)复制画笔2SetROP2GetROP2
其他
路径(准备好的线)空路径4BeginPath、EndPath ...-
上下文堆栈2SaveDCRestoreDC

待续...

画刷对象

[编辑 | 编辑源代码]

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,然后用相关信息填充它。对于此示例,我们只需要 pshdc 成员。这是一个指向我们窗口设备上下文的句柄。接下来,我们创建一个矩形。这包含我们要绘制此矩形的左上角和右下角坐标。坐标相对于窗口客户区的左上角。我们还必须创建一个画刷,否则 Windows 将不知道要使用什么颜色来绘制矩形。最后,我们调用 FillRect,并传递参数 ps.hdc、指向 rectangle 的指针和 hbr(我们的画刷)。这会将矩形直接绘制到我们窗口的设备上下文,然后从那里绘制到屏幕上。在每次绘画操作后,都需要清理我们使用的任何 GDI 对象,在本例中为 hbrps

高级提示

[编辑 | 编辑源代码]

由于 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) {
 ...
}

元文件

[编辑 | 编辑源代码]

下一章

[编辑 | 编辑源代码]
  1. QuinnRadich. "Windows 图形架构概述 - Win32 应用". learn.microsoft.com. 检索于 2023-04-11.
华夏公益教科书