チェックボックス
チェックボックスの作成
チェックボックスコントロールはオン/オフの状態を持つボタンです。
ボタンなのでBUTTON
クラスで作成します。
ウィンドウスタイルにBS_CHECKBOX
を指定するとチェックボックスを作成できます。
コントロールの作成の基本的なことはボタンコントロールの項を参照してください。
ウィンドウスタイルにボタンの種類を指定しない場合、BS_PUSHBUTTON
が指定されたものと解釈されます。
これは通常のプッシュボタンを作成します。
#define IDC_CHECK1 100
//チェックボックスの作成
CreateWindow(
L"BUTTON", L"Check",
WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
10, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK1, hInst, NULL);
これでチェックボックスが作成できます。
プッシュボタンの時と同様に、クリックするとWM_COMMAND
メッセージが通知されます。
しかしこの状態ではクリックしてもチェックのオン/オフは変わりません。
チェック状態の操作
BS_AUTOCHECKBOXスタイル
クリックするごとにチェックの状態を切り替えるにはBS_AUTOCHECKBOX
スタイルを使用します。
//チェックボックスの作成
CreateWindow(
L"BUTTON", L"Check",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
10, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK1, hInst, NULL);
チェックボックスはクリックごとにオン/オフを切り替えることが多いと思うので、通常はこれを使用するのが良いでしょう。
BM_SETCHECKメッセージ
チェックボックスのオン/オフの状態はBM_SETCHECK
メッセージで設定できます。
これはSendMessage関数で送信します。
SendMessage関数のWPARAMには、設定したい状態の定数を指定します。
BST_CHECKED
を指定するとチェックをオンにします。
BST_UNCHECKED
を指定するとチェックをオフにします。
LPARAMは使用しないのでNULL
(または0)を指定します。
戻り値は常に0です。
このメッセージによってチェックボックスの状態を変更してもWM_COMMAND
メッセージは送信されません。
BM_GETCHECKメッセージ
チェックボックスのオン/オフの状態はBM_GETCHECK
メッセージで取得できます。
SendMessage関数のWPARAM、LPARAMは共に使用しないのでNULL
(または0)を指定します。
オンの状態ならBST_CHECKED
を返します。
オフの状態はらBST_UNCHECKED
を返します。
BM_SETCHECK/BM_GETCHECメッセージを使用したチェックボックスのサンプルです。
#include <windows.h>
BOOL HasUnChecked(HWND[], size_t);
void OnClickCheckBox(HWND, HWND[], size_t);
//ウィンドウの生成等は省略
#define IDC_CHECK1 100
#define IDC_CHECK2 101
#define IDC_CHECK3 102
#define IDC_BUTTON1 103
#define CHECKBOX_NUM 3
//チェックボックスにひとつでもオフ状態があればTRUEを返す
BOOL HasUnChecked(HWND hCheckBoxes[], size_t length)
{
for (size_t i = 0; i < length; i++)
{
if (SendMessage(hCheckBoxes[i], BM_GETCHECK, 0, 0) == BST_UNCHECKED) {
return TRUE;
}
}
return FALSE;
}
//チェックボックスのクリック時にボタンテキストを切り替える
void OnClickCheckBox(HWND hBtn, HWND hCheckBoxes[], size_t length)
{
SendMessage(
hBtn,
WM_SETTEXT,
0,
(LPARAM)(HasUnChecked(hCheckBoxes, length) ? L"All On" : L"All Off"));
}
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hCheckBoxes[CHECKBOX_NUM];
static HWND hBtn;
switch (message)
{
case WM_CREATE: //ウィンドウ作成
hCheckBoxes[0] = CreateWindow(
L"BUTTON", L"Check1",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
10, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK1, hInst, NULL);
hCheckBoxes[1] = CreateWindow(
L"BUTTON", L"Check2",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
90, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK2, hInst, NULL);
hCheckBoxes[2] = CreateWindow(
L"BUTTON", L"Check3",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
170, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK3, hInst, NULL);
hBtn = CreateWindow(
L"BUTTON", L"All On",
WS_CHILD | WS_VISIBLE,
10, 45, 80, 25,
hWnd, (HMENU)IDC_BUTTON1, hInst, NULL);
break;
case WM_COMMAND: //コントロールの操作
switch (LOWORD(wParam))
{
case IDC_CHECK1:
case IDC_CHECK2:
case IDC_CHECK3:
OnClickCheckBox(hBtn, hCheckBoxes, CHECKBOX_NUM);
break;
case IDC_BUTTON1:
if (HasUnChecked(hCheckBoxes, CHECKBOX_NUM)) {
for (int i = 0; i < CHECKBOX_NUM; i++) {
SendMessage(hCheckBoxes[i], BM_SETCHECK, BST_CHECKED, 0);
}
SendMessage(hBtn, WM_SETTEXT, 0, (LPARAM)L"All Off");
}
else {
for (int i = 0; i < CHECKBOX_NUM; i++) {
SendMessage(hCheckBoxes[i], BM_SETCHECK, BST_UNCHECKED, 0);
}
SendMessage(hBtn, WM_SETTEXT, 0, (LPARAM)L"All On");
}
break;
}
break;
case WM_DESTROY: //ウィンドウの破棄
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
実行結果です。
このチェックボックスは個別に操作可能なほか、下のボタンを押すとすべてのチェックボックスを一括でオン/オフが出来ます。
ボタンのテキストはチェックボックスの状態によって切り替わります。
3状態チェックボックス
チェックボックスは「オン」「オフ」のふたつの状態を表しますが、オンでもオフでもない第三の状態を持てる3状態チェックボックスを作ることもできます。
3状態チェックボックスはウィンドウスタイルにBS_3STATE
を指定して作成します。
このスタイルではBS_CHECKBOX
スタイルと同様、クリックしても状態が切り替わりません。
クリックするごとに状態が切り替わる3状態チェックボックスはBS_AUTO3STATE
で作成できます。
3状態チェックボックスの「オン」と「オフ」については2状態チェックボックスと同じです。
(BST_CHECKED
とBST_UNCHECKED
)
3つ目の状態は定数BST_INDETERMINATE
で表され、「どちらでもない」「あいまい」な状態を意味します。
3つ目の状態をどのように扱うかはプログラマ次第です。
例えばいくつかのチェックボックスの状態を一括して表す場合に、オンとオフの状態が混在している場合に「どちらでもない」状態を使用できます。
#include <windows.h>
short GetCheckboxesState(HWND[], size_t);
void OnClickCheckBox(HWND, HWND[], size_t);
//ウィンドウの生成等は省略
#define IDC_CHECK1 100
#define IDC_CHECK2 101
#define IDC_CHECK3 102
#define IDC_CHECKALL 103
#define CHECKBOX_NUM 3
//複数のチェックボックスの状態を返す
short GetCheckboxesState(HWND hCheckBoxes[], size_t length)
{
int count = 0;
for (size_t i = 0; i < length; i++)
{
if (SendMessage(hCheckBoxes[i], BM_GETCHECK, 0, 0) == BST_CHECKED) {
count++;
}
}
return count == 0 ?
BST_UNCHECKED : count == length ?
BST_CHECKED : BST_INDETERMINATE;
}
//チェックボックスのクリック時にボタンの状態とテキストを切り替える
void OnClickCheckBox(HWND hBtn, HWND hCheckBoxes[], size_t length)
{
short state = GetCheckboxesState(hCheckBoxes, length);
SendMessage(hBtn, BM_SETCHECK, state, 0);
SendMessage(hBtn, WM_SETTEXT, 0,
state == BST_CHECKED ? L"All Off" : L"All On");
}
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hCheckBoxes[CHECKBOX_NUM];
static HWND hCheck3State;
short state;
switch (message)
{
case WM_CREATE: //ウィンドウ作成
hCheckBoxes[0] = CreateWindow(
L"BUTTON", L"Check1",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
10, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK1, hInst, NULL);
hCheckBoxes[1] = CreateWindow(
L"BUTTON", L"Check2",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
90, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK2, hInst, NULL);
hCheckBoxes[2] = CreateWindow(
L"BUTTON", L"Check3",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
170, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK3, hInst, NULL);
hCheck3State = CreateWindow(
L"BUTTON", L"All On",
WS_CHILD | WS_VISIBLE | BS_3STATE,
10, 45, 80, 25,
hWnd, (HMENU)IDC_CHECKALL, hInst, NULL);
break;
case WM_COMMAND: //コントロールの操作
switch (LOWORD(wParam))
{
case IDC_CHECK1:
case IDC_CHECK2:
case IDC_CHECK3:
OnClickCheckBox(hCheck3State, hCheckBoxes, CHECKBOX_NUM);
break;
case IDC_CHECKALL:
//手動でチェックボックスの状態を切り替える
state = SendMessage(hCheck3State, BM_GETCHECK, 0, 0);
state = state == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED;
SendMessage(hCheck3State, BM_SETCHECK, (WPARAM)state, 0);
if (state == BST_UNCHECKED) {
for (int i = 0; i < CHECKBOX_NUM; i++) {
SendMessage(hCheckBoxes[i], BM_SETCHECK, BST_UNCHECKED, 0);
}
SendMessage(hCheck3State, WM_SETTEXT, 0, (LPARAM)L"All On");
}
else {//BST_CHECKED or BST_INDETERMINATE
for (int i = 0; i < CHECKBOX_NUM; i++) {
SendMessage(hCheckBoxes[i], BM_SETCHECK, BST_CHECKED, 0);
}
SendMessage(hCheck3State, WM_SETTEXT, 0, (LPARAM)L"All Off");
}
break;
}
break;
case WM_DESTROY: //ウィンドウの破棄
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
実行結果です。
上段のチェックボックスを1つまたは2つチェックが入った状態にすると、下段のチェックボックスが「あいまい」な状態になります。
テキストの位置
チェックボックスは「左にボックス、右にテキスト」という形で作成されますが、BS_LEFTTEXT
スタイルまたはBS_RIGHTBUTTON
スタイルを使用することで、左右を入れ替えることができます。
CreateWindow(
L"BUTTON", L"Check1",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
10, 10, 80, 25,
hWnd, (HMENU)IDC_CHECK1, hInst, NULL);
//ボックスの位置の左右入れ替え
CreateWindow(
L"BUTTON", L"Check2",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT,
10, 40, 80, 25,
hWnd, (HMENU)IDC_CHECK2, hInst, NULL);
テキストの左揃え/右揃えはBS_LEFT
スタイル、BS_RIGHT
スタイルで設定します。
CreateWindow(
L"BUTTON", L"Check1",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT,
10, 10, 120, 25,
hWnd, (HMENU)IDC_CHECK1, hInst, NULL);
//テキストの右揃え
CreateWindow(
L"BUTTON", L"Check2",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_RIGHT,
10, 40, 120, 25,
hWnd, (HMENU)IDC_CHECK2, hInst, NULL);