システムカラー


システムカラーを使う

Windows をある程度使いこなせる方ならば、システムカラーをご存知でしょう
Windows はコントロールの色をユーザーに決定させる機能があります

この色のことを システムカラー と呼びます
システムカラーは、アプリケーションが自由に取得することもでき
アプリケーションがコントロールを生成した時のデフォルトの色にも使われます

以前説明したボタンコントロールの色は、システムカラーが用いられます
今回は、このシステムカラーについて説明しましょう

システムカラーの設定や管理は Windows が担当しています
Windows NT ではレジストリ、Windows 9x では WIN.INI ファイルに情報が保管されています
[colors]
Scrollbar=192 192 192
Background=0 128 128
ActiveTitle=0 0 128
InactiveTitle=128 128 128
Menu=192 192 192
Window=255 255 255
WindowFrame=0 0 0
MenuText=0 0 0
WindowText=0 0 0
TitleText=255 255 255
ActiveBorder=192 192 192
InactiveBorder=192 192 192
AppWorkspace=128 128 128
Hilight=0 0 128
HilightText=255 255 255
ButtonFace=192 192 192
ButtonShadow=128 128 128
GrayText=128 128 128
ButtonText=0 0 0
InactiveTitleText=192 192 192
ButtonHilight=255 255 255
ButtonDkShadow=0 0 0
ButtonLight=223 223 223
InfoText=0 0 0
InfoWindow=255 255 225
ButtonAlternateFace=181 181 181
HotTrackingColor=0 0 255
GradientActiveTitle=192 192 192
GradientInactiveTitle=255 255 255
これは、Windows 98 SE の WIN.INI ファイルのシステムカラーの部分です
しかし、通常はプログラムがこれに直接アクセスして調べるようなことはしません

アプリケーションがシステムカラーを得るには GetSysColor() 関数を使います

DWORD GetSysColor(int nIndex);

nIndex に、取得したいシステムカラーの色を表す定数を指定します
関数は、要求された色を返します

Windows 初期のころは、システムカラーの数が少なかったのですが
現在は、立体的に表示するために多くのシステムカラーが存在し
Windows 98 の時点で、29種類ものシステムカラーが存在します
システムカラーを表す定数は、下のリファレンスを参照してください
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	int iCount , iWidth = 0;
	static const int syscolor[] = {
		COLOR_3DDKSHADOW ,		COLOR_3DFACE ,
		COLOR_3DHILIGHT ,		COLOR_3DLIGHT ,
		COLOR_3DSHADOW ,		COLOR_ACTIVEBORDER ,
		COLOR_ACTIVECAPTION ,		COLOR_APPWORKSPACE ,
		COLOR_BACKGROUND ,		COLOR_BTNTEXT ,
		COLOR_CAPTIONTEXT ,		COLOR_GRAYTEXT ,
		COLOR_HIGHLIGHT ,		COLOR_HIGHLIGHTTEXT ,
		COLOR_INACTIVEBORDER ,	COLOR_INACTIVECAPTION ,
		COLOR_INFOBK ,			COLOR_INFOTEXT ,
		COLOR_MENU ,			COLOR_MENUTEXT ,
		COLOR_SCROLLBAR ,		COLOR_WINDOW ,
		COLOR_WINDOWFRAME ,		COLOR_WINDOWTEXT
	};

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd , &ps);
		SelectObject(hdc , GetStockObject(NULL_PEN));
		for(iCount = 0 ; iCount < sizeof(syscolor) / sizeof(int) ; iCount++) {
			SelectObject(hdc , CreateSolidBrush(GetSysColor(syscolor[iCount])));
			Rectangle(hdc , iWidth , 0 , iWidth + 20 , 200);
			DeleteObject(SelectObject(hdc , GetStockObject(WHITE_BRUSH)));
			iWidth += 20;
		}
		EndPaint(hwnd , &ps);
		return 0;
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
	return msg.wParam;
}


このプログラムは、列挙したシステムカラーを表示するプログラムです
タイトルバーやスクロールバーなどの非クライアントエリアの部品の色は
実はシステムカラーで設定されている色だったのです


システムカラーをセットする

システムカラーは、通常ユーザーがコントロールパネルの「画面」で設定します
しかし、プログラムからシステムカラーを設定することができます

これを利用すれば、コントロールの色を変更することができます
といっても、コントロールの色を指定職に変えたいという目的で
システムカラーを変更してはいけません

システムカラーを変更すると、あらゆるアプリケーション
そしてタスクバーなど Windows 全体に影響を与えてしまいます
むやみにシステムカラーを変更すると、ユーザーの反感をかうことになるかもしれません

システムカラーの変更には SetSysColors() 関数を使います
GetSysColor() と違って、配列を用いて一度に全体を設定することができます
BOOL WINAPI SetSysColors(
	int cElements,
	CONST INT *lpaElements,
	CONST COLORREF *lpaRgbValues
);
nElements は、設定する要素の数を指定します
lpaElements は設定するシステムカラーの定数が各要素に格納されている
INT 型の配列へのポインタを指定します
lpaRgbValues は、lpaElements の要素に対して設定する色の配列へのポインタです

