論理パレットの操作


論理パレットを制御する

これまで、LOGPALETTE 構造体を用いて論理パレットを作成し
これをリアライズしてパレットを使ってきました

Windows は、この論理パレットの情報を取得したり
あるいは、論理パレットの内容を更新する手段を提供しています
論理パレットの RGB 値に問い合わせるには GetPaletteEntries() を使います
これは、GetSystemPaletteEntries() の第一引数を論理パレットにしたものです
UINT GetPaletteEntries(
	HPALETTE hpal , UINT iStartIndex ,
	UINT nEntries , LPPALETTEENTRY lppe
);
hpal には論理パレットのハンドル
iStartIndex には、色の取得を開始する最初のパレットエントリを
nEntries は、データを取得する数を指定します
lppe は取得したデータを格納する PALETTEENTRY 構造体へのポインタです

関数が成功し lppe が NULL 以外ならば、取得したエントリの数が
lppe が NULL ならば指定したパレット内のインデックス数が返ります
関数が失敗すると 0 が返ります

逆に、論理パレットに色を設定することも可能です
設定するには SetPaletteEntries() 関数を使用します
UINT SetPaletteEntries(
	HPALETTE hpal , UINT iStart ,
	UINT cEntries , CONST PALETTEENTRY *lppe
);
hpal は論理パレットのハンドルを、iStart には設定を開始するパレットエントリ
cEntries には設定する数、lppe は設定するデータが格納されている
PALETTEENTRY 構造体へのポインタを指定します

関数が成功すると、論理パレットに設定されたエントリ数が
失敗すると 0 が返ります

必要であれば、論理パレットのサイズを変更することも可能です
これには、ResizePalette() 関数を使用します

BOOL ResizePalette(HPALETTE hpal , UINT nEntries);

hpal には、サイズを変更する論理パレットのハンドルを
nEntries には、サイズ変更後のパレットのエントリ数を指定します
関数が成功すると 0 以外、失敗すると 0 が返ります
#include <windows.h>
#include <stdlib.h>

#define BUTTON_OK 1
#define ERR_INDEX TEXT("エントリは 0 〜 255 で指定してください")
#define ERR_COLOR TEXT("RGB 値を数値で指定してください")

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	HBRUSH hBrush;
	TCHAR strIndex[16] , strColor[16];
	int count , entry , index , color , x = 20 , y = 40;
	LOGPALETTE lpPalette;
	static HPALETTE hPalette;
	static HWND hEditPalIndex , hEditColor , hButtonOK;
	
	switch (msg) {
	case WM_DESTROY:
		DeleteObject(hPalette);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		hEditPalIndex = CreateWindow(
			TEXT("EDIT") , TEXT("0") ,
			WS_CHILD | WS_VISIBLE | WS_BORDER |ES_NUMBER ,
			10 , 10 , 100 , 25 , hWnd , NULL ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		hEditColor = CreateWindow(
			TEXT("EDIT") , TEXT("0x000000") ,
			WS_CHILD | WS_VISIBLE | WS_BORDER ,
			120 , 10 , 100 , 25 , hWnd , NULL ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		hButtonOK = CreateWindow(
			TEXT("BUTTON") , TEXT("OK") ,
			WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,
			230 , 10 , 100 , 25 , hWnd , (HMENU)BUTTON_OK ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);

		lpPalette.palVersion = 0x0300;
		lpPalette.palNumEntries = 1;

		lpPalette.palPalEntry[0].peRed =
		lpPalette.palPalEntry[0].peGreen =
		lpPalette.palPalEntry[0].peBlue = 
		lpPalette.palPalEntry[0].peFlags = NULL;

		hPalette = CreatePalette(&lpPalette);

		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd , &ps);
		entry = GetPaletteEntries(hPalette , 0 , 0 , NULL);
		SelectPalette(hdc , hPalette , FALSE);
		RealizePalette(hdc);

		for (count = 0 ; count < entry ; count++ , x += 20) {
			hBrush = CreateSolidBrush(PALETTEINDEX(count));
			SelectObject(hdc , hBrush);

			Rectangle(hdc , x , y , x + 10 , y + 20);
			if (x > 600) { y += 30; x = 0; }
			SelectObject(hdc , GetStockObject(WHITE_BRUSH));
			DeleteObject(hBrush);
		}

		EndPaint(hWnd ,&ps);
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wp)) {
		case BUTTON_OK:
			GetWindowText(hEditPalIndex , strIndex , 16);
			index = atoi(strIndex);
			if (index < 0 || index > 255) {
				MessageBox(hWnd , ERR_INDEX , NULL , MB_OK);
				return 0;
			}

			GetWindowText(hEditColor , strColor , 16);
			color = (int)strtol(strColor , NULL , 16);
			if (color < 0 || color > 0xFFFFFF) {
				MessageBox(hWnd , ERR_COLOR , NULL , MB_OK);
				return 0;
			}

			lpPalette.palPalEntry[0].peRed = (BYTE)(color >> 16);
			lpPalette.palPalEntry[0].peGreen = (BYTE)(color >> 8);
			lpPalette.palPalEntry[0].peBlue = (BYTE)color;
			lpPalette.palPalEntry[0].peFlags = NULL;

			if (index + 1 > GetPaletteEntries(hPalette , 0 , 0 , NULL))
				ResizePalette(hPalette , index + 1);

			SetPaletteEntries(hPalette , index , 1 , lpPalette.palPalEntry);
			InvalidateRect(hWnd , NULL , TRUE);
		}
		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 )) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}


