Windows编程 第八回 绘图课(下)

阅读更多

书接上回,我们先来看一个例子吧,我们画了一个矩形和一个圆:

caseWM_PAINT:

HDChDC;

PAINTSTRUCTps;

hDC=BeginPaint(hwnd,&ps);

Rectangle(hDC,50,50,200,200);

Ellipse(hDC,100,100,300,300);

Ellipse(hDC,400,100,600,300);

Rectangle(hDC,350,50,500,200);

EndPaint(hwnd,&ps);

break;

你会感到奇怪,这两个函数画出的图形怎么会相互遮盖呢?或许你猜出了原因了,这两个函数不是单纯地画“边框”,其内部还被白色的背景填充着,让它们可以相互遮挡而不是“透明”的。像前面讲过的Rectangle、Ellipse、RoundRect、Chord、Pie和本回要讲的Polygon、PolyPolygon这些画带边界框的填充图形函数都是这样的。

认识画刷

在Windows中图形是以当前设备描述表选中的画刷来填充的。默认情况下,使用现有的白色画刷,这意味着图形内部将画为白色。Windows预定义了六种现有画刷:WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH和NULL_BRUSH (也叫HOLLOW_BRUSH),大家看名字就应该知道它们代表什么颜色了吧。你可以将任何一种现有画刷选入你的设备描述表中,就和你选择一种画笔一样。

Windows用HBRUSH定义画刷句柄,可以像这样定义一个画刷句柄变量:

HBRUSH hBrush;

你可以通过调用GetStockObject来取得GRAY_BRUSH的句柄:

hBrush = (HBRUSH) GetStockObject (GRAY_BRUSH) ;//这里需要强制类型转换

你可以调用SelectObject将它选进设备描述表:

SelectObject (hdc, hBrush) ;

现在,如果你要用上面的提到的任意一个函数画图,则图形内部将为灰色。

如果您想画一个没有边界框的图形,可以将NULL_PEN选进设备描述表:

SelectObject (hdc,(HBRUSH) GetStockObject (NULL_PEN)) ;
上一回我曾提到过NULL_PEN有啥用?我估计这可能就是它的一个用途吧。

如果您想画出图形的边界框,但不填入内部,则将NULL_BRUSH选进设备内容:

