我们在《GDI中矩形区域(含圆角矩形区域)的三种创建方法》中讲解了矩形区域的创建。在《GDI中椭圆区域的创建方法详细说明》中详细说明了椭圆区域的创建方法。在《GDI中多边形区域的创建讲解和代码实现》中详细说明了多边形区域的创建。
最后一个就是多个多边形区域的创建了。创建函数为:
CreatePolyPolygonRgn 创建一系列多边形组成的区域
CreatePolyPolygonRgn函数声明如下:
HRGN CreatePolyPolygonRgn(
CONST POINT *lppt, // 顶点数组
CONST INT *lpPolyCounts, // 多个多边形的顶点个数数组
int nCount, // 多边形的个数
int fnPolyFillMode // 填充模式);
这个函数的参数是比较绕的,所以在此多说几句。第一个参数是多个多边形的所有顶点坐标的数组。将每一个多边形的所有顶点坐标依次填写在数组中。多边形要填写的顶点坐标数,由第二个参数的数组对应的元素值确定。
第二个参数为一个整数数组,这个数组的值依次对应着第一个参数的多个多边形的顶点个数。比如第二个参数传入下面这个数组名称:
static int pc[]={4,4};
那么pc[0]的值即4,表示第一个多边形有四个顶点。pc[1]表示第二个多边形有4个顶点。依次类推。那么第一个参数的数组中应该是8个坐标值,即16个整数。也就是说,函数会根据第二个参数数组中元素值来确定对应的多边形的顶点个数。如果第二个参数数组元素值为4,即表示多边形只需要给出4个顶点即可。此时如果没有形成闭合的区域,函数会自动闭合。如果你想自己闭合多边形,就在第一个参数数组中写5个坐标点来闭合矩形,那么一定要在第二个参数数组对应的元素值填成5。
第三个参数就是指定一共有多少个多边形。第四个参数为填充多个多边形的方式。和多边形的填充方式的意义一样。
函数会根据第三个参数得到多边形的个数,然后根据第二个参数数组来确定每一个多边形的顶点数,得到了每一个顶点的数目就可以在第一个参数给定的所有顶点的数组中切割出多边形的几个顶点,在用这些顶点值来绘制多边形。如果得到的顶点不是闭合的,就会自动闭合。
多个多边形的绘制,就是分这么几步:确定多边形个数->确定每一个多边形顶点数->从第一个参数数组中切割多边形的顶点坐标->用得到的多边形顶点坐标绘制多边形,如果没有闭合就自动闭合。
那么最终的区域就是由多个多边形组合得到的。如何组合,就是最后一个参数来确定的。因为多个多边形可能会重叠,重叠的部分需要处理。如果没有重叠,那么最后一个参数没有什么用。这两种方式比较难以理解,将会用单独的文章来分析。
下面是用两个矩形实现的多个多边形区域的效果图,采用的是ALTERNATE填充方式。
【采用ALTERNATE填充方式创建的多个多边形区域效果】
下面是完整的代码:#include "windows.h"
#include <tchar.h>
TCHAR txt[100]=_T("C++技术网http://www.cjjjs.com");
// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static POINT pt[]={10,20,80,20,80,55,10,55,50,10,110,10,110,40,50,40,50,10};
static int pc[]={4,4};
switch (message)
{
case WM_PAINT:
{
hdc = BeginPaint(hwnd,&ps);
HRGN hEllipRgn = CreatePolyPolygonRgn(pt,pc,2,ALTERNATE);
FillRgn(hdc,hEllipRgn,(HBRUSH)GetStockObject(LTGRAY_BRUSH));
EndPaint(hwnd,&ps);
DeleteObject(hEllipRgn);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;//跳出到默认处理
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
if(!RegisterClass(&wndClass))return 0;
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,10,100,550,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}