《Windows API每日一练》4.4 绘制填充区域

本节讲述如何填充由线条构建的封闭区域。当我们初始化一个窗口类时,往往已经指定了窗口的背景色画刷(WHITE_BRUSH),即默认的填充封闭区域背景的画刷。如果我们想更换背景颜色,需要选入其他系统预定义的画刷(BLACK_BRUSH、GRAY_BRUSH、NULL_BRUSH)。我们也可以选择创建并选入自定义的画刷。此外,我们还需要关注与填充背景相关的背景模式(透明模式和非透明模式)、填充模式(ALTERNATE模式和WINDING模式)和绘图模式。

本节必须掌握的知识点:

        多边形填充模式

        第26练:绘制填充区域

        画刷

4.4.1 多边形填充模式

Windows使用当前被选入设备环境的画笔来绘制图形的边框线。边框线使用当前的背 景模式、背景颜色和绘图模式,这与Windows绘制线条一样。我们所学的关于线条的所有 知识都适用于这些图形的边框线。下表列出了 Windows用于绘制带有边框的填充区域的7个函数。

函数名称

图形

Rectangle

直角矩形

Ellipse

椭圆

RoundRect

圆角矩形

Chord

弓形,由椭圆圆周上的弧和一根弦组成

Pie

椭圆上的一个扇形

Polygon

多边形

PolyPolygon

多个多边形

表4-2 带有边框的填充区域函数

Windows使用当前选入设备环境的画刷来填充图形。在默认情况下,使用的是备用对象WHITE_BRUSH,这就意味着使用白色来绘制图形内部。

Windows定义了 6种备用画刷: WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH 和NULL_BRUSH(又称为HOLLOW_BRUSH)。和选择备用画笔一样,可以将任何一种备用画刷选入设备环境。Windows定义画刷的句柄为HBRUSH类型,所以要先定义一个画 刷句柄变量:

HBRUSH hBrush;

获取GRAY_BRUSH句柄可以通过调用如下的GetStockObject函数实现:

hBrush = GetStockObject (GRAY_BRUSH);

然后通过调用SelectObject函数将它选进设备环境:

SelectObject (hdc, hBrush);

现在,当绘制上表中的任意图形时,内部都会变成灰色。

如果要绘制一个不含边框线的图形,则要把NULL_PEN画笔选入设备环境:

SelectObject (hdc, GetStockObject (NULL_PEN));

如果只想绘制图形的边框线,而不想填充图形的内部,可以将NULL_BRUSH选入设备环境:

