尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

第5章,[Win32 章节] :创建、选择和删除画笔

第5章,[Win32 章节] :创建、选择和删除画笔 专栏导航上一篇第5章[Win32 章节] 使用现有画笔回到目录下一篇第5章[Win32 章节] 填充空隙本节前言对于本节所讲解的知识有可能你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点请你自行查阅。我呢也会提到一部分的参考课节。但是呢你不应该依赖于我的主动提及。最好呢你自己能够多去了解和查看本专栏目录。在上一节我们讲解了如何来使用系统备用画笔。本节我们来讲解如何来操作自定义画笔。本节内容来自于对佩措尔德教材的大段抄录。一. 本节内容尽管使用备用对象中的画笔非常方便但只能使用实心的黑色画笔、实心的白色画笔或者没有画笔三种情况。如果想要获得更丰富的效果则必须创建自己的画笔。这里是创建画笔的一般过程调用 CreatePen 或者 CreatePenIndirect 函数创建一个 “逻辑画笔”它只是说明你想要得到一个什么样的画笔。这些函数会返回一个逻辑画笔的句柄。然后需要调用 SelectObject 函数将画笔选入设备环境中。接着就可以使用这个新的画笔来绘制线条。一次只能有一支画笔被选入设备环境。释放设备环境之后或者将其他画笔选入设备环境之后需要调用 DeleteObject 函数来删除你创建的逻辑画笔。此后画笔的句柄不再有效。逻辑画笔是一个 “GDI 对象”一个程序可以创建 6 种 GDI 对象它是其中之一。其他五种分别是画刷、位图、区域、字体和调色板。除了调色板之外所有这些对象都通过 SelectObject 函数选入设备环境。下面三条规则控制画笔等 GDI 对象的使用。最终应当删除你所创建的所有 GDI 对象。当 GDI 对象被选入一个有效的设备环境时不要删除它。不要删除备用对象。这些规则都是有道理的。但是有时候有点棘手。下面我们将通过例子来帮助理解这些规则。CreatePen 函数的一般语法如下。hPen CreatePen (iPenStyle, iWidth, crColor);其中参数 iPenStyle 决定画笔绘制的是实线、虚线或者点线。这个参数可以使用定义在 WinGDI.h 头文件中的下列标识符。下面的图也显示了每种样式产生的线条。图1对于 PS_SOLID、PS_NULL 和 PS_INSIDEFRAME 样式参数 iWidth 表示画笔的宽度。当 iWidth 值为 0 时Windows 会把画笔的宽度设定为 1 个像素。这其实是一个很重要的知识点。以后我们还会学习映射模式的知识。在这里我们要求大家先有一个印象无论处于何种映射模式之下当 iWidth 值为 0 时Windows 都会把画笔的宽度设定为 1 个像素。至于何为映射模式我们以后会学习到的。此处我们要求大家有个印象。备用画笔总是一个像素宽。如果指定使用虚线或点线样式同时把画笔宽度设置为大于 1 个像素那么 Windows 会使用实心的画笔来代替。CreatePen 的参数 crColor 是一个 COLORREF 值它用来指定画笔的颜色。对所有的除了 PS_INSIDEFRAME 之外的画笔样式当将画笔选入到设备环境时Windows 将该颜色转换为设备所能表示的最接近的纯色。PS_INSIDEFRAME 画笔样式是唯一能够使用抖动色的画笔样式并且只有当画笔宽度大于 1 时才如此。PS_INSIDEFRAME 画笔样式用于填充区域的函数时有另外一个奇特之处。当使用非 PS_INSIDEFRAME 样式的画笔样式时如果用于绘制轮廓的画笔宽度大于 1 个像素那么画笔的中心会处于边界之上这样画出的轮廓线部分将会在边框之外。但是对于 PS_INSIDEFRAME 画笔样式整个轮廓线都会在边框内。举几个例子。假定我们分别用 PS_SOLID 和 PS_INSIDEFRAME 样式创建两个黑色的 6 像素宽度的画笔并且都去画同样的矩形。那么在 PS_INSIDEFRAME 样式里面所有的 6 像素画笔线条都位于边框之内。而在 PS_SOLID 样式里面有 3 像素的线条像素在边框内另外的 3 像素的线条像素在边框之外。再来假定我们分别用 PS_SOLID 和 PS_INSIDEFRAME 样式创建两个黑色的 7 像素宽度的画笔并且都去画同样的矩形。那么在 PS_INSIDEFRAME 样式里面所有的 7 像素画笔线条都位于边框之内。而在 PS_SOLID 样式里面有 4 像素的线条像素在边框之内另外的 3 像素的线条像素在边框之外。如果用两种样式创建 10 像素宽度的实线来绘制矩形那么在 PS_INSIDEFRAME 样式里面所有的 10 像素画笔线条像素都位于边框之内。而在 PS_SOLID 样式里面有 5 像素的线条像素在边框之内另外的 5 像素的线条像素在边框之外。如果用两种样式创建 11 像素宽度的实线来绘制矩形那么在 PS_INSIDEFRAME 样式里面所有的 11 像素画笔线条像素都位于边框之内。而在 PS_SOLID 样式里面有 6 像素的线条像素在边框之内另外的 5 像素的线条像素在边框之外。如果用两种样式创建 2nn 为大于或等于 1 的整数像素宽度的实线来绘制矩形那么在 PS_INSIDEFRAME 样式里面所有的 2n 像素画笔线条像素都位于边框之内。而在 PS_SOLID 样式里面有 n 像素的线条像素在边框之内另外的 n 像素的线条像素在边框之外。如果用两种样式创建 2n1n 为大于或等于 1 的整数像素宽度的实线来绘制矩形那么在 PS_INSIDEFRAME 样式里面所有的 2n1 像素的画笔线条像素都位于边框之内。而在 PS_SOLID 样式里面有 n1 像素的线条像素在边框之内另外的 n 像素的线条像素在边框之外。我想这么来解释你应该能明白 PS_INSIDEFRAME 样式与非 PS_INSIDEFRAME 样式在绘制矩形椭圆时在绘制外侧边缘的区别了吧。我们接着讲。也可以通过建立一个类型为 LOGPEN逻辑画笔的结构并调用 CreatePenIndirect 函数来建立一个画笔。如果你的程序在初始化时需要创建很多不同的画笔这种方法会很有效。为了使用 CreatePenIndirect 函数首先要定义一个类型为 LOGPEN 的结构体变量。LOGPEN logpen;这个结构有三个字段lopnStyle无符号整型或 UINT表示画笔样式lopnWidth一个 POINT 结构是以逻辑单位表示的画笔宽度还有 lopnColorCOLORREF表示画笔的颜色。Windows 仅使用 lopnWidth 结构中的 x 字段来设置画笔的宽度y 字段会被忽略。可以通过将该结构的地址传递到 CreatePenIndirect 函数来建立画笔。hPen CreatePenIndirect (logpen);注意CreatePen 和 CreatePenIndirect 函数不需要设备环境句柄。在调用 SelectObject 之前这些函数创建的逻辑画笔和设备环境没有任何联系。可以为几种不同的设备例如屏幕和打印机使用相同的逻辑画笔。这里给出创建、选择和删除画笔的一种方法。假定程序使用三种画笔宽度为 1 的黑色画笔、宽度为 3 的红色画笔和黑色的点线画笔。可以首先定义存储这些画笔的句柄的静态变量。static HPEN hPen1, hPen2, hPen3;在处理 WM_CREATE 消息时可以创建这三种画笔。hPen1 CreatePen (PS_SOLID, 1, RGB(0, 0, 0)); hPen2 CreatePen (PS_SOLID, 3, RGB(255, 0, 0)); hPen1 CreatePen (PS_DOT, 0, RGB(0, 0, 0));在处理 WM_PAINT 消息时或者在任何拥有有效的设备环境句柄时可以将其中任何一支画笔选入到设备环境并且使用它来绘制线条。SelectObject (hdc, hPen2); [画线函数] SelectObject (hdc, hPen1); [画线函数]在处理 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 (HPEN) SelectObject (hdc, CreatePen (PS_DASH, 0, RGB(255, 0, 0)));hPen 究竟是什么呢如果这是在获得设备环境后第一次调用 SelectObject 函数hPen 函数就是 BLACK_PEN 的句柄。在这里为何要在 SelectObject 函数调用的左边写上强制类型转换代码 (HPEN) 呢其实道理和 GetStockObject 一样SelectObject 函数的返回值是一个句柄类型 HGDIOBJ 。如果不对 SelectObject 函数的返回值进行强制类型转换那么你说它返回的句柄类型是画笔句柄 HPEN 呢还是画刷句柄 HBRUSH 呢还是位图句柄 HBITMAP 呢在上面的代码块中为了明确地告诉 Windows我们要返回的是一个画笔句柄因此我们需要在 SelectObject 函数的左边加上强制类型转换代码 (HPEN) 。现在可以在同一条语句中选择该画笔到设备环境并且删除自己创建的画笔第二次 SelectObject 调用返回你创建的画笔的句柄。DeleteObject (SelectObject (hdc, hPen));如果有一个画笔的句柄LOGPEN 结构中各个字段成员的值就可以通过调用 GetObject 函数获得。GetObject (hPen, sizeof(LOGPEN), (LPVOID) logpen);如果需要获得当前被选入设备环境的画笔句柄则进行如下调用。hPen GetCurrentObject (hdc, OBJ_PEN);我们将在以后讨论另外一个画笔创建函数ExtCreatePen 。结束语本节内容有点长。好好学吧。专栏导航上一篇第5章[Win32 章节] 使用现有画笔回到目录下一篇第5章[Win32 章节] 填充空隙
返回列表