尽管使用现有画笔非常方便,但却受限于实心的黑画笔、实心的白画笔,或者没有画笔这三种情况。
如果想得到更丰富多彩的效果,就必须创建自己的画笔。
而这一过程通常是:使用函数CreatePen或CreatePenIndirect创建一个“逻辑画笔”,这仅仅是对画笔的描述。这些函数返回逻辑画笔的句柄;然后调用SelectObject将画笔选进设备描述表。现在就可以使用新的画笔来画线了。在任何时候,都只能有一种画笔选进设备描述表。在释放设备描述表(或在选择了另一种画笔到设备描述表中)之后,就可以调用DeleteObject来删除所创建的逻辑画笔了。在删除后,该画笔的句柄就不再有效了。
逻辑画笔是一种“GDI对象”,它是您可以创建的6种GDI对象之一,其他5种是刷子、位图、区域、字体和调色板。除了调色板之外,这些对象都是通过SelectObjcet选进设备描述表的。
在使用画笔等GDI对象时,应该遵守以下三条规则:
1.最后要删除自己创建的所有GDI对象;
2.当GDI对象正在一个有效的设备描述表中时,还要删除它;
3.不要删除现有对象。
这些规则当然是不无道理的,不过有时还挺微妙的。下面来举些例子
CreateOen函数的语法形如: hPen=CreatePen(iPenStyle,iWidth,crColor);
其中,iPenStyle参数确定画笔是实线、点线还是虚线,该参数可以是WINGDI.H头文件中定义的以下标识符,下图显示了每种线型产生的线类型。
对于PS_SOLD、PS_NULL、PS_INSIDEFRAME线型,iWidth参数是画笔的宽度。iWidth值为0则意味着画笔宽度为一个像素。现有画笔是一个像素宽。如果指定的是点划线或虚线式画笔线型,同时又指定一个大于1的物理宽度,那么Windows将使用实线画笔来代替。
CreatePen的crColor参数是一个COLORREF值,它指定画笔的颜色。对于除了PS_INSIDEFRAME之外的画笔线型,如果将画笔选入设备描述表中,Windows会将颜色转换为设备所能表示的最相近的纯色。PS_INSIDEFRAME是唯一一种可以使用抖动色的画笔线型,并且只有在宽度大于1的情况下才如此。
在与定义一个填充区域的函数一起使用时,PS_INSIDEFRAME线型还有另外一个奇特之处,对于除了PS_INSIDEFRAME以外的所有画笔线型来说,如果用来画边界框的画笔宽度大于1个像素,那么画笔将居中对齐在在边界框线上,这样边界框线的一部分将位于边界框之外;而对于PS_INSIDEFRAME画笔线型来说,整条边界框线都画在边界框之内。
您也可以通过建立一个类型为LOGPEN(“逻辑画笔”)的结构,并调用CreatePenIndirect来创建画笔。如果您的程序使用许多能在源代码中初始化的画笔,那么使用这种方法将有效得多。
要使用CreatePenIndirect,首先定义一个LOGPEN类型的结构:LOGPEN logpen;
此结构有三个成员:lopnStyle(无符号整数或UINT)是画笔线型,lopnWidth(POINT结构)是按逻辑单位度量的画笔宽度,lopnColor(COLORREF)是画笔颜色。Windows只使用lopnWidth结构的x值作为画笔宽度,而忽略y值。
将结构的地址传递给CreatePenIndirect结构就可以创建画笔了: hPen=CreatePenIndirect(&logpen);
注意:CreatePen和CreatePenIndirect函数不需要设备描述表句柄作为参数。这些函数创建与设备描述表没有联系的逻辑画笔。直到调用SelectObjcet之后,画笔才与设备描述表发生联系。因此,可以对不同的设备(如屏幕和打印机)使用相同的逻辑画笔。
下面是创建、选择和删除画笔的一种方法。假设您的程序使用三种画笔:一种宽度为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);{其它代码}
SelectObject(hdc,hPen1);{其它代码}
可以在处理WM_DESTORY期间删除创建的三种画笔:DeleteObject(hPen1);DeleteObject(hPen2);DeleteObject(hPen3);
以上是创建、选择和删除画笔最直接的方法。但是逻辑画笔需要在整个程序运行期间占用存储,为此,您可能想要在每个WM_PAINT消息期间创建画笔,并在调用EndPaint之后删除它们,但要小心不要删除设备描述表中当前选择的画笔。
您可能还希望随时创建画笔,并将CreatePen和SelectObject调用组合到同一个语句中:
SelectObject(hdc,CreatePen(PS_DASH,0,RGB(255,0,0)));
如上的方法如何删除画笔呢?请记住SelectObject将返回设备描述表中上一次选择的画笔句柄。所以可以通过调用SelectObject将BLACK PEN选进设备描述表,并删除从SelectObject返回的值(也可先保存在hPen变量中):
DelectObject(SelectObject(hdc,GetStockObject(BLACK_PEN)));
如果有一个画笔的句柄,就可以通过调用GetObject获取LOGPEN结构各个成员的值:
GetObject(hPen,sizeof(LOGPEN),(LPVOID)&logpen);
如果需要当前选进设备描述表的画笔句柄,可以调用: hPen=GetCurrentObject(hdc,OBJ_PEN);
还有另一个创建画笔的函数ExtCreatePen,以后讨论。