ダイアログとキー


Tabキーとグループ

ダイアログボックスの場合、コントロールのキー操作の多くは
Windows がその大部分を処理してくれます

通常、Tab キーを押すとキーボードフォーカスは次のコントロールへ進み
Shift + Tab キーを押すと前のコントロールにフォーカスが戻ります
しかし、それ以外でもラジオボタンのようなグループ化しているコントロールは
上下キーによるサポートが必要になったりもします

コントロールの入力フォーカスの切り替えは WS_TABSTOP の指定が必要です
多くのコントロールはこの指定をデフォルトで持ち合わせています
といっても、ダイアログテンプレートは明示的に WS_TABSTOP を明示することがある

リソーススクリプトで WS_TABSTOP を明示すると、そのコントロールが
グループの中で最初にフォーカスを受け取るコントロールであるということを意味する
これは、ラジオボタンのグループなどにおいては重要な動作です

また、コントロールのグループは WS_GROUP で指定できます
このスタイルが指定されているコントロールから
次に WS_GROUP が指定されるコントロールまでが一つのグループです
最後のグループまでフォーカスが来ると、次は最初のグループに戻ります

ただし、完全にマウスに依存しないダイアログの作成にはまだ問題があります
それは、ダイアログが表示された時点ではどのコントロールもフォーカスを持たないことです
そのため、何らかのコントロールにフォーカスを持たせなければ、Tab で移動できません

そこで WM_INITDIALOG メッセージを使用します
このメッセージは、ダイアログボックスが生成された時に送られてきます
WPARAM には、デフォルトでフォーカスを受ける予定のコントロールのハンドル
LPARAM はシステムに渡される初期化値で、通常は使いません

この時、SetFocus() 関数を使ってフォーカスを合わせてもかまいません

HWND SetFocus(HWND hWnd);

hWnd にはキーボードフォーカスを設定するウィンドウのハンドルを指定します
NULL を指定すると、キーストロークは無視されます
戻り値は以前フォーカスを持っていたウィンドウのハンドルです
hWnd が無効だった場合などは NULL が返ります

SetFocus() 関数を使ってフォーカスを合わせた場合
WM_INITDIALOG の結果は FALSE を返さなければならず
そうでなければ、TRUE を返します
TRUE を返した場合は、最初の WS_TABSTOP をもつコントロールにフォーカスがセットされます
//リソーススクリプト
KITTY DIALOG 10 , 10 , 100 , 50
FONT 12 , "MS ゴシック"
CAPTION "Magical nyan nyan TARUTO" {
	RADIOBUTTON "RENA" , 1 , 5 , 5 , 40 , 10 , WS_GROUP | WS_TABSTOP
	RADIOBUTTON "YUKI" , 2 , 5 , 15 , 40 , 10
	RADIOBUTTON "MIMI" , 3 , 5 , 25 , 40 , 10

	RADIOBUTTON "KAIMU" , 4 , 50 , 5 , 40 , 10 , WS_GROUP
	RADIOBUTTON "TOMOKA" , 5 , 50 , 15 , 40 , 10 , WS_TABSTOP
}
#include <windows.h>

BOOL CALLBACK DialogProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	int iCount;

	switch (msg) {
	case WM_CLOSE:
		EndDialog(hwnd , IDOK);
		return TRUE;
	case WM_INITDIALOG:
		return TRUE;
	case WM_COMMAND:
		if (LOWORD(wp) < 4)
			CheckRadioButton(hwnd , 1 , 3 , LOWORD(wp));
		else CheckRadioButton(hwnd , 4 , 5 , LOWORD(wp));
		return TRUE;
	}
	return FALSE;
}

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_LBUTTONUP:
		DialogBox(
			(HINSTANCE)GetWindowLong(hwnd , GWL_HINSTANCE) ,
			TEXT("KITTY") , hwnd , DialogProc
		);
		return 0;
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	HACCEL haccel;
	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;
}


ダイアログが作成された時、デフォルトで RENA ラジオボタンにフォーカスがあります
グループ内のボタンは上下キーでフォーカスが移動でき
他のグループへは Tab キーで移動させることができます

また、ダイアログボックスが表示されている時
Esc キーなどを押すと IDCANCEL を持つ WM_COMMAND が発行される
因みに、フォーカスは GetFocus() 関数で取得することもできる


SetFocus

HWND SetFocus(HWND hWnd);

キーボードフォーカスを指定したウィンドウにセットします

hWnd - キーボードフォーカスを設定するウィンドウのハンドルを指定します

戻り値 - 以前フォーカスを持っていたウィンドウのハンドル。失敗すれば NULL

GetFocus()

HWND GetFocus(VOID);

キーボードフォカースを持つウィンドウのハンドルを取得します

戻り値 - キーボードフォーカスを持つウィンドウのハンドルが返ります



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