色の選択
コモンダイアログ
Windows は、ユーザーに一貫性のある、直感的な操作をサポートしています
例えば、熟練ユーザーは「ファイル」メニューの「保存」アイテムをクリックすれば
ファイルの保存ダイアログが表示されることを知っています
この、ファイルの保存ダイアログは、多くのアプリケーションが表示します
メーカーが異なっていても、素人が作ったプログラムでも、保存の時は同じダイアログです
(稀に、独自のウィンドウを表示させるマニアックなソフトウェアもあるが…)
実は、これはコモンダイアログと呼ばれる
Windows が提供している、標準的なダイアログコントロールなのです
全てのアプリケーションが共通した処理に、共通した UI を提供することで
使用するユーザーは、直感的に、わかりやすくアプリケーションを使えるのです
もちろん開発者も、その分、作業量が減り、より生産性を高めることができます
これは、多くの利用者が Windows を標準の OS に選択した理由のひとつでもあるでしょう
もし、あなたのアプリケーションが、ファイルを保存する時、印刷するとき、フォントを選択する時
他のアプリケーションとは違う、独自のダイアログを表示させれば
ユーザーは操作方法がなかなか理解できず、単純な作業に時間を奪われるかもしれません
高度なソフトウェアを開発するには、標準コントロールの存在が不可欠なのです
色の設定ダイアログ
今回は、色をユーザーに選択してもらう「色の設定」ダイアログを表示させてみましょう
画像関連のソフトウェアで、多く用いられるダイアログです
色の設定ダイアログを表示するには ChooseColor() 関数を使います
この関数は、指定したスタイルで、モーダルダイアログボックスを表示させます
BOOL ChooseColor(LPCHOOSECOLOR lpcc);
lpcc には、設定情報を格納した CHOOSECOLOR 構造体へのポインタを指定します
戻り値は、ユーザーが色を選択したら TRUE、そうでなければ FALSE を返します
キャンセルボタンを選択されり、エラーが発生した場合は FALSE が返ります
CHOOSECOLOR 構造体は、次のように定義されています
typedef struct { // cc
DWORD lStructSize;
HWND hwndOwner;
HWND hInstance;
COLORREF rgbResult;
COLORREF* lpCustColors;
DWORD Flags;
LPARAM lCustData;
LPCCHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
} CHOOSECOLOR;
lStructSize には、この構造体のサイズを指定します
hwndOwner は、ダイアログのオーナーウィンドウを指定します
オーナーウィンドウが存在しない場合は NULL を指定することができます
hInstance は、ダイアログテンプレートを用いる場合に
使用するダイアログテンプレートを含む、モジュールのインスタンスを指定します
ダイアログテンプレートについては、後で説明します
rgbResult は、ダイアログが最初に選択している初期カラーを指定します
ユーザーが色を選択してダイアログを閉じた後は、選択した色が格納されています
このメンバの色を使えない場合は、それに一番近い色をシステムが設定します
lpCistColors には、ダイアログが持っている基本色を格納する
16個の COLORREF 配列へのポインタを指定します
ユーザーは、作成した色をダイアログのパレット領域に一時保存することができ
この変数の配列には、そのダイアログの基本色が格納されます
Flags は、ダイアログボックスの初期化フラグを指定します
このメンバには、以下の定数を組み合わせて指定することができます
定数 | 解説
|
---|
CC_ENABLEHOOK | lpfnHook メンバで指定されたフック関数を有効にする
|
CC_ENABLETEMPLATE | nInstance メンバと lpTemplateName メンバで指定された ダイアログボックステンプレートを使ってダイアログを作成します
|
CC_ENABLETEMPLATEHANDLE | hInstance メンバがロード済みのダイアログボックステンプレートを含む メモリブロックを指していることを表す このフラグが指定されている場合、lpTemplateName は無視される
|
CC_FULLOPEN | カスタムカラー作成部を含む 色の設定ダイアログボックス全体を表示する
|
CC_PREVENTFULLOPEN | 「色の作成」ボタンを無効にする
|
CC_RGBINIT | rgbResult メンバで指定した値を 初期設定カラーとしてダイアログに使用します
|
CC_SHOWHELP | ダイアログボックスに「ヘルプ」ボタンを追加する このフラグを指定した場合、hwndOwner を指定しなければなりません
|
lCustData メンバは、lpfnHook で指定されたフック関数に渡す追加情報を指定します
データは、WM_INITDIALOG めっせーじの LPARAM 型引数に渡されます
lpfnHook は、フック関数へのポインタを指定します
フック関数については、次の章で詳しく解説しますが、簡単に説明するならサブクラス化です
コモンダイアログは、独自のメッセージ処理関数を使ってカスタマイズすることができるのです
lpTemplateName には、使用するダイアログテンプレートの名前を指定します
hInstance メンバで指定したモジュールの指定したテンプレートを使用するようになります
ダイアログテンプレートとは、外観を変更するときに用います
コモンダイアログに、独自のコントロールを貼りつけたい場合や
丸々、独自のダイアログをつけたい場合などに、フック関数と合わせて拡張したりできます
ダイアログテンプレートについても、後ほど詳しく解説いたします
さて、これだけで、複雑な色の設定ウィンドウをアプリケーションで使うことができます
自分で同じようなものを作成することを考えれば、かなり便利だと思うでしょう
他のコモンダイアログも、同じように1つの専用関数と1つの専用構造体を使用します
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
static CHOOSECOLOR cc = {0};
static COLORREF color = 0 , CustColors[16];
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE:
cc.lStructSize = sizeof (CHOOSECOLOR);
cc.hwndOwner = hWnd;
cc.rgbResult = color;
cc.lpCustColors = CustColors;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
return 0;
case WM_LBUTTONUP:
if (!ChooseColor(&cc)) return 0;
SetClassLong(hWnd , GCL_HBRBACKGROUND ,
(LONG)CreateSolidBrush(cc.rgbResult));
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(BLACK_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;
}
このプログラムは、ウィンドウのクライアント領域を左クリックすると
今回の主役である、色の選択ダイアログボックスが表示されます
色を選択すると、プログラムはクライアント領域の背景色としてその色を選択します
ChooseColor()
BOOL ChooseColor(LPCHOOSECOLOR lpcc);
色の選択ダイアログボックスを表示します
lpcc - 設定情報を格納した CHOOSECOLOR 構造体へのポインタを指定します
戻り値 - ユーザーが色を選択したら TRUE、そうでなければ FALSE