関数が成功すると 0 以外、失敗すると 0 が返ります

lpaElements と lpaRgbValues は、互いのインデックスで関係し合います
lpaElements[0] が COLOR_WINDOW、lpaRgbValues[0] が 0xFF ならば
システムカラー COLOR_WINDOW は赤色に設定されます
この時、配列の数(設定する数)を cElements に指定すれば良いのです
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	static const COLORREF newSysColor[] = { RGB(0xFF , 00 , 00) };
	static const int setSysColor[] = { COLOR_BTNFACE };
	static COLORREF defSysColor[1];

	switch (msg) {
	case WM_DESTROY:
		SetSysColors(1 , setSysColor , defSysColor);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		defSysColor[0] = GetSysColor(setSysColor[0]);
		SetSysColors(1 , setSysColor , newSysColor);
		return 0;
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
	return msg.wParam;
}


このプログラムは、システムカラーの COLOR_BTNFACE を赤に変更します
これによって、このシステムカラーを使っているアプリケーションの色が全て変更します
このプログラムは終了すると、元の色に戻るようにしているので安心してください

見てわかるように、自分自身だけではなく
他のアプリケーションにまで影響していることが確認できますね

ただし、このシステムカラーは保存されないので
ウィンドウズが終了した時点で元に戻ってしまう

また、プログラムの実行中にシステムカラーが変更された場合
WM_SYSCOLORCHANGE メッセージを受け取ります
パラメータ、戻り値はとくにありません

しかし、Windows はシステムカラーが変更されると WM_PAINT も発行する ため
通常、このメッセージを処理する必要はありません

一般に、ウィンドウがデバイスコンテキストの属性を保存する形式をとっている状態で
ブラシなどがシステムカラーを使っている時に、既存のブラシの解放と
新しいブラシの生成の処理に、このメッセージを使う程度です


GetSysColor()

DWORD GetSysColor(int nIndex);

システムカラーを取得します

nIndex - システムカラーの要素を指定します

戻り値 - 指定したシステムカラーのRGB値を返します

nIndex には次のいずれかの値を指定します

定数解説
COLOR_3DDKSHADOW 3D オブジェクトの暗い影の色
COLOR_3DFACE,
COLOR_BTNFACE
3D オブジェクトの表面色
COLOR_3DHILIGHT,
COLOR_3DHIGHLIGHT,
COLOR_BTNHILIGHT,
COLOR_BTNHIGHLIGHT
3D オブジェクトの最も明るい色 (光源方向の縁用)
COLOR_3DLIGHT 3D オブジェクトの明るい色 (光源方向の縁用)
COLOR_3DSHADOW,
COLOR_BTNSHADOW
3D オブジェクトの影の色 (光源の反対方向の縁用)
COLOR_ACTIVEBORDER アクティブウィンドウの境界の色
COLOR_ACTIVECAPTION アクティブウィンドウのタイトルバーの色
COLOR_APPWORKSPACE マルチドキュメントインターフェイス (MDI) アプリケーションの背景色
COLOR_BACKGROUND,
COLOR_DESKTOP
デスクトップの色
COLOR_BTNTEXT プッシュボタンのテキストの色
COLOR_CAPTIONTEXT アクティブウィンドウのタイトルバーのテキストの色
COLOR_GRAYTEXT 淡色状態 (無効状態) のテキストの色
COLOR_HIGHLIGHT コントロール内における選択された項目の色
COLOR_HIGHLIGHTTEXT コントロール内における選択された項目のテキストの色
COLOR_INACTIVEBORDER 非アクティブウィンドウの境界色
COLOR_INACTIVECAPTION 非アクティブウィンドウのタイトルバーのテキストの色
COLOR_INFOBK ツールチップコントロールの背景色
COLOR_INFOTEXT ツールチップコントロールのテキストの色
COLOR_MENU メニューの背景色
COLOR_MENUTEXT メニュー内のテキストの色
COLOR_SCROLLBAR スクロールバーの軸の色
COLOR_WINDOW ウィンドウの背景色
COLOR_WINDOWFRAME ウィンドウの枠の色
COLOR_WINDOWTEXT ウィンドウ内のテキストの色

SetSysColors()

BOOL WINAPI SetSysColors(
	int cElements,
	CONST INT *lpaElements,
	CONST COLORREF *lpaRgbValues
);
システムカラーを設定します

cElements - 設定する配列の要素数を指定します
lpaElements - 設定するシステムカラーを表した定数を指定します
lpaRgbValues - 設定する色を指定します

戻り値 - 成功すると 0 以外、失敗すると 0

lpaElements に指定する定数は GetSysColor() を参照してください




前のページへ戻る次のページへ