画笔
2015-10-21 09:41
281 查看
摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P131
在 Windows 程序中,使用句柄来操作画笔。Windows 头文件 WINDEF.H 定义画笔句柄的类型为 HPEN。可以使用这个类型定义一个变量(例如 hPen):
除了明确地定义 hPen 变量,还可以将 GetStockObject 调用和 SelectObject 调用组合在一条语句中:
SelectObject 函数返回一个先前选入设备环境的画笔的句柄。如果使用一个新的设备环境,并且调用:
这里是创建画笔的一般过程:调用 CreatePen 或者 CreatePenIndirect 函数创建一个“逻辑画笔”,它只是说明你想得到一个什么样的画笔。这些函数会返回一个逻辑画笔的句柄。然后需要调用 SelectObject 函数将画笔选入设备环境中。接着,就可以使用这个新的画笔来绘制线条。一次只能有一支画笔被选入设备环境。释放设备环境之后(或者将其他画笔选入设备环境之后),需要调用 DeleteObject 函数来删除你创建的逻辑画笔。此后,画笔的句柄不再有效。
逻辑画笔是一个“GDI 对象”,一个程序可以创建 6 种GDI 对象,它是其中之一,其他 5 种分别是画刷、位图、区域、字体和调色板。除了调色板之外,所有这些对象都通过 SelectObject 函数选入设备环境。
下面三条规则控制画笔等 GDI 对象的使用:
最终应当删除你所创建的所有 GDI 对象。
当 GDI 对象被选入一个有效的设备环境时,不要删除它。
不要删除备用对象。
这些规则都是有道理的,但是有时候会有点棘手。下面我们将通过例子来帮助理解这些规则。
CreatePen 函数的一般语法如下:
其中,参数 iPenStyle 决定画笔绘制的是实现或者虚线或电线。这个参数可以使用定义在 WINGDI.H 头文件中的下列标识符。图 5-18 显示了每种样式产生的线条。
![](https://img-blog.csdn.net/20151021101851162)
对于 PS_SOLID、PS_NULL 和 PS_INSIDEFRAME 样式,参数 iWidth 表示画笔的宽度。当 iWidth 值为 0 时,Windows 把画笔的宽度设定为 1 个像素。备用画笔总是 1 个像素宽。如果指定使用虚线或点线样式,同时把画笔宽度设定为大于 1 个 像素,那么 Windows 会使用实心的画笔来代替。
CreatePen 的参数 crColor 是一个 COLORREF 值,它用来指定画笔的颜色。对所有的除了 PS_INSIDEFRAME 之外的画笔样式,当将画笔选入到设备环境时,Windows 将该颜色转换为设备所能表示的最近的纯色。PS_INSIDEFRAME 画笔样式是唯一能够使用抖动色的画笔样式,并且只有当画笔宽度大于 1 时才如此。
PS_INSIDEFRAME 画笔样式用于填充区域的函数时有另外一个奇特之处。当使用非 PS_INSIDEFRAME 样式的画笔样式时,如果用于绘制轮廓的画笔宽度大于 1 个像素,那么画笔的中心会处于边界之上,这样画出的轮廓线部分将会在边框之外。但是对于 PS_INSIDEFRAME 画笔样式,整个轮廓线都会在边框内。
也可以通过建立一个类型为 LOGPEN(“逻辑画笔”)的结构,并调用 CreatePenIndirect 函数来建立一个画笔。如果你的程序在初始化时需要创建很多不同的画笔,这种方法会很有效。
为了使用 CreatePenIndirect 函数,首先要定义一个类型为 LOGPEN 的结构:
可以通过将该结构的地址传递到 CreatePenIndirect 函数来创建画笔:
注意:CreatePen 和 CreatePenIndirect 函数不需要设备环境句柄。在调用 SelectObject 之前,这些函数创建的逻辑画笔和设备环境没有任何联系,可以为几种不同的设备,例如屏幕和打印机,使用相同的逻辑画笔。
这里给出创建、选择和删除画笔的一种方法。假定程序使用三种画笔(宽度为 1 的黑色画笔、宽度为 3 的红色画笔和黑色的点线画笔)。可以首先定义存储这些画笔的句柄的静态变量:
可以随时创建画笔,还可以将 CreatePen 和 SelectObject 调用组合到一条语句中:
下面给出另一个方法。当将一支画笔选入到一个新创建的设备环境时,保存 SelectObject 返回的画笔句柄:
如果有一个画笔的句柄,LOGPEN 结构中各个字段成员的值可以通过调用 GetObject 函数获得:
如果需要获得当前被选入设备环境的画笔句柄,则调用:
我将在第 17 章讨论另外一个画笔创建函数:ExtCreatePen。
空隙的颜色是由设备环境的两个属性(背景模式和背景颜色)决定的。默认的背景模式是 OPAUQE(不透明),这就意味着 Windows 使用背景颜色来填充空隙,背景颜色在默认时是白色。这与许多程序在窗口类中用 WHITE_BRUSH 来擦除窗口背景的做法相同。
可以通过调用下面的函数来改变 Windows 填充空隙的背景颜色:
也可以通过将背景模式改为 TRANSPARENT(透明)来阻止 Windows 填充空隙:
5.3.5 使用现有画笔
调用本节介绍的任何一个画线函数时,Windows 都会使用当前选入设备环境的“画笔”来绘制直线。画笔决定了线条的颜色、宽度和样式,样式可以是实线、点线或者虚线。画笔的默认设备环境 BLACK_PEN。该画笔会绘制一条实心的宽度为 1 个像素的黑色线条。BLACK_PEN 是 Windows 提供的三种“备用画笔”(stock pen)的一种。另外两种分别是 WHITE_PEN 和 NULL_PEN。NULL_PEN 表示不绘制任何图形的画笔。你也可以创建自己的画笔。在 Windows 程序中,使用句柄来操作画笔。Windows 头文件 WINDEF.H 定义画笔句柄的类型为 HPEN。可以使用这个类型定义一个变量(例如 hPen):
HPEN hPen;调用 GetStockObject 函数可以获取备用画笔的句柄。例如想使用名为 WHITE_PEN 的备用画笔。可以按照如下方式获取画笔句柄:
hPen = GetStockObject (WHITE_PEN);现在必须把该画笔选入设备环境:
SelectObject (hdc, hPen);现在,当前画笔变成白色画笔。也就是说在该函数调用之后,绘制的所有线条都将使用 WHITE_PEN,直到将另一种画笔选入设备环境 或者你释放了设备环境句柄。
除了明确地定义 hPen 变量,还可以将 GetStockObject 调用和 SelectObject 调用组合在一条语句中:
SelectObject (hdc, GetStockObject (WHITE_PEN));接着,如果想恢复使用 BLACK_PEN,也可以只使用一条语句来获取那个备用对象(BLACK_PEN)的句柄,同时将它选入设备环境:
SelectObject (hdc, GetStockObject (BLACK_PEN));
SelectObject 函数返回一个先前选入设备环境的画笔的句柄。如果使用一个新的设备环境,并且调用:
hPen = SelectObject (hdc, GetStockObject (WHITE_PEN));那么设备环境中的当前画笔就变为 WHITE_PEN,变量 hPen 将是 BLACK_PEN 画笔的句柄。可以接着通过下面的调用将 BLACK_PEN 重新选入设备环境:
SelectObject (hdc, hPen);
5.3.6 创建、选择和删除画笔
尽管使用备用对象中的画笔非常方便,但只能使用实心的黑色画笔、实心的白色画笔或者没有画笔三种情况。如果想获得更丰富的效果,则必须创建自己的画笔。这里是创建画笔的一般过程:调用 CreatePen 或者 CreatePenIndirect 函数创建一个“逻辑画笔”,它只是说明你想得到一个什么样的画笔。这些函数会返回一个逻辑画笔的句柄。然后需要调用 SelectObject 函数将画笔选入设备环境中。接着,就可以使用这个新的画笔来绘制线条。一次只能有一支画笔被选入设备环境。释放设备环境之后(或者将其他画笔选入设备环境之后),需要调用 DeleteObject 函数来删除你创建的逻辑画笔。此后,画笔的句柄不再有效。
逻辑画笔是一个“GDI 对象”,一个程序可以创建 6 种GDI 对象,它是其中之一,其他 5 种分别是画刷、位图、区域、字体和调色板。除了调色板之外,所有这些对象都通过 SelectObject 函数选入设备环境。
下面三条规则控制画笔等 GDI 对象的使用:
最终应当删除你所创建的所有 GDI 对象。
当 GDI 对象被选入一个有效的设备环境时,不要删除它。
不要删除备用对象。
这些规则都是有道理的,但是有时候会有点棘手。下面我们将通过例子来帮助理解这些规则。
CreatePen 函数的一般语法如下:
hPen = CreatePen (iPenStyle, iWidth, crColor);
其中,参数 iPenStyle 决定画笔绘制的是实现或者虚线或电线。这个参数可以使用定义在 WINGDI.H 头文件中的下列标识符。图 5-18 显示了每种样式产生的线条。
对于 PS_SOLID、PS_NULL 和 PS_INSIDEFRAME 样式,参数 iWidth 表示画笔的宽度。当 iWidth 值为 0 时,Windows 把画笔的宽度设定为 1 个像素。备用画笔总是 1 个像素宽。如果指定使用虚线或点线样式,同时把画笔宽度设定为大于 1 个 像素,那么 Windows 会使用实心的画笔来代替。
CreatePen 的参数 crColor 是一个 COLORREF 值,它用来指定画笔的颜色。对所有的除了 PS_INSIDEFRAME 之外的画笔样式,当将画笔选入到设备环境时,Windows 将该颜色转换为设备所能表示的最近的纯色。PS_INSIDEFRAME 画笔样式是唯一能够使用抖动色的画笔样式,并且只有当画笔宽度大于 1 时才如此。
PS_INSIDEFRAME 画笔样式用于填充区域的函数时有另外一个奇特之处。当使用非 PS_INSIDEFRAME 样式的画笔样式时,如果用于绘制轮廓的画笔宽度大于 1 个像素,那么画笔的中心会处于边界之上,这样画出的轮廓线部分将会在边框之外。但是对于 PS_INSIDEFRAME 画笔样式,整个轮廓线都会在边框内。
也可以通过建立一个类型为 LOGPEN(“逻辑画笔”)的结构,并调用 CreatePenIndirect 函数来建立一个画笔。如果你的程序在初始化时需要创建很多不同的画笔,这种方法会很有效。
为了使用 CreatePenIndirect 函数,首先要定义一个类型为 LOGPEN 的结构:
LOGPEN logpen;这个结构由三个字段:lopnSytle(无符号整型,或 UINT)表示画笔样式,lopnWidth(一个 POINT 结构)是以逻辑单位表示的画笔宽度,还有 lopnColor(COLORREF)表示画笔的颜色。Windows 仅使用 lopnWidth 结构中的 x 字段来设置画笔的宽度,y 字段会被忽略。
可以通过将该结构的地址传递到 CreatePenIndirect 函数来创建画笔:
hPen = CreatePenIndirect (&logpen);
注意:CreatePen 和 CreatePenIndirect 函数不需要设备环境句柄。在调用 SelectObject 之前,这些函数创建的逻辑画笔和设备环境没有任何联系,可以为几种不同的设备,例如屏幕和打印机,使用相同的逻辑画笔。
这里给出创建、选择和删除画笔的一种方法。假定程序使用三种画笔(宽度为 1 的黑色画笔、宽度为 3 的红色画笔和黑色的点线画笔)。可以首先定义存储这些画笔的句柄的静态变量:
static HPEN hPen1, hPen2, hPen3;在处理 WM_CREATE 消息时,可以创建这三种画笔:
hPen1 = CreatePen(PS_SOLD, 1, 0); hPen2 = CreatePen(PS_SOLD, 3, RGB(255, 0, 0)); hPen3 = CreatePen(PS_DOT, 0, 0);在处理 WM_PAINT 消息时(或者在任何拥有有效的设备环境句柄时),可以将其中任何一支画笔选入到设备环境,并且使用它来绘制线条:
SelectObject(hdc, hPen2); [line-drawing functions] SelectObject(hdc, hPen1); [line-drawing functions]在处理 WM_DESTROY 消息时,可以删除这三种画笔:
DeleteObject(hPen1); DeleteObject(hPen2); DeleteObject(hPen3);这是用于创建、选择和删除画笔最直接的方法。但是很显然,程序必须知道需要使用什么样的画笔。因此可能需要在每个 WM_PAINT 消息处理时创建画笔,并在调用 EndPaint 函数后删除它们。(也可以在调用 EndPaint 函数前删除它们,但是需要小心,不要删除已被选入设备环境中的当前画笔。)
可以随时创建画笔,还可以将 CreatePen 和 SelectObject 调用组合到一条语句中:
SelectObject (hdc, CreatePen (PS_DASH, 0, RGB(255, 0, 0));现在,在绘制直线时,将使用一个红色的虚线画笔。红色虚线绘制完成后,可以删除画笔。槽糕,你没有保存画笔句柄,怎么才能删除画笔呢?前面介绍过,SelectObject 函数将返回先前被选入设备环境的画笔句柄。也就是说,可以通过将备用的 BLACK_PEN 选入到设备环境中来得到需要被删除的画笔句柄,然后删除它:
DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN)));
下面给出另一个方法。当将一支画笔选入到一个新创建的设备环境时,保存 SelectObject 返回的画笔句柄:
hPen = SelectObject (hdc, CreatePen (PS_DASH, 0, RGB (255, 0, 0)));hPen 究竟是什么呢?如果这是在获得设备环境后第一次调用 SelectObject 函数,hPen 就是 BLACK_PEN 的句柄。现在可以在同一条语句中选择该画笔到设备环境,并且删除自己创建的画笔(第二次 SelectObject 调用返回你创建的画笔的句柄):
DeleteObject (SelectObject (hdc, hPen));
如果有一个画笔的句柄,LOGPEN 结构中各个字段成员的值可以通过调用 GetObject 函数获得:
GetObject (hPen, sizeof(LOGPEN), (LPVOID) &logpen);
如果需要获得当前被选入设备环境的画笔句柄,则调用:
hPen = GetCurrentObject (hdc, OBJ_PEN);
我将在第 17 章讨论另外一个画笔创建函数:ExtCreatePen。
5.3.7 填充空隙
使用点式画笔和虚线画笔会带来这样一个问题:点和虚线之间的空隙是什么颜色呢?你觉得呢?空隙的颜色是由设备环境的两个属性(背景模式和背景颜色)决定的。默认的背景模式是 OPAUQE(不透明),这就意味着 Windows 使用背景颜色来填充空隙,背景颜色在默认时是白色。这与许多程序在窗口类中用 WHITE_BRUSH 来擦除窗口背景的做法相同。
可以通过调用下面的函数来改变 Windows 填充空隙的背景颜色:
SetBKColor (hdc, crColor);crColor 参数和画笔颜色中使用时一样,Windows 会将背景色转换为纯色。定义在设备环境的当前背景颜色可以通过调用 GetBKColor 函数获得。
也可以通过将背景模式改为 TRANSPARENT(透明)来阻止 Windows 填充空隙:
SetBKMode (hdc, TRANSPARENT);这样,Windows 会忽略背景颜色,从而不填充空隙。当前的背景模式可以通过调用 GetBKMode 函数获取(要么是 TRANSPARENT,要么是 OPAQUE)。
相关文章推荐
- HTML5+CSS3技术制作的数据云,下载即可使用,真正方便于程序员的demo
- nginx学习
- eclipse 插件未安装成功定位
- Nginx集群(转)
- 大牛总结:关注技术
- 遇见gtest -- HelloGtest
- 2015网页导航设计趋势&案例大搜罗
- 禁止Apache显示目录索引
- jQuery checkbox attr checked不起作用
- 基础篇(四) Service生命周期和进程内通信
- Spark学习笔记之-Spark 命令及程序入口
- Using Arel to Compose SQL Queries
- 测试我的第一篇博客
- 听说网易用户信息泄露了?
- 数组中的逆序对的总数
- python -- 抽奖
- [笔记]--Oracle 终止expdp/impdp进程运行的方法
- 威尔逊定理
- cardview使用笔记
- Android Studio解决unspecified on project app resolves to an APK archive which is not supported