ツールバーボタンの状態

状態の取得

ツールバーのボタンの状態はTB_GETSTATEメッセージで取得することができます。

WPARAMは取得するボタンの識別子を指定します。
LPARAMは使用しないので0を指定します。

戻り値はボタンの状態を示す定数の組み合わせを示す整数値です。
(DWORD型)
失敗した場合は-1を返します。

定数 説明
TBSTATE_CHECKED チェックボックススタイルを持つボタンで、チェックされている状態
TBSTATE_ELLIPSES ボタンテキストの省略
TBSTATE_ENABLED 有効なボタン
TBSTATE_HIDDEN ボタンの非表示
TBSTATE_INDETERMINATE ボタンの灰色表示
TBSTATE_MARKED ボタンがマークされた状態
この状態の意味はアプリケーションにより異なる
TBSTATE_PRESSED ボタンは押されている状態
TBSTATE_WRAP ボタンの後ろに改行を入れる
TBSTATE_ENABLEDを同時に指定する必要がある

ある状態のオン/オフを調べるにはビット演算を使用します。


DWORD state = SendMessage(hToolbar, TB_GETSTATE, id, 0);
if(state & TBSTATE_ENABLED) {
	//オン
}

サンプルコード


#pragma comment(lib, "Comctl32.lib")

#include <windows.h>
#include <strsafe.h>
#include <commctrl.h>
#include "resource.h"

//ウィンドウの生成等は省略

#define BUFFERSIZE 1024

#define IDC_A 101
#define IDC_I 102
#define IDC_U 103
#define IDC_E 104
#define IDC_O 105

//ツールバーを作成
HWND CreateToolbar(HWND hWnd)
{
	INITCOMMONCONTROLSEX icc;
	icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
	icc.dwICC = ICC_BAR_CLASSES;
	InitCommonControlsEx(&icc);

	HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
		WS_CHILD | WS_VISIBLE,
		0, 0, 0, 0,
		hWnd, NULL, hInst, NULL);

	SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
	SendMessage(hToolbar, TB_SETBITMAPSIZE, 0, MAKELPARAM(16, 15));

	COLORMAP colorMap;
	colorMap.from = RGB(255, 255, 255);
	colorMap.to = GetSysColor(COLOR_BTNFACE);
	HBITMAP hbm = CreateMappedBitmap(hInst, IDB_BITMAP1, 0, &colorMap, 1);

	TBADDBITMAP tb;
	tb.hInst = NULL;
	tb.nID = (UINT_PTR)hbm;
	int index = SendMessage(hToolbar, TB_ADDBITMAP, (WPARAM)5, (LPARAM)&tb);

	//ボタンの登録
	TBBUTTON tbb[] = {
		{ index++, IDC_A, TBSTATE_ENABLED, BTNS_BUTTON },
		{ index++, IDC_I, TBSTATE_ENABLED, BTNS_CHECK },
		{ 0, 0, 0, BTNS_SEP },
		{ index++, IDC_U, TBSTATE_ENABLED, BTNS_CHECKGROUP },
		{ index++, IDC_E, TBSTATE_ENABLED, BTNS_CHECKGROUP },
		{ index++, IDC_O, TBSTATE_ENABLED, BTNS_CHECKGROUP }
	};
	SendMessage(hToolbar, TB_ADDBUTTONS, (WPARAM)6, (LPARAM)&tbb);

	return hToolbar;
}

//ツールバーボタンの状態を文字列で取得する
//hToolbar:	ツールバーハンドル
//id:		ボタン識別子
//buf:		文字列バッファ
//cchBuf:	バッファサイズ
BOOL GetTBButtonState(HWND hToolbar, int id, WCHAR* buf, size_t cchBuf)
{
	if (buf == NULL)
		return FALSE;

	//ツールバーボタンの状態の取得
	DWORD state = SendMessage(hToolbar, TB_GETSTATE, id, 0);
	if (state < 0)
		return FALSE;

	if (SUCCEEDED(
		StringCchPrintf(buf, cchBuf,
			L"ENABLED: %s, HIDDEN: %s, CHECKED: %s, MARKED: %s\n",
			(state & TBSTATE_ENABLED) ? L"Y" : L"N",
			(state & TBSTATE_HIDDEN) ? L"Y" : L"N",
			(state & TBSTATE_CHECKED) ? L"Y" : L"N",
			(state & TBSTATE_MARKED) ? L"Y" : L"N")
	)) {
		return TRUE;
	}
	return FALSE;
}

