EternalWindows
ツールバー / 縦型のツールバー

今回は、ボタンにテキストを表示するプログラムを作成します。 また、ツールバーを縦型にする方法も取り上げます。

#include <windows.h>
#include <commctrl.h>

#define ID_TOOLBAR 100
#define ID_OPEN    200
#define ID_SAVE    300
#define ID_STYLE   400

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

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	TCHAR      szAppName[] = TEXT("sample");
	HWND       hwnd;
	MSG        msg;
	WNDCLASSEX wc;

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WindowProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hinst;
	wc.hIcon         = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	wc.hCursor       = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = szAppName;
	wc.hIconSm       = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	
	if (RegisterClassEx(&wc) == 0)
		return 0;

	hwnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL);
	if (hwnd == NULL)
		return 0;

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	static HWND hwndToolbar = NULL;
	
	switch (uMsg) {
		
	case WM_CREATE: {
		TBBUTTON tbButton[] = {
			{STD_FILEOPEN, ID_OPEN, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("開く")},
			{STD_FILESAVE, ID_SAVE, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("保存")},
			{I_IMAGENONE, ID_STYLE, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("スタイル変更")}
		};
		int                  nCount = nCount = sizeof(tbButton) / sizeof(tbButton[0]);
		INITCOMMONCONTROLSEX ic;
		
		ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
		ic.dwICC  = ICC_BAR_CLASSES;
		InitCommonControlsEx(&ic);

		hwndToolbar = CreateToolbarEx(hwnd, WS_CHILD | WS_VISIBLE | TBSTYLE_LIST, ID_TOOLBAR, 0, HINST_COMMCTRL, IDB_STD_SMALL_COLOR, tbButton, nCount, 0, 0, 0, 0, sizeof(TBBUTTON));

		return 0;
	}

	case WM_COMMAND:
		if (LOWORD(wParam) == ID_STYLE) {
			int      i;
			int      nCount = (int)SendMessage(hwndToolbar, TB_BUTTONCOUNT, 0, 0);
			DWORD    dwStyle, dwState;
			TBBUTTON tbButton;

			dwStyle = (DWORD)SendMessage(hwndToolbar, TB_GETSTYLE, 0, 0) ^ CCS_VERT;
			SendMessage(hwndToolbar, TB_SETSTYLE, 0, (LPARAM)dwStyle);

			for (i = 0; i < nCount; i++) {
				SendMessage(hwndToolbar, TB_GETBUTTON, i, (LPARAM)&tbButton);
				dwState = (DWORD)SendMessage(hwndToolbar, TB_GETSTATE, tbButton.idCommand, 0) ^ TBSTATE_WRAP;
				SendMessage(hwndToolbar, TB_SETSTATE, tbButton.idCommand, dwState);
			}

			SendMessage(hwndToolbar, TB_AUTOSIZE, 0, 0);
			InvalidateRect(hwndToolbar, NULL, TRUE);
		}

		return 0;
	
	case WM_SIZE:
		MoveWindow(hwndToolbar, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	default:
		break;

	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

TBBUTTON構造体の最後のメンバには、テキストのアドレスを指定することができます。 ウインドウスタイルとして指定しているTBSTYLE_LISTは、ボタンのテキストをアイコンの右横に表示する意味を持ちます。 この定数を指定する場合は、ボタンのスタイルにBTNS_AUTOSIZEを指定し、 ボタンの幅が最も幅の大きなボタンに準拠しないようにしておきます。 3番目のボタンでは最初のメンバにI_IMAGENONEを指定していますが、 これはボタンのイメージを表示しないことを意味します。

「スタイル変更」というボタンが押された場合は、横型のツールバーが縦型になり、 縦型のツールバーが横型に変更されます。 処理内容は次のようになっています。

dwStyle = (DWORD)SendMessage(hwndToolbar, TB_GETSTYLE, 0, 0) ^ CCS_VERT;
SendMessage(hwndToolbar, TB_SETSTYLE, 0, (LPARAM)dwStyle);

for (i = 0; i < nCount; i++) {
	SendMessage(hwndToolbar, TB_GETBUTTON, i, (LPARAM)&tbButton);
	dwState = (DWORD)SendMessage(hwndToolbar, TB_GETSTATE, tbButton.idCommand, 0) ^ TBSTATE_WRAP;
	SendMessage(hwndToolbar, TB_SETSTATE, tbButton.idCommand, dwState);
}

SendMessage(hwndToolbar, TB_AUTOSIZE, 0, 0);
InvalidateRect(hwndToolbar, NULL, TRUE);

ツールバーが縦型であるかどうかは、ウインドウスタイルにCCS_VERTが含まれるかどうかで決定します。 よって、TB_GETSTYLEでウインドウスタイルを取得し、この結果とCCS_VERTとの排他的論理和を とった値をTB_SETSTYLEで設定すればよいことになります。 また、ツールバーが縦型の場合はボタンの状態にTBSTATE_WRAPが含まれなければならないため、 これについても同じように排他的論理和をとることになります。 ただし、TB_SETSTATEは目的のボタンをインデックスではなくIDで識別するため、 インデックスからボタンの情報を取得できるTB_GETBUTTONを送り、 取得したTBBUTTON構造体のidCommandを参照することになります。 ツールバーのスタイルを変更した場合はサイズ変更も必要になるため、TB_AUTOSIZEをツールバーに送るようにします。 InvalidateRectを呼び出しているのは前のスタイルの跡を残さないためです。


戻る