図形の描画2

長方形の描画

前ページで直線を引く方法を説明しました。
直線が引ければ長方形も描画できるのですが、長方形の描画は専用の関数が用意されています。

Rectangle関数

長方形の描画はRectangle関数を使用します。

BOOL Rectangle(
 HDC hdc,
 int left,
 int top,
 int right,
 int bottom
);
長方形を描画する。
成功した場合は0以外を、失敗した場合は0を返す。

座標の指定方法はRECT構造体と同じです。
lefttopが長方形の左上の座標を、rightbottomが右下の座標を表します。

この関数はLineTo関数などとは異なり現在の座標を使用しません。
描画の起点としても使用しませんし、描画後も現在の座標を更新しません。

このページで紹介する図形描画関数は、図形の内部に「塗り」という処理が行われています。
LineTo関数で同じ形の四角形を描画しても「塗り」は行われません。
「塗り」についてはブラシの項で説明します。

RoundRect関数

RoundRect関数は角丸の長方形を描画できます。

BOOL RoundRect(
 HDC hdc,
 int left,
 int top,
 int right,
 int bottom,
 int width,
 int height
);
角丸長方形を描画する。
成功した場合は0以外を、失敗した場合は0を返す。

widthは角の楕円の幅を、heightは高さを表します。

サンプルコード

ここまでのサンプルコードです。


//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (message)
	{
	case WM_PAINT: //ウィンドウの描画
		hdc = BeginPaint(hWnd, &ps);

		Rectangle(hdc, 10, 10, 210, 60);
		RoundRect(hdc, 10, 70, 210, 120, 10, 10);

		EndPaint(hWnd, &ps);
		break;

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

通常の長方形と角丸の長方形を描画しています。

多角形の描画

Polygon関数

多角形はPolygon関数で描画できます。

BOOL Polygon(
 HDC hdc,
 const POINT *apt,
 int cpt
);
POINT配列aptの各座標を結んだ多角形を描画する。
成功した場合は0以外を、失敗した場合は0を返す。

引数aptPOINT構造体の配列、引数cptは配列aptの要素数です。
配列の要素数は2以上が必要です。

要素数が2の場合は直線が描画されます。
要素数が3以上の時、最後の座標から最初の座標への直線が描画されます。
つまり三角形の描画ならば座標情報は3つで良いということです。

PolyPolygon関数

PolyPolygon関数は多角形を複数同時に描画できます。
使い方はPolyPolyline関数とよく似ています。

BOOL PolyPolygon(
 HDC hdc,
 const POINT *apt,
 const INT *asz,
 int csz
);
多角形を複数描画する。
成功した場合は0以外を、失敗した場合は0を返す。

第二引数aptPOINT構造体の配列です。
第三引数aszは各多角形の頂点の数を格納する配列で、この配列の要素数が描画可能な多角形の数になります。
この配列の各要素の値は2以上が必要です。
第四引数cszは描画する多角形の数です。


//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	POINT points1[] = {
		{60, 10},
		{20, 100},
		{110, 40},
		{10, 40},
		{100, 100}
	};

	POINT points2[] = {
		{60 + 120, 10},
		{10 + 120, 85},
		{110 + 120, 85},
		{60 + 120, 110},
		{10 + 120, 35},
		{110 + 120, 35}
	};
	DWORD vertices[] = {
		3, 3
	};

	switch (message)
	{
	case WM_PAINT: //ウィンドウの描画
		hdc = BeginPaint(hWnd, &ps);

		Polygon(hdc, points1, 5);
		PolyPolygon(hdc, points2, vertices, 2);
		
		EndPaint(hWnd, &ps);
		break;

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);

		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

五個の頂点情報で五芒星を、三個の頂点情報ふたつで六芒星を描画しています。
多角形の描画

円の描画

Ellipse関数

円はEllipse関数で描画できます。

