欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-05 16:55:44
...

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

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;

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

你会感到奇怪,这两个函数画出的图形怎么会相互遮盖呢?或许你猜出了原因了,这两个函数不是单纯地画“边框”,其内部还被白色的背景填充着,让它们可以相互遮挡而不是“透明”的。像前面讲过的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参数描述影线标记的外观。下图显示了六种可用的影线标记风格。

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


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

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

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

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

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

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

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

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