SelectObject (hdc, GetStockobject (NULL_BRUSH);

也可以建立自定义的画刷,就像建立自定义的画笔一样。我们将在下一小节中介绍。

Polygon函数和多边形填充模式

Polygon函数用于绘制一个多边形形状。以下是Polygon函数的常见原型:

BOOL Polygon(

    HDC hdc,             // 设备上下文句柄

    const POINT* points,   // 多边形的顶点数组指针

    int count            // 顶点的数量

);

Polygon函数用于在设备上下文中绘制一个多边形形状。多边形由一系列顶点构成,通过指定顶点的坐标数组来定义。多边形的绘制遵循顺时针顺序连接顶点的规则。

举例

以下是一个示例代码,演示如何使用Polygon函数绘制一个三角形:

HDC hdc = GetDC(hwnd);  // 获取窗口的设备上下文

POINT points[3];  // 三角形的顶点数组

points[0].x = 100; points[0].y = 100;  // 第一个顶点

points[1].x = 200; points[1].y = 200;  // 第二个顶点

points[2].x = 300; points[2].y = 100;  // 第三个顶点

Polygon(hdc, points, 3);  // 绘制三角形

ReleaseDC(hwnd, hdc);  // 释放设备上下文

上述代码中,我们创建了一个包含三个顶点的POINT数组,并将顶点的坐标赋值。然后调用Polygon函数传递顶点数组和顶点数量来绘制三角形。

需要注意的是,绘制的多边形将使用当前设备上下文的绘图属性,如线条颜色、填充模式等。

PolyPolygon函数的调用形式如下:

PolyPolygon (hdc, apt, aiCounCs, iPolyCounC);

这个函数会绘制多个多边形。最后一个参数是绘制的多边形的个数。对每个多边形,数组 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(螺旋)。这两种方式的区别如图4-6所示。

●ALTERNATE和WINDING模式的区别

“ALTERNATE” 和 “WINDING”是用来处理复杂路径(即,路径中有交叉或重叠部分)的填充规则,本质上是决定哪些区域是需要被填充,哪些区域是应该被排除的。

1.ALTERNATE:也称为奇偶规则。该规则通过画直线从需要考虑填充的区域到区域外部,如果这个线穿过路径的交叉点次数是奇数,则算作在路径内部,该区域会被填充,如果是偶数,则不会被填充。

2.WINDING:也称为非零环绕数规则。按照这个规则,所有的路径都是有方向的。从一个区域向外画射线,路径从左到右穿过射线会加一,从右到左穿过射线会减一,如果最终的结果是非零,那么这个区域视为在路径内部,会被填充。如果结果是零,那么这个区域不会被填充。

图4-6用两种多边形填充模式绘制的图:ALTERNATE(左)和WINDING(右)

4.4.2 第26练:绘制填充区域

/*------------------------------------------------------------------

026  WIN32 API 每日一练

     第26个例子ALTWIND.C:绘制填充区域

     SetPolyFillMode函数

     Polygon函数

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName[] = TEXT ("AltWind.C") ;

    (略)

     return msg.wParam ;

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

     static POINT apt[10];

     //多边形顶点坐标数组

     static POINT aptFigure[10] = { {10,70}, 50,70, 50,10, 90,10, 90,50,

      30,50, 30,90, 70,90, 70,30, 10,30 };

     static int cxClient,cyClient;

     HDC hdc ;

     PAINTSTRUCT ps

     switch (message)

     {

     case WM_SIZE:

          cxClient = LOWORD(lParam);

          cyClient = HIWORD(lParam);

          return 0 ;

     case WM_PAINT :

          hdc = BeginPaint(hwnd,&ps);

          SelectObject(hdc,GetStockObject(GRAY_BRUSH));

          //设置顶点坐标---左图

          for (int i = 0;i < 10;i++)

          {

               apt[i].x = cxClient *aptFigure[i].x/200;

               apt[i].y = cyClient *aptFigure[i].y/200;

          }

          //设置ALTERNATE填充模式

          //选择交替模式(填充每条扫描线上奇数和偶数多边形边之间的区域)

          SetPolyFillMode(hdc,ALTERNATE);

          Polygon(hdc,apt,10);//绘制多边形

          //重置顶点坐标---左图

          for (int i = 0;i < 10;i++)

          {

               apt[i].x += cxClient/2;

          }

          //设置WINDING填充模式

          //选择缠绕模式(用非零缠绕值填充任何区域)

          SetPolyFillMode(hdc,WINDING);

          Polygon(hdc,apt,10);//绘制多边形

          EndPaint(hwnd,&ps);

          return 0;

     case WM_DESTROY:

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd, message, wParam, lParam);

}

/******************************************************************************

SetPolyFillMode函数:设置填补多边形多边形填充模式。

int SetPolyFillMode(

  HDC hdc,

  int mode     //ALTERNATE:选择替代模式,只有该射线穿越奇数条边框线时,封闭区域才会被填充。

               //WINDING:选择绕线模式,穿过奇数条边框线或相同方向偶数条边时封闭区域才会被填充。

);

*******************************************************************************

Polygon函数:

绘制由以直线连接两个或更多个顶点的多边形。

使用当前的笔勾勒出多边形的轮廓,并使用当前的笔刷和多边形填充模式填充多边形。

BOOL Polygon(

  HDC         hdc,

  const POINT *apt, //指向POINT结构数组的指针,该数组以逻辑坐标形式指定多边形的顶点。

  int         cpt   //数组中的顶点数。该值必须大于或等于2。

);

*/

运行结果:

图4-7 填充模式

       总结

       上述实例非常简单,窗口过程中处理WM_PAINT消息时,先调用SelectObject函数选入一个灰色背景画刷,然后使用一个for循环语句初始化一个多边形顶点坐标数组,接着调用SetPolyFillMode函数和SetPolyFillMode函数设置填充模式并绘制多边形。

4.4.3 画刷

       在4.3节中我们讲述了如何创建新的自定义画笔。同样的道理,我们也可以创建新的自定义画刷。

Windows允许使用5种函数来建立逻辑画刷。调用SelectObject函数将画刷选入设备 环境。逻辑画刷也是GDI对象,这和逻辑画笔一样。所以所有你建立的画刷都必须最终被删除,但是如果它当前被选入了设备环境中,则不要删除它。

建立逻辑画刷的第一个函数

hBrush = CreateSolidBrush (crColor);

这个函数中的Solid(中文含义为实心)并不意味着画刷为纯色。将该画刷选入设备环境后, Windows可能会建立一个抖动位图,并且使用它作为画刷。

建立逻辑画刷的第二个函数

可以使用由水平、垂直或者对角线组成的“阴影线标记”(hatchmark)来建立一个画刷。这种样式的画刷对着色条形图的内部和在绘图机上绘图最常用。建立阴影线画刷的函数如下:

hBrush = CreateHatchBrush (iHatchSCyle, crColor);

参数iHatchStyle表示阴影线标记的外观。图4-8显示了 6种可用的明影线样式及其外观。

                                          图4-8 6种阴影线固刷样式

                           

CreateHatchBrush函数中的参数crClolor表示阴影线的颜色。把画刷选入设备环境后, Windows把这种颜色转换为显示器上可用的最近的纯色。阴影线之间的区域会使用设备环 境中定义的背景模式和背景颜色来着色。如果背景模式是OPAQUE,则背景颜色(也被转换 为纯色)用来填充线与线之间的空隙。如果背景的模式是TRANSPARENT,则Windows只画出阴影线,不填充它们之间的空隙。

建立逻辑画刷的第三和第四个函数

可以通过函数CreatePatternBrush和CreateDIBPatternBrushPt来建立自己的位图画刷。我们将在第十四章位图详细讲解。

建立逻辑画刷的第五个函数

建立逻辑画刷的第5个函数包含其他4个函数的所有功能:

hBrush = CreateBrushlndirect (&logbrush);

变量logbrush是一个类型为LOGBRUSH( “逻辑画刷”)的结构。这个结构有三个字段,lbStyle字段的值决定着Windows如何解释其他的两个字段。

LOGBRUSH结构体(三个字段,lbStyle 字段的值决定Windows如何解释其他两个字段)

lbStyle(UINT)

lbColor(COLORREF)

lbHatch(LONG)

BS_SOLID

画刷的颜色

被忽略

BS_HOLLOW

被忽略

被忽略

BS_HATCHED

阴影线的颜色

阴影线画刷的样式

BS_PATTERN

被忽略

位图的句柄

BS_DIBPATTERNPT

被忽略

指向DIB的指针

选入画刷和删除画刷

画刷作为GDI对象,同样必须遵循GDI对象三原则。在前面我们调用SelectObject函数将逻辑画笔选入设备环境,调用DeleteObject函数来 删除这个逻辑画笔,调用GetObject函数来获取逻辑画笔的信息。对于画刷,同样可以使用 这三个函数。一旦拥有一个画刷句柄,就可以调用SelectObject函数将其选入设备环境:

SelectObject (hdc, hBrush);

然后,调用DeleteObject函数删除已建立的画刷:

DeleteObject (hBrush);

但是不要删除当前被选入设备环境的画刷。

如果需要获取画刷的信息,可以调用GetObject函数:

GetObject (hBrush, sizeof (logbrush), (LPVOID) slogbrush);

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

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值