このプログラムを実行すると、上のようなウィンドウが表示されます
左のエディットウィンドウは論理パレットのエントリ番号
右のエディットウィンドウは指定したパレットエントリの RGB 値を入力するものです

各値を正しく入力し OK ボタンを押すと、下にパレットが色で表示されます
プログラム起動時には、論理パレットは 1 つしかエントリを保有していません
存在していないエントリが指定されると、その番号までパレットを拡張します

この他にも、指定した色に最も近いパレットインデックスを取得する方法もあります
そのためには GetNewrestPaletteIndex() を用います

UINT GetNearestPaletteIndex(HPALETTE hpal , COLORREF crColor);

hpal には論理パレットのハンドル、crColor は検索する RGB 値を指定します
成功すれば、指定した色に最も近い論理パレットのインデックスが
失敗すると、CLR_INVALID が返ります

現在のシステムパレットの情報を取得して、そこから論理パレットを作成し
システムパレット内で、欲しい色にもっとも近い色はどれかを調べたりすることができます


GetPaletteEntries()

UINT GetPaletteEntries(
	HPALETTE hpal , UINT iStartIndex ,
	UINT nEntries , LPPALETTEENTRY lppe
);
論理パレットから指定範囲のカラー情報を取得します

hpal - 論理パレットのハンドルを指定します
iStartIndex - 取得する最初のパレットエントリを指定します
nEntries - 取得するパレットエントリ数を指定します
lppe - 取得したデータを格納するバッファを指定します

戻り値 - 取得したエントリ数、lppeが NULL ならパレットエントリ数、失敗したら 0

setPaletteEntries()

UINT SetPaletteEntries(
	HPALETTE hpal , UINT iStart ,
	UINT cEntries , CONST PALETTEENTRY *lppe
);
論理パレットのカラー情報を変更します

hpal - 論理パレットのハンドルを指定します
iStart - 設定する最初のパレットエントリを指定します
cEntries - 設定するエントリ数を指定します
lppe - 設定するデータが格納されているバッファを指定します

戻り値 - 論理パレットに設定されたエントリ数。失敗すると 0

ResizePalette()

BOOL ResizePalette(HPALETTE hpal , UINT nEntries);

論理パレットのエントリ数を変更します

hpal - サイズを変更する論理パレットのハンドルを指定します
nEntries - サイズ変更後のパレットのエントリ数を指定します

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

GetNearestPaletteIndex()

UINT GetNearestPaletteIndex(HPALETTE hpal , COLORREF crColor);

指定した色に最も近い論理パレットのインデックスを返します

hpal - 論理パレットのハンドルを指定します
crColor - 検索する色を指定します

戻り値 - 指定した色に最も近いインデックス。失敗すると、CLR_INVALID



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