//ツールバーボタンの状態を文字列で取得し、キャプションを付ける
//hToolbar:	ツールバーハンドル
//id:		ボタン識別子
//caption:	キャプション
//cchCaption: キャプション文字列のサイズ
//buf:		文字列バッファ
//cchBuf:	バッファサイズ
//concat:	FALSE:バッファに上書き,TRUE:バッファに結合
BOOL GetTBButtonStateEx(HWND hToolbar, int id, const WCHAR* caption, size_t cchCaption, WCHAR* buf, size_t cchBuf, BOOL concat)
{
	if (buf == NULL)
		return FALSE;

	if (caption != NULL)
	{
		if (concat) {
			if (!SUCCEEDED(StringCchCatN(buf, cchBuf, caption, cchCaption)))
				return FALSE;
		}
		else {
			if (!SUCCEEDED(StringCchCopyN(buf, cchBuf, caption, cchCaption)))
				return FALSE;
		}
		if (!SUCCEEDED(StringCchCatN(buf, cchBuf, L"\n", 1)))
			return FALSE;
	}

	WCHAR* _buf = malloc(sizeof(WCHAR) * cchBuf);
	if (_buf == NULL)
		return FALSE;

	if (!GetTBButtonState(hToolbar, id, _buf, cchBuf)) {
		free(_buf);
		return FALSE;
	}
	if (!SUCCEEDED(StringCchCatN(buf, cchBuf, _buf, cchBuf))) {
		free(_buf);
		return FALSE;
	}
	free(_buf);
	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND hToolbar;

	HDC hdc;
	PAINTSTRUCT ps;
	RECT rcToolbar;
	static RECT rcClient;

	static WCHAR output[BUFFERSIZE];

	switch (message)
	{
	case WM_CREATE: //ウィンドウの作成
		hToolbar = CreateToolbar(hWnd);
		break;

	case WM_SIZE:
		SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
		GetClientRect(hWnd, &rcClient);
		GetWindowRect(hToolbar, &rcToolbar);
		rcClient.top += rcToolbar.bottom - rcToolbar.top;
		rcClient.left += 5;
		rcClient.top += 5;
		rcClient.right -= 5;
		rcClient.bottom -= 5;
		break;

	case WM_COMMAND: //コントロールの操作
		switch (LOWORD(wParam))
		{
		case IDC_A:
		case IDC_I:
		case IDC_U:
		case IDC_E:
		case IDC_O:
			output[0] = L'\0';

			if (!GetTBButtonStateEx(hToolbar, IDC_I, L"IDC_I", 5, output, BUFFERSIZE, FALSE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			if (!GetTBButtonStateEx(hToolbar, IDC_U, L"\nIDC_U", 6, output, BUFFERSIZE, TRUE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			if (!GetTBButtonStateEx(hToolbar, IDC_E, L"\nIDC_E", 6, output, BUFFERSIZE, TRUE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			if (!GetTBButtonStateEx(hToolbar, IDC_O, L"\nIDC_O", 6, output, BUFFERSIZE, TRUE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			InvalidateRect(hWnd, NULL, TRUE);
			break;
		}
		break;

	case WM_PAINT:
		hdc =  BeginPaint(hWnd, &ps);

		if (output[0] == L'\0')
		{
			DrawText(hdc, L"情報なし", -1, &rcClient, DT_WORDBREAK);
		}
		else
		{
			DrawText(hdc, output, -1, &rcClient, DT_WORDBREAK);
		}
		EndPaint(hWnd, &ps);
		break;

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

「あ」は通常のボタン、「い」はトグルボタン(チェックボタン)、「う」「え」「お」はラジオボタングループとして作成しています。
いずれかのボタンをクリックすることでそれぞれのボタンの状態を取得し、画面に出力します。
(Y=オン、N=オフ)
ツールバーボタンの状態を取得するサンプル

状態の設定

ツールバーボタンの状態はTB_SETSTATEメッセージで設定できます。

WPARAMは設定するボタンの識別子を指定します。
LPARAMは、下位ワードにボタンの状態を示す整数値を指定します。
上位ワードは0を指定します。
成功した場合はTRUEを、失敗した場合はFALSEを返します。


//ウィンドウの生成等は省略

#define BUFFERSIZE 1024

#define IDC_A 101
#define IDC_I 102
#define IDC_U 103
#define IDC_E 104
#define IDC_O 105

HWND CreateToolbar(HWND hWnd)
{ //省略 }

BOOL GetTBButtonState(HWND hToolbar, int id, WCHAR* buf, size_t cchBuf)
{ //省略 }

BOOL GetTBButtonStateEx(HWND hToolbar, int id, const WCHAR* caption, size_t cchCaption, WCHAR* buf, size_t cchBuf, BOOL concat)
{ //省略 }

//ツールバーボタンの状態をランダムに設定する
//hToolbar:	ツールバーハンドル
//ids:		ボタン識別子の配列
//length:	配列サイズ
void SetTBButtonStateRandom(HWND hToolbar, int* ids, size_t length)
{
	static char init;
	if (!init) {
		init = 1;
		//乱数の種の初期化
		srand(time(NULL));
	}

	for (int n = 0; n < length; n++) {
		DWORD state = 0;
		//ボタンの状態をランダムに設定
		if (rand() % 2) state |= TBSTATE_ENABLED;
		//if (rand() % 2) state |= TBSTATE_HIDDEN;
		if (rand() % 2) state |= TBSTATE_CHECKED;
		if (rand() % 2) state |= TBSTATE_MARKED;
		SendMessage(hToolbar, TB_SETSTATE, ids[n], MAKELPARAM(state, 0));
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND hToolbar;

	HDC hdc;
	PAINTSTRUCT ps;
	RECT rcToolbar;
	static RECT rcClient;

	static WCHAR output[BUFFERSIZE];

	switch (message)
	{
	case WM_CREATE: //ウィンドウの作成
		hToolbar = CreateToolbar(hWnd);
		break;

	case WM_SIZE:
		SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
		GetClientRect(hWnd, &rcClient);
		GetWindowRect(hToolbar, &rcToolbar);
		rcClient.top += rcToolbar.bottom - rcToolbar.top;
		rcClient.left += 5;
		rcClient.top += 5;
		rcClient.right -= 5;
		rcClient.bottom -= 5;
		break;

	case WM_COMMAND: //コントロールの操作
		switch (LOWORD(wParam))
		{
		case IDC_A: {
			int ids[] = { IDC_I, IDC_U, IDC_E, IDC_O };
			SetTBButtonStateRandom(hToolbar, ids, sizeof(ids) / sizeof(ids[0]));
		}
		case IDC_I:
		case IDC_U:
		case IDC_E:
		case IDC_O:
			output[0] = L'\0';

			if (!GetTBButtonStateEx(hToolbar, IDC_I, L"IDC_I", 5, output, BUFFERSIZE, FALSE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			if (!GetTBButtonStateEx(hToolbar, IDC_U, L"\nIDC_U", 6, output, BUFFERSIZE, TRUE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			if (!GetTBButtonStateEx(hToolbar, IDC_E, L"\nIDC_E", 6, output, BUFFERSIZE, TRUE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			if (!GetTBButtonStateEx(hToolbar, IDC_O, L"\nIDC_O", 6, output, BUFFERSIZE, TRUE)) {
				output[0] = L'\0';
				InvalidateRect(hWnd, NULL, TRUE);
				break;
			}
			InvalidateRect(hWnd, NULL, TRUE);
			break;
		}
		break;

	case WM_PAINT:
		hdc =  BeginPaint(hWnd, &ps);

		if (output[0] == L'\0')
		{
			DrawText(hdc, L"情報なし", -1, &rcClient, DT_WORDBREAK);
		}
		else
		{
			DrawText(hdc, output, -1, &rcClient, DT_WORDBREAK);
		}
		EndPaint(hWnd, &ps);
		break;

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

「あ」ボタンをクリックすると、それ以外のボタンの状態をランダムに設定します。
(ただしTBSTATE_HIDDENフラグは見た目にわかりにくくなるので除外しています)
単純にランダムに設定しているだけなので、ラジオボタンが二つ同時に押された状態になるなど通常では起こらない状態になることもあります。
ツールバーボタンの状態を設定するサンプル