多角形モード


多角形の塗りつぶし

以前、線の描画を説明した時にPolyline()ファンクションなどを説明しまいた
これ以外に、多角形でありかつ内部を塗りつぶすこともできるのです

Polyline()は、連続した線を描画する関数でしたが
閉じた図形の多角形を描画するにはPolygon()関数を使います
このファンクションは、始点と終点を最後に結ぶことで閉じた図形として描画されます
Polyline()と異なり、内部はブラシによって塗りつぶされます

BOOL Polygon(HDC hdc , CONST POINT *lpPoints , int nCount);

基本的にはPolyline()ファンクションと同じです
hdcにはデバイスコンテキストのハンドル、lpPointsには各点を表すPOINT配列へのポインタ
nCountは多角形の頂点の数を指定します

しかし、多角形の場合は多角形塗りつぶしモードと呼ばれる特殊な属性があります
これは、複数の線が重なり交差しあう複雑な多角形で効果を発揮します
多角形塗りつぶしモードを設定するにはSetPolyFillMode()を用います

int SetPolyFillMode(HDC hdc , int iPolyFillMode);

hdcには、デバイスコンテキストのハンドルを指定します
iPolyFillModeは、定数ALTERNATEまたはWINDINGを指定します
戻り値は、以前の塗りつぶしモードが返ります。失敗すれば0が返ります

デフォルトでALTERNATEに設定されていますが、これは多角形の内部で隣接しない部分を塗りつぶします
他の境界線と交差している内面は塗りつぶされません

WINDINGを指定すれば、多角形の交差する内面も通常は塗りつぶされます
しかし交差する線の方向が逆の場合は塗りつぶされません
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;

	static POINT po[8];
	static INT imode;

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		po[0].x = 10;	po[0].y = 50;
		po[1].x = 150;	po[1].y = 50;
		po[2].x = 150;	po[2].y = 150;
		po[3].x = 50;	po[3].y = 150;
		po[4].x = 50;	po[4].y = 10;
		po[5].x = 200;	po[5].y = 10;
		po[6].x = 200;	po[6].y = 125;
		po[7].x = 10;	po[7].y = 125;

		imode = MessageBox(
			NULL , TEXT("多角形モードを変更しますか?") ,
			TEXT("SetPolyFillMode") , MB_YESNO
		);
		if (imode == IDYES) imode = WINDING;
		else imode = ALTERNATE;

		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd , &ps);
		SelectObject(hdc , CreateSolidBrush(0xFF));
		SetPolyFillMode(hdc , imode);
		Polygon(hdc , po , 8);
		EndPaint(hwnd , &ps);
		DeleteObject(SelectObject(hdc , GetStockObject(WHITE_BRUSH)));
		return 0;
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
	return msg.wParam;
}
WINDINGALTERNATE

左がWINDING、右がデフォルトのALTERNATEです
塗りつぶしモードを変えると、このように交差する領域の塗りつぶしが変化します

また、複数の多角形を描画するPolyPolygon()もあります


Polygon()

BOOL Polygon(HDC hdc , CONST POINT *lpPoints , int nCount);

閉じた多角形を描画します

hdc - デバイスコンテキストのハンドルを指定します
lpPoints - 多角形の角頂点の位置を表した配列へのポインタを指定します
nCount - 多角形の頂点の数を指定します

戻り値 - 成功すると0以外、失敗すると0

PolyPolygon()

BOOL PolyPolygon(
	HDC hdc,
	CONST POINT *lpPoints,
	CONST INT *lpPolyCounts,
	int nCount
);
複数の閉じた多角形を描画します

hdc - デバイスコンテキストのハンドルを指定します
lpPoints - 多角形の角頂点の位置を表した配列へのポインタを指定します
lpPolyCounts - 各多角形の頂点の数が入った配列へのポインタを指定します
nCount - 多角形の総数を指定します

戻り値 - 成功すると0以外、失敗すると0

SetPolyFillMode()

int SetPolyFillMode(HDC hdc , int iPolyFillMode);

多角形塗りつぶしモードを設定します

hdc - デバイスコンテキストのハンドルを指定します
iPolyFillMode - 塗りつぶしモードを表す定数を指定します

戻り値 - 以前の塗りつぶしモード、失敗した時は0

塗りつぶしモードは次の定数を指定します

定数解説
ALTERNATE 交互モードを選択します
多角形の各走査行について、多角形の奇数番目の辺から
偶数番目の辺までの間の領域が塗りつぶされます
WINDING 全域モードを選択します
0 以外のワインディング値をもつすべての領域が塗りつぶされます



前のページへ戻る次のページへ