BOOL Ellipse(
 HDC hdc,
 int left,
 int top,
 int right,
 int bottom
);
円を描画する。
成功した場合は0以外を、失敗した場合は0を返す。

この関数の引数はRectangle関数と同じで、長方形の四辺に内接する円を描画します。
正方形を指定すれば正円になります。


//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (message)
	{
	case WM_PAINT: //ウィンドウの描画
		hdc = BeginPaint(hWnd, &ps);

		Rectangle(hdc, 10, 10, 110, 110);
		Ellipse(hdc, 10, 10, 110, 110);

		Rectangle(hdc, 120, 10, 220, 60);
		Ellipse(hdc, 120, 10, 220, 60);

		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

このサンプルコードではEllipse関数と同じ引数でRectangle関数を実行し、長方形も一緒に描画しています。
Ellipse関数だけでは長方形自体は描画されない点に注意してください。
円の描画

扇、円弧、弦の描画

Pie関数、Arc関数、Chord関数

扇型の図形はPie関数で、円弧はArc関数で、弦はChordで描画できます。

BOOL Pie(
 HDC hdc,
 int left,
 int top,
 int right,
 int bottom,
 int xr1,
 int yr1,
 int xr2,
 int yr2
);
扇を描画する。
成功した場合は0以外を、失敗した場合は0を返す。
BOOL Arc(
 HDC hdc,
 int left,
 int top,
 int right,
 int bottom,
 int xr1,
 int yr1,
 int xr2,
 int yr2
);
円弧を描画する。
成功した場合は0以外を、失敗した場合は0を返す。
BOOL Chord(
 HDC hdc,
 int left,
 int top,
 int right,
 int bottom,
 int xr1,
 int yr1,
 int xr2,
 int yr2
);
弦を描画する。
成功した場合は0以外を、失敗した場合は0を返す。

これらの関数は同じ形状の図形を定義するので、引数の意味は三つとも同じです。
扇は円の中心から円周への二本の線と孤を描画します。
円弧は円周の孤のみを描画します。
弦は二本の線が円周に接する点同士を結ぶ線と孤を描画します。

「円の中心から円周への二本の線」の一本目は引数xr1yr1、二本目はxr2yr2で定義します。
一本目から反時計回りに二本目の間が描画されます。
これらの座標は円周上を指定する必要はなく、円周に接する長さに自動で伸縮されます。


//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	POINT points[] = {
		{ 60, 60 },
		{ 40, 130 },
		{ 60, 60 },
		{ 130, 50 }
	};
	DWORD vertices[] = {
		2, 2
	};
	int x, y;

	switch (message)
	{
	case WM_PAINT: //ウィンドウの描画
		hdc = BeginPaint(hWnd, &ps);

		Rectangle(hdc, 10, 10, 110, 110);
		Ellipse(hdc, 10, 10, 110, 110);
		PolyPolyline(hdc, points, vertices, 2);
		TextOut(hdc, points[1].x, points[1].y, L"線1", 2);
		TextOut(hdc, points[3].x, points[3].y, L"線2", 2);

		x = 0;
		y = 170;
		TextOut(hdc, 30, 10 + y, L"Pie", 3);
		Pie(hdc, 10 + x, 10 + y, 110 + x, 110 + y,
			40 + x, 130 + y, 130 + x, 50 + y);

		x = 100;
		y = 170;
		TextOut(hdc, 30 + x, 10 + y, L"Arc", 3);
		Arc(hdc, 10 + x, 10 + y, 110 + x, 110 + y,
			40 + x, 130 + y, 130 + x, 50 + y);

		x = 200;
		y = 170;
		TextOut(hdc, 30 + x, 10 + y, L"Chord", 5);
		Chord(hdc, 10 + x, 10 + y, 110 + x, 110 + y,
			40 + x, 130 + y, 130 + x, 50 + y);

		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

この画像の上の図形は説明用に描画したものです。
反時計回りに、一本目の線と二本目の線の間が描画対象になっていることがわかります。
扇と円弧の描画