「Windows API/図形の描画」の版間の差分

出典: フリー教科書『ウィキブックス(Wikibooks)』
削除された内容 追加された内容
編集の要約なし
20 行 20 行
当然、これらの命令は、WM_PAINT ケースにある
当然、これらの命令は、WM_PAINT ケースにある
「// TODO: HDC を使用する描画コードをここに追加してください...」
「// TODO: HDC を使用する描画コードをここに追加してください...」
下のブロックで書く必要があります。
あるブロックで書く必要があります。




つまり、下記のコードのようになります。
<source lang=c>
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: HDC を使用する描画コードをここに追加してください...


HBRUSH brasi_buhin_1;
brasi_buhin_1 = CreateSolidBrush(RGB(255, 100, 100)); // ピンク色のブラシを作成
SelectObject(hdc, brasi_buhin_1); // ウィンドウhdcと、さきほど作成したブラシを関連づけ
Rectangle(hdc, 20, 30, 50, 70); // 図形の描画


EndPaint(hWnd, &ps);
上記コードを実際に描画すると、四角形の輪郭が黒色で描画されます。これは、ペンの設定が黒色になってるからです。
}
break;
</source>


さて、上記コードを実際に描画すると、四角形の輪郭が黒色で描画されます。これは、ペンの設定が黒色になってるからです。


図形をピンク色の長方形だけにしたい場合、ペンの色もピンク色にします。
図形をピンク色の長方形だけにしたい場合、ペンの色もピンク色にします。

2019年9月8日 (日) 22:26時点における版

図形を塗りつぶすには?

図形を塗りつぶしたい場合には、図形描画命令の直前に、下記のように描画のモードをブラシに設定します。

塗りつぶし専用の命令は、無いのです。

Windows API でいう「ブラシ」とは、図形の塗りつぶしの色を設定するためのツールのことです。画像作成ソフトで例えるなら、Windows API でいうブラシとは、画像作成ソフトの「バケツ」ツールに近いです。世間一般の画材でいう「ブラシ」とは、意味が違います。

			HBRUSH brasi_buhin_1;
			brasi_buhin_1 = CreateSolidBrush(RGB(255, 100, 100)); // ピンク色のブラシを作成
			SelectObject(hdc, brasi_buhin_1); // ウィンドウhdcと、さきほど作成したブラシを関連づけ
			Rectangle(hdc, 20, 30, 50, 70); // 図形の描画

上記の2段階のブラシ作成の作業は、CreateSolidBrush はブラシの色作成のためのアドレス確保を意味し、もう片方 SelectObject は、どのウィンドウでどのブラシ色を使うかを定義するための情報を保存するアドレスの確保を意味しています。

「Rectangle」は、単に、四角形を描くための命令です。これが塗りつぶしか、それとも輪郭線だけをペンで描くのかは、このRectangle命令だけでは指定できず、この命令が来る前の設定に依存します。


当然、これらの命令は、WM_PAINT ケースにある

「// TODO: HDC を使用する描画コードをここに追加してください...」

のあるブロックで書く必要があります。


つまり、下記のコードのようになります。

case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: HDC を使用する描画コードをここに追加してください...

			HBRUSH brasi_buhin_1;
			brasi_buhin_1 = CreateSolidBrush(RGB(255, 100, 100)); // ピンク色のブラシを作成
			SelectObject(hdc, brasi_buhin_1); // ウィンドウhdcと、さきほど作成したブラシを関連づけ
			Rectangle(hdc, 20, 30, 50, 70); // 図形の描画

            EndPaint(hWnd, &ps);
        }
        break;


さて、上記コードを実際に描画すると、四角形の輪郭が黒色で描画されます。これは、ペンの設定が黒色になってるからです。

図形をピンク色の長方形だけにしたい場合、ペンの色もピンク色にします。

Rectangle 命令の前に、あらかじめ

			HPEN pen_buhin_1;
			pen_buhin_1 = CreatePen (PS_SOLID, 0, RGB(255, 100, 100));
			SelectObject(hdc, pen_buhin_1);

のように、ペンを指定します。 CreatePen 命令の第2引数の「0」は、ペン幅の追加の線幅です。「0」に指定しても、最低でも1ドットぶんの線幅はあります。

よって、今までの話をまとめると、

			HPEN pen_buhin_1; // ペンの設定用
			pen_buhin_1 = CreatePen (PS_SOLID, 0, RGB(255, 100, 100));
			SelectObject(hdc, pen_buhin_1);

			HBRUSH brasi_buhin_1; // ブラシの設定用
			brasi_buhin_1 = CreateSolidBrush(RGB(255, 100, 100));
			SelectObject(hdc, brasi_buhin_1);

			Rectangle(hdc, 20, 30, 50, 70); // 図形の描画

のように、なります。

複数個の描画を関数にしたい場合は

ソースの冒頭で関数を宣言する際、通常の関数と同じように、

void kansuu(HDC hdc){
    // ここに描画命令を書く
}

のように宣言する必要があります。引数の型と変数名が、単にハンドル型(HDC)とハンドル変数(hdc)になっただけです。通常のC言語の関数と同じです。


また、呼び出し側(親側)で、

kansuu(hdc);

のように、hdcの値を渡す必要があります(通常のC言語の関数と同じです)。

もし、上述の引数定義の手間を面倒くさがって、hdc の定義を static に変更すると、コードの他の部分の動作結果がバグります。なので、hdc は static に変更せず、ウィザードの初期設定のままにしておいてください。


当然、呼び出し側(親側)の関数のコードのある位置は、

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: HDC を使用する描画コードをここに追加してください...

// TODO: HDC を使用する描画コードをここに追加してください...

より下の部分です。


つまり、

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: HDC を使用する描画コードをここに追加してください...

            (中略)
            kansuu(hdc);
            (中略)

のように書かれます。

For文による代用

WindowsAPIで関数を使う場合、関数の内容を記述する場所が、呼び出し元の場所から、大きく離れた場所に記述しなければならない場合があります。

このような場合、いっそ関数をつかわずに、For文で記述するという方法もあります。

WindowsAPI でも、標準C言語と同様にFor文を使えます。

For文の繰り返しの数(たとえば for (int j = 1; j <= 20; ++j) の20の部分)を十分に大きな自然数にしておいて、使い終わったら break でそのブロックを脱出すればいいだけです。

たとえば、5種類の違う作業の前に、共通する前段階の作業を5回呼び出したい場合、

for (int j = 1; j <= 20; ++j) {

	ここに共通する前段階の作業を記述 ;

	if (j == 1) { 1回目にしたい処理内容 ; }
	if (j == 2) { 2回目にしたい処理内容 ; }
	if (j == 3) { 3回目にしたい処理内容 ; }
	if (j == 4) { 4回目にしたい処理内容 ; }
	if (j == 5) { 5回目にしたい処理内容 ; 
					 break;}
}

のように書くのです。

このFor文による代用の方法は、有限の回数しか呼び出しをしない処理にしか使えません。何度使うのか不特定な場合や、ずっとループ的に処理させたい場合には、むいてない方法です。

しかし、有限の回数しか呼び出さない処理ならば、この方法でも充分なのです。


また、もし関数を使う場合でも、For文で書いた処理を関数に置き換えるのはラクです。なので、関数を作る前に、とりあえず、For文で試しに似たような処理を書くという方法もあります。