ブラシ

四角形や円などは線で閉じられた「内側」の領域を持っています。
これらの図形は、線で外形を描画すると同時に内側は塗りつぶされています。
この塗りつぶすためのオブジェクトをブラシ(刷毛、はけ)といいます。

ブラシで内側が塗りつぶされるのはRectangle関数、RoundRect関数、Polygon関数、PolyPolygon関数、Ellipse関数、Pie関数、Chord関数などです。
(→図形の描画2)
LineTo関数などの線描画関数で三角形などを描画しても塗りつぶしは行われません。

ストックオブジェクト

ペン同様、ブラシにもストックオブジェクトが用意されています。
(→GetStockObject関数)

定数 説明
WHITE_BRUSH 白色のブラシ
LTGRAY_BRUSH 明るい灰色のブラシ
GRAY_BRUSH 灰色のブラシ
DKGRAY_BRUSH 暗い灰色のブラシ
BLACK_BRUSH 黒色のブラシ
NULL_BRUSH 透明ブラシ
(何も描画しない)
HOLLOW_BRUSH NULL_BRUSHと同じ
DC_BRUSH 色を変更可能なブラシ

色の種類が少し増えましたが、使い方はペンの時と同じです。
初期状態ではWHITE_BRUSHが設定されています。

SetDCBrushColor関数

DC_BRUSHSetDCBrushColor関数で任意の色に変更できます。

COLORREF SetDCBrushColor(
 HDC hdc,
 COLORREF color
);
DC_BRUSHの色を設定する。
戻り値は設定した色。
失敗した場合はCLR_INVALIDを返す。

COLORREF型に関しては→文字色と背景色を参照してください。

GetDCBrushColor関数

ペンと同様、現在のブラシの色を取得するGetDCBrushColor関数もあります。

COLORREF GetDCBrushColor(
 HDC hdc,
);
DC_BRUSHの色を取得する。

サンプルコード


