オーナードローボタンの作成

ボタンをオーナードローで作成するには、次の手順が必要になる。
  1. リソースエディタでボタンを親ウィンドウに貼りつける。
  2. ボタンのプロパティで「オーナー描画」をチェックする。
  3. CButtonクラスの派生クラスを定義する。
  4. このクラスにDrawItem関数をオーバーライドさせる。
  5. ClassWizardで、ボタンのオブジェクトを作成し、それを派生クラスのオブジェクトに置きかえる。

ここからは実際の描画処理について、下図のようにダイアログと異なる配色を持ったボタンの作成を例として説明する。

ボタンの状態の取得と処理の分岐
オーナードローボタンの描画処理はDrawItem関数内で行うが、 ボタンの場合は上図のようにフォーカスの有無やボタンが押されているかどうかといった状態により異なる描画が必要となる。 そのためには現在描画したいボタンがどんな状態にあるかを取得しなければならない。
DrawItem関数には引数としてDRAWITEMSTRUCT構造体へのポインタが渡されている。この構造体のitemStateメンバに、 現在のボタンコントロールの状態が格納されているので、これを取得すればよい。
	// 現在のボタンコントロールの状態を取得
	UINT nState = lpDrawItemStruct->itemState;
ボタンの状態を取得したら、その状態によって処理を分岐させる必要がある。 ボタンの各状態はフラグとしてnStateに設定されているので、このフラグがONかどうかを調べればよい。 例えばフォーカスがある場合はODS_FOCUSフラグが、 また選択されている(ボタンが押されている)場合はODS_SELECTEDフラグがONになっている。
以下のようにすることでフラグがONかどうかを調べることができる。
	if( nState & ODS_FOCUS ) {
		……  // フォーカスがある場合の処理
	}
ボタンの描画
ボタンコントロールのクライアント領域に描画するため、まず以下の処理が必須となる。
	CRect rect;
	rect = (CRect)(lpDrawItemStruct->rcItem);		// クライアント四角形の取得
	CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);	// デバイスコンテキストの取得
四角形全体を単一色で塗りつぶすにはCDC::FillSolidRect関数が適している。
四角形の淵を立体的に描画するにはCDC::Draw3dRect関数を使う。また、フォーカスはCDC::DrawFocusRect関数を使う。
フォーカスはボタンの四角形全体より小さくする必要があり、また淵の描画の際も、 淵を太くするために四角形全体の大きさより一回り小さい四角形でも描画したい。こういう場合、 四角形の大きさを自由に変更できるCRect::InflateRect関数が便利である。
	// 四角形全体を塗りつぶす
	pDC->FillSolidRect(&rect, RGB(153,204,204));

	// フォーカス四角形の描画
	rect.InflateRect(-4, -4);	// 四角形を上下に4、左右も4縮小する
	if( nState & ODS_FOCUS )
		pDC->DrawFocusRect(&rect);

	// ボタンの淵の描画。選択されているとき(ボタンが押されている)とそうでないときは描画が異なる
	if( nState & ODS_SELECTED ) {
		rect.InflateRect(4, 4);
		pDC->Draw3dRect(&rect, RGB(0,0,0), RGB(0,0,0));
		rect.InflateRect(-1, -1);
		pDC->Draw3dRect(&rect, RGB(153,204,204), RGB(153,204,204));
		rect.InflateRect(-2, -2, 0, 0);  // テキスト描画位置の補正
	}
	else {
		rect.InflateRect(4, 4);
		pDC->Draw3dRect(&rect, RGB(255,255,255), RGB(0,0,0));
		rect.InflateRect(-1, -1);
		pDC->Draw3dRect(&rect, RGB(255,255,255), RGB(0,0,0));
	}
テキストの描画
ボタンにはテキストの表示も必要である。CDC::TextOut関数を使いたいところだが、 これではうまくボタンの中央にテキストを表示させるのが難しい。ここではCDC::DrawText関数が便利である。
なお、フォントの変更については 「コントロールのフォントを変更する」 の項を参照されたい。
	CString str;
	GetWindowText(str);
	pDC->SetBkMode(TRANSPARENT);
	pDC->DrawText(str, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	// --> DT_VCENTERを指定する場合は必ずDT_SINGLELINEも指定すること
オブジェクトの置き換え
オブジェクトの置き換えについては、 オーナードローリストビューの作成を参照すること。

目次へ