ツールバーボタンのテキストとサイズ

テキストを表示

以前作成したツールバーのボタンは画像のみでしたが、同時にテキストを表示させることができます。
方法は簡単で、TBBUTTON構造体fsStyleメンバにBTNS_AUTOSIZE(TBSTYLE_AUTOSIZE)を指定し、iStringメンバに表示したい文字列(のポインタ)を指定します。


TBBUTTON tbb[] = {
	{ 0, IDC_A, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"あああ" },
	{ 1, IDC_I, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"いいい" },
	{ 0, 0, 0, BTNS_SEP },
	{ 2, IDC_U, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"ううう" },
	{ 3, IDC_E, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"えええ" },
	{ 4, IDC_O, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"おおお" }
};

ツールバーボタンにテキストを表示

BTNS_AUTOSIZEスタイルにより、テキストの長さに応じてボタンのサイズが自動調節されるようになります。
iStringメンバはINT_PTR型なのでキャストしておきます。
(キャストしなくても動きますがビルド時に警告がでます)

TB_ADDSTRINGメッセージ

ツールバーボタンにテキストを表示するにはTB_ADDSTRINGメッセージを使用する方法もあります。
このメッセージはツールバーに文字列を登録します。
登録した文字列は0から順に番号が割り振られ、TBBUTTON構造体のiStringにその番号を指定することで文字列を表示できます。

WPARAMには文字列リソースを含むモジュールのインスタンスを指定します。
NULLを指定すると、文字列リソースではなく文字列配列から文字列を登録します。

LPARAMは、WPARAMがNULLでない場合はリソースの識別子を指定します。
NULLの場合は文字列配列のポインタを指定します。

SendMessage関数が成功した場合、戻り値は登録した文字列の最初のインデックスです。
失敗した場合は-1が返されます。


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 | TBSTYLE_TOOLTIPS,
		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;
	SendMessage(hToolbar, TB_ADDBITMAP, (WPARAM)5, (LPARAM)&tb);

	//↓ここからテキスト表示処理

	//ボタンに表示する文字列
	//NULL文字を区切り文字として複数の文字を指定する
	WCHAR texts[] =
		L"あああ\0"
		L"いいい\0"
		L"ううう\0"
		L"えええ\0"
		L"おおお\0";

	//文字列の登録
	int index = SendMessage(hToolbar, TB_ADDSTRING, 0, (LPARAM)texts);

	TBBUTTON tbb[] = {
		{ 0, IDC_A, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
		{ 1, IDC_I, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
		{ 0, 0, 0, BTNS_SEP },
		{ 2, IDC_U, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
		{ 3, IDC_E, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
		{ 4, IDC_O, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ }
	};
	//↑テキスト表示処理ここまで

	SendMessage(hToolbar, TB_ADDBUTTONS, (WPARAM)6, (LPARAM)&tbb);
	return hToolbar;
}

登録する文字列配列はNULL文字を区切り文字とした特殊な文字列を使用します。
NULL文字が連続して出現すると文字列の終端を表します。
(詳しくはダブルNULL終端文字列を参照)

文字列配列ではなく文字列リソースから登録する場合は以下のようにします。


/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
    IDS_A                   "/あああ/いいい/ううう/えええ/おおお//"
END

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ で生成されたインクルード ファイル。
// Resource.rc で使用
//
#define IDB_BITMAP1                     101
#define IDS_A                           102

int index = SendMessage(hToolbar, TB_ADDSTRING, (WPARAM)hInst, (LPARAM)IDS_A);

TBBUTTON tbb[] = {
	{ 0, IDC_A, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
	{ 1, IDC_I, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
	{ 0, 0, 0, BTNS_SEP },
	{ 2, IDC_U, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
	{ 3, IDC_E, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ },
	{ 4, IDC_O, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, index++ }
};

リソース文字列は、区切り文字から始まり、各項目を区切り文字で区切り、最後は区切り文字を二つ連続させた文字列を使用します。
区切り文字は任意の文字を使用できます。
仕組みとしては文字列配列を使用する場合と同じです。

TB_ADDSTRINGメッセージではWPARAMにモジュール(実行ファイル)のインスタンスを、LPARAMに文字列リソースの識別子を指定します。
後の処理は文字列配列の場合と同じです。

ボタンサイズの調整

ボタンのスタイルにBTNS_AUTOSIZE(TBSTYLE_AUTOSIZE)を指定すると、各ボタンにサイズはテキストの長さにより自動的に調整されます。
つまり、ボタン毎にサイズがバラバラになる可能性があります。

このスタイルを適用しない場合、全てのボタンサイズは一番長いテキストを持つボタンのサイズに揃えられます。
ボタンサイズを自動調整しない場合

TB_SETBUTTONWIDTHメッセージ

ボタンサイズを自動調節しない場合、ボタンの横幅はTB_SETBUTTONWIDTHメッセージで調整することができます。

WPARAMは使用しないので0を指定します。
LPARAMの下位ワードはボタンの最小幅を、上位ワードは最大幅をそれぞれピクセル単位で指定します。
成功した場合は0以外を返します。


TBBUTTON tbb[] = {
	{ 0, IDC_A, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"あ" },
	{ 1, IDC_I, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"いい" },
	{ 2, IDC_U, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"ううう" },
	{ 3, IDC_E, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"ええええ" },
	{ 4, IDC_O, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"おおおおお" }
};

//ボタン幅の設定
SendMessage(hToolbar, TB_SETBUTTONWIDTH, 0, MAKELPARAM(30, 50));

SendMessage(hToolbar, TB_ADDBUTTONS, (WPARAM)5, (LPARAM)&tbb);

このコードは最小幅を30、最大幅を50に設定しています。
幅に収まりきらない場合はテキストが省略されます。
ボタン幅の設定

なお、このメッセージはボタンを追加する前に送信する必要がある、とMicrosoftは説明しています。

TB_SETBUTTONSIZEメッセージ

ボタンのサイズはTB_SETBUTTONSIZEメッセージで設定することもできます。

WPARAMは使用しないので0を指定します。
LPARAMの下位ワードはボタンの横幅を、上位ワードは縦幅をそれぞれピクセル単位で指定します。
成功した場合は0以外を返します。


TBBUTTON tbb[] = {
	{ 0, IDC_A, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"あ" },
	{ 1, IDC_I, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"いい" },
	{ 2, IDC_U, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"ううう" },
	{ 3, IDC_E, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"ええええ" },
	{ 4, IDC_O, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)L"おおおおお" }
};

SendMessage(hToolbar, TB_ADDBUTTONS, (WPARAM)5, (LPARAM)&tbb);

//ボタンサイズの設定
SendMessage(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(40, 60));

このコードは横幅を40、縦幅を60に設定しています。
なお、このメッセージはボタンを追加した後に送信する必要があります。
ボタンサイズの設定