SelectObject (hdc, (HBRUSH) GetStockobject (NULL_BRUSH) ;
大家看到此,应该想出画不互相遮盖的图形了吧:
               case WM_PAINT:
               HDC hDC;
 PAINTSTRUCT ps;
 hDC=BeginPaint(hwnd,&ps);

SelectObject(hDC, (HBRUSH) GetStockObject (NULL_BRUSH) ;

Rectangle(hDC,50,50,200,200);

Ellipse(hDC,100,100,300,300);

Ellipse(hDC,400,100,600,300);

Rectangle(hDC,350,50,500,200);

 EndPaint(hwnd,&ps);
 break;

再认识画刷

我们除了可以使用以上的现有画刷,还可以创建自己的画刷,就如同上回我们创建自己的画笔一样。而且过程也是类似的:

首先创建逻辑画刷,这里Windows为我们提供了几个函数可供使用;

然后使用SelectObject把画刷选进设备描述表

绘图函数绘图;

最后在释放设备描述表(或者在选择了另一种画刷到设备内容中)之后,就可以调用DeleteObject来删除画刷了。

接着我们就来看一下这几个创建画刷的函数吧。

下面是建立逻辑画刷的第一个函数:

hBrush = CreateSolidBrush (crColor) ;

函数中crColor为COLORREF类型,指定画刷颜色。

你还可以使用由水平、垂直或者倾斜的线组成的“影线标记(hatch marks)”来创建画刷,这种风格的画刷对着色条形图的内部和在绘图仪上进行绘图最有用。创建影线画刷的函数为:

hBrush = CreateHatchBrush (iHatchStyle, crColor) ;

iHatchStyle参数描述影线标记的外观。下图显示了六种可用的影线标记风格。


CreateHatchBrush中的crColor参数是影线的色彩。

你还可以使用这个函数创建逻辑画刷:

hBrush = CreateBrushIndirect (&logbrush) ;

变量logbrush是一个类型为LOGBRUSH(“逻辑画刷”)的结构,该结构的三个字段如表5-4所示,lbStyle字段的值确定了Windows如何解释其它两个字段的值:

lbStyle (UINT)

lbColor (COLORREF)

lbHatch (LONG)

BS_SOLID

画刷的色彩

忽略

BS_HOLLOW

忽略

忽略

BS_HATCHED

影线的色彩

影线画刷风格

BS_PATTERN

忽略

位图的句柄

BS_DIBPATTERNPT

忽略

指向DIB的指标

上一回我们用SelectObject将逻辑画笔选进设备描述表,用DeleteObject删除画笔,用GetObject来取得逻辑画笔的信息。对于画刷,同样能使用这三个函数。

一旦你取得到了画刷句柄,就可以使用SelectObject将该画刷选进设备描述表:

SelectObject (hdc, hBrush) ;

然后,你可以使用DeleteObject函数删除所建立的画刷:

DeleteObject (hBrush) ;

但是,不要删除目前选进设备描述表内的画刷。

如果您需要取得画刷的信息,可以调用GetObject:

GetObject (hBrush, sizeof (LOGBRUSH), (LPVOID) &logbrush) ;

其中,logbrush是一个类型为LOGBRUSH的结构。

Polygon函数和多边形填充

我们好像还有两个函数没有讲,趁我还没有忘记,赶紧把它讲完吧。

Polygon函数也是一个画带边界框的填充图形函数,它的调用与Polyline函数相似:

Polygon (hdc, apt, iCount) ;
 

其中,apt参数是POINT结构的一个数组,iCount是点的数目。如果该数组中的最后一个点与第一个点不同,则Windows将会再加一条线,将最后一个点与第一个点连起来(在Polyline函数中,Windows不会这么做)。

PolyPolygon函数如下所示:

PolyPolygon (hdc, apt, aiCounts, iPolyCount) ; 

该函数绘制多个多边形。最后一个参数给出了所画的多边形的个数。对于每个多边形,aiCounts数组给出了多边形的端点数。apt数组具有全部多边形的所有点。除返回值以外,PolyPolygon在功能上与下面的代码相同:

for (i = 0, iAccum = 0 ; i < iPolyCount ; i++)
{
 Polygon (hdc, apt + iAccum, aiCounts[i]) ;
 iAccum += aiCounts[i] ;
}

对于Polygon和PolyPolygon函数,Windows使用定义在设备描述表中的当前画刷来填充这个带边界的区域。至于填充内部的方式,则取决于多边形填充方式,你可以用SetPolyFillMode函数来设定:

SetPolyFillMode (hdc, iMode) ;

默认情况下,多边形填入方式是ALTERNATE,但是您可以将它设定为WINDING。

对于ALTERNATE方式,您可以设想从一个无穷大的封闭区域内部的点画线,只有假想的线穿过了奇数条边界线时,才填充封闭区域,当然若为偶数,则不填充该区域。这就是星的角被填充而中心没被填充的原因。

对于WINDING方式:方法一样,如为奇数,填充该区域;如为偶数则要根据边框线的方向来判断:如果穿过的边框线在不同方向的边框线数目相等,则不填充,如不等,则填充。还是来分析个例子吧,比如要绘制下图,线上的箭头指出了画线的方向。

用这两种方式填充的效果如下图(左侧是ALTERNATE方式,右侧是WINDING方式):

两种方式都会填充三个封闭的L形区域,号码从13。号码为45的两个小内部区域,在ALTERNATE方式下不会被填充。但是,在WINDING方式下,号码为5的区域会被填充,因为从区域内必须穿过两条相同方向的线才能到达图形外部。号码为4的区域不会被填充,因为必须穿过两条方向相反的线。

经过这两节绘图课后,大家应该对Windows中常用的绘图函数有所了解了,发挥你的想象力,去画一些漂亮的图形吧!

你可能感兴趣的:(Windows编程 第八回 绘图课(下))