FAQ4-4

Q. キャプションバーの色を取得し,SetBkColor() 関数にセットする方法は

 眞柄@舞鶴高専と申します.
 トラ技コンピュータ1995年6月号の「256色ビットマップを表示するには」に関して,便乗質問させてください.現在,キャプションバーに張り付くディジタル時計を制作中です.
 GetSysColor(COLOR_CAPTIONTEXT)の値を,SetTextColor() 関数の引数に,GetSysColor(COLOR_ACTIVECAPTION) の値を,SetBkColor() 関数の引数に使用しておりますが,SetBkColor() の設定値が,キャプションバーの色と一致しません.6月号を読んで,SDKヘルプを調べた結果,リスト4-5と変更しましたが,だめでした.
 キャプションバーの色(パレット値)を取得し,SetBkColor() 関数に正確にセットする方法がわかりません.
 解決方法を御教授くださいますよう,よろしくお願いいたします.参考までに,ウィンドウ背景色は,
 SetClassWord( hwnd, GCW_HBRBACKGROUND,CreateSolidBrush(rAb) );
にて,キャプションバーと一致するようになりました.


[リスト4-5] :

rAb = GetSysColor(COLOR_ACTIVECAPTION);
 ...
SetBkColor(hdc, PALETTERGB( GetRValue(rAb), GetGValue(rAb), GetBValue(rAb) ) );

A. 背景モードを透明にする

 この問題は,おそらくパレットとは関係ありません.
 Windows95を除いて,16色や256色可変パレットの環境の場合,キャプションの色はシステムカラー16色(もしくは20色)しか使っていないからです.
 SetBkColor( hdc, rAb );
で設定したテキストの背景色と,
 SetClassWord( hwnd, GCW_HBRBACKGROUND, CreateSolidBrush(rAb) );
で設定したウィンドウ背景色が違って見えるのは,描画方法が違うためです.
 ウィンドウの背景色は,WM_ERASEBKGNDメッセージをDefWindowProc()に処理させた場合,多分Windowsはクラススタイルの背景ブラシを使ってFillRect()やPatBlt()で背景を描画していると思われます.
 CreateSolidBrush()で作ったブラシをFillRect()やPatBlt()で描画する場合,WindowsはRGB値にもっとも近い色に見せるために,システムカラー16色を組み合わせて色を作って描画してくれます.これをディザカラーといいます.
 かわって,TextOut()や,DrawText()などのテキスト描画関数では,SetBkColor()で設定した背景色を使いますが,このときはなぜかシステムカラー16色(または20色)にもっとも近い色しか使ってくれません(組み合わせではなく,純色のみ).
 ということで,ウィンドウの背景色とテキストの背景色が違って見えるのは,おそらくウィンドウの背景色(=キャプションの背景色)がディザカラーになっているためだと思います.
 ディザカラーは,ある二つの色のちょうど中間色にあると,1ピクセルごとに交互に色を埋めていくので,遠くから見た場合,純色と区別がつかない場合があります.きっとそんな状況になっているのでしょう.
 リスト4-6のようなプログラムにした場合,キャプションの背景色がディザの場合テキストの背景色と一致しなくなります(図4-2).

[図4-2] :

[リスト4-6] :

	case WM_CREATE:
		SetClassWord( hwnd, GCW_HBRBACKGROUND,
				CreateSolidBrush(GetSysColor(COLOR_ACTIVECAPTION)) );
		break;
	case WM_PAINT :{
		HDC			hdc;
		PAINTSTRUCT	ps;
		RECT		rc;
		hdc = BeginPaint(hwnd ,&ps);
		GetClientRect (hwnd , &rc);
		SetBkColor(hdc, GetSysColor(COLOR_ACTIVECAPTION) );
		SetTextColor(hdc, GetSysColor(COLOR_CAPTIONTEXT) );
		DrawText (hdc , szText ,-1 ,&rc,
			DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		EndPaint (hwnd ,&ps) ;
		return 0;
		}
 しかし,キャプションの色がディザでなく純色の場合,一致しているように見えることもあります(図4-3).

[図4-3] :

または32000色やフルカラーの環境の場合も一致します.
これを回避する方法として一番簡単なのは,SetBkMode()で背景モードを透明にしてしまうという方法があります(リスト4-7).
 SetBkMode()にTRANSPARENTを指定して背景を透明にすることで,(図4-4)のように背景がディザでも一致するようになりました.
 めでたしめでたし.

[図4-4] :

[リスト4-7] :

	case WM_CREATE:
		SetClassWord( hwnd, GCW_HBRBACKGROUND,
			CreateSolidBrush(GetSysColor(COLOR_ACTIVECAPTION)) );
		break;
	case WM_PAINT :{
		HDC			hdc;
		PAINTSTRUCT	ps;
		RECT		rc;
		
		hdc = BeginPaint(hwnd ,&ps);
		GetClientRect (hwnd , &rc);
		SetBkMode( hdc, TRANSPARENT );
		SetTextColor(hdc, GetSysColor(COLOR_CAPTIONTEXT) );
		DrawText (hdc , szText ,-1 ,&rc,
			DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		EndPaint (hwnd ,&ps) ;
		return 0;
		}

Back to FAQ main page