//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	
	switch (message)
	{
	case WM_PAINT: //ウィンドウの描画
		hdc = BeginPaint(hWnd, &ps);

		//明るい灰色ブラシ
		SelectObject(hdc, GetStockObject(LTGRAY_BRUSH));
		Rectangle(hdc, 10, 10, 110, 60);

		//透明ペン、明るい灰色ブラシ
		SelectObject(hdc, GetStockObject(NULL_PEN));
		Rectangle(hdc, 10, 70, 110, 120);

		//黒ペン、白ブラシ(初期状態)
		SelectObject(hdc, GetStockObject(BLACK_PEN));
		SelectObject(hdc, GetStockObject(WHITE_BRUSH));
		MoveToEx(hdc, 5, 155, NULL);
		LineTo(hdc, 115, 155);
		Rectangle(hdc, 10, 130, 110, 180);
		
		//黒ペン、透明ブラシ
		SelectObject(hdc, GetStockObject(NULL_BRUSH));
		MoveToEx(hdc, 5, 215, NULL);
		LineTo(hdc, 115, 215);
		Rectangle(hdc, 10, 190, 110, 240);

		EndPaint(hWnd, &ps);
		break;

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

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

このコードの実行結果です。
ストックオブジェクトによるブラシの描画

最初の四角形は灰色のブラシで描画しています。

二番目の四角形は透明ペンを設定しています。
透明ペンは描画されないので、輪郭線のない四角形が描画されます。

三番目はペンとブラシを初期設定に戻し、横線を引いた上に四角形を描画しています。
線は上書きされ、途切れてしまっています。

四番目は三番目と同じ手順で描画していますが、ブラシを透明ブラシにしています。
内側は塗りつぶされないため、線は上書きされません。

ブラシの作成

ペン同様、ブラシも自分で作成することができます。
ブラシは単色での塗りつぶしのほか、模様や画像などで塗りつぶすこともできます。
そのための関数もいくつか用意されています。
ここでは単色と模様を使用した塗りつぶしを紹介します。

なお、作成したブラシは不要になったらDeleteObject関数で破棄する必要があります。

CreateSolidBrush関数

CreateSolidBrush関数は単色のブラシを作成します。

HBRUSH CreateSolidBrush(
 COLORREF color
);
color色の単色の論理ブラシを作成する。

この関数は難しいことはないでしょう。
戻り値はHBRUSH型です。

CreateHatchBrush関数

CreateHatchBrush関数はハッチ模様のブラシを作成します。

HBRUSH CreateHatchBrush(
 int iHatch,
 COLORREF color
);
color色のハッチ模様の論理ブラシを作成する。

ハッチ模様とは平行な線で面を埋めた模様です。
第一引数iHatchは以下の定数を指定します。

定数 説明
HS_HORIZONTAL 水平
HS_VERTICAL 垂直
HS_FDIAGONAL 右下がり
HS_BDIAGONAL 右上がり
HS_CROSS 水平交差
HS_DIAGCROSS 斜め交差

第二引数colorは平行線の色です。
線と線の間はデバイスコンテキストの背景色で塗りつぶされます。
背景色を変更するにはSetBkColor関数を、背景色を透明にするにはSetBkMode関数を使用します。
(→背景色の変更)


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

	HBRUSH brush;
	HGDIOBJ hgdi;

	int x, y;

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

		x = y = 10;
		//水平
		brush = CreateHatchBrush(HS_HORIZONTAL, RGB(255, 0, 0));
		hgdi = SelectObject(hdc, brush);
		Rectangle(hdc, x, y, x + 60, y + 60);
		SelectObject(hdc, hgdi);
		DeleteObject(brush);

		x = y += 30;
		//垂直
		brush = CreateHatchBrush(HS_VERTICAL, RGB(0, 255, 0));
		hgdi = SelectObject(hdc, brush);
		Rectangle(hdc, x, y, x + 60, y + 60);
		SelectObject(hdc, hgdi);
		DeleteObject(brush);

		x = y += 30;
		//右下がり
		brush = CreateHatchBrush(HS_FDIAGONAL, RGB(0, 0, 255));
		hgdi = SelectObject(hdc, brush);
		Rectangle(hdc, x, y, x + 60, y + 60);
		SelectObject(hdc, hgdi);
		DeleteObject(brush);

		//ここから背景色を透明に変更
		SetBkMode(hdc, TRANSPARENT);

		x = y += 30;
		//右上がり
		brush = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));
		hgdi = SelectObject(hdc, brush);
		Rectangle(hdc, x, y, x + 60, y + 60);
		SelectObject(hdc, hgdi);
		DeleteObject(brush);

		x = y += 30;
		//水平交差
		brush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 255));
		hgdi = SelectObject(hdc, brush);
		Rectangle(hdc, x, y, x + 60, y + 60);
		SelectObject(hdc, hgdi);
		DeleteObject(brush);

		x = y += 30;
		//斜め交差
		brush = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 255));
		hgdi = SelectObject(hdc, brush);
		Rectangle(hdc, x, y, x + 60, y + 60);
		SelectObject(hdc, hgdi);
		DeleteObject(brush);

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

上で説明した順番でブラシを作成し四角形を描画するサンプルコードです。
後半の三つは背景色を透明にしています。
ブラシの作成

多角形の塗りつぶしモード

Polygon関数やPolyPolygon関数は多角形を描画しますが、初期設定では重なり合った面の塗りつぶしは行われません。
重なり合った面も塗りつぶしたい場合はSetPolyFillMode関数で多角形の塗りつぶしモードを変更します。

int SetPolyFillMode(
 HDC hdc,
 int mode
);
多角形塗りつぶしモードを変更する。
戻り値は変更前の塗りつぶしモード。
失敗した場合は0を返す。

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

定数 説明
ALTERNATE 交互モード。
(重なり合った面は塗りつぶさない)
WINDING 全域モード。
(重なり合った面も塗りつぶす)

初期状態ではALTERNATEが選択されています。


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

	HBRUSH brush;

	POINT points1[] = {
		{10, 30},
		{110, 30},
		{110, 90},
		{10, 90},
		{60, 10},
		{90, 120},
		{30, 120}
	};
	POINT points2[] = {
		{10 + 110, 30},
		{110 + 110, 30},
		{110 + 110, 90},
		{10 + 110, 90},
		{60 + 110, 10},
		{90 + 110, 120},
		{30 + 110, 120}
	};
	DWORD vertices[] = {
		4, 3
	};

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

		brush = CreateSolidBrush(RGB(255, 0, 0));
		SelectObject(hdc, brush);

		PolyPolygon(hdc, points1, vertices, 2);

		//全域モードに切り替える
		SetPolyFillMode(hdc, WINDING);
		PolyPolygon(hdc, points2, vertices, 2);

		EndPaint(hWnd, &ps);
		DeleteObject(brush);
		break;

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

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

左がALTERNATEモード、右がWINDINGモードです。
多多角形の塗りつぶしモード