ステータスバー

ステータスバーは、ウィンドウの下部に表示される、情報を表示するための棒状のコントロールです。
ツールバーと同じくコモンコントロールの一種です。
ステータスバー

コモンコントロールについてはツールバーのページを参照してください。
INITCOMMONCONTROLSEX構造体dwICCメンバは、ツールバーと同じくICC_BAR_CLASSESを指定することで使用できます。

ステータスバーの作成

ステータスバーはCreateWindowEx関数で、ウィンドウスタイルにSTATUSCLASSNAMEという定数を指定することで作成できます。
この定数の中身は"msctls_statusbar32"という文字列です。

ウィンドウスタイルはWS_CHILDWS_VISIBLEのほか、CCS_BOTTOMSBARS_SIZEGRIPの二つも指定します。

CCS_BOTTOMはコモンコントロールに共通のウィンドウスタイルで、ウィンドウの下部にコントロールを表示するという意味です。
位置指定のスタイルを何も指定しない場合はウィンドウの上部に表示されます。
(CCS_TOPを指定するのと同じ)

SBARS_SIZEGRIPは、ステータスバーの右下にウィンドウサイズ調整のグリップが表示されます。
このスタイルを指定しなくてもウィンドウサイズは調整できますが、マウス入力を受け付ける領域が少し広くなり操作しやすくなります。


HWND hStatusbar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
	WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP,
	0, 0, 0, 0,
	hWnd, NULL, hInst, NULL);

SB_SIMPLEメッセージ

ステータスバーは、単純なテキストひとつだけを表示する簡易モード(シンプルモード)と、いくつかのパーツに分割して異なる情報を同時に表示できる分割モードがあります。
モードはステータスバーにSB_SIMPLEメッセージを送信することで切り替えることができます。

WPARAMTRUEを指定すると簡易モード、FALSEを指定すると分割モードに設定されます。
LPARAMは使用しないので0を指定します。

ここでは簡易モードに設定します。


SendMessage(hStatusbar, SB_SIMPLE, TRUE, 0);

SB_SETTEXTメッセージ

ステータスバーに文字列を設定するにはSB_SETTEXTメッセージを使用します。

WPARAMは、下位ワードの下位バイト(LOBYTE、下位ワードではない)に、テキストを設定するパーツのインデックス(番号)を指定します。
簡易モードの場合、ここにはSB_SIMPLEIDという定数を指定します。
下位ワードの上位バイト(HIBYTE)には、ステータスバーの描画方法を示す以下の定数のいずれかを指定します。
WPARAMの上位ワードは無視されます。

定数 説明
0 窪んだ罫線
ウィンドウ領域より低く見える
SBT_NOBORDERS 罫線なし
SBT_OWNERDRAW オーナードロー
簡易モードでは使用できない
SBT_POPOUT 膨らんだ罫線
ウィンドウ領域より高く見える
SBT_RTLREADING テキスト方向を親ウィンドウとは逆にする
SBT_NOTABPARSING タブ文字を無視する

LPARAMには表示したい文字列を指定します。

WPARAMの指定がなんだかややこしく見えますが、それぞれの値をビットOR演算子でつなげるだけです。


SendMessage(
	hStatusbar,
	SB_SETTEXT,
	SB_SIMPLEID | SBT_NOBORDERS,
	(LPARAM)L"表示したいテキスト");

定数SB_SIMPLEIDは「0xff」(255)と定義されています。
パーツ数の指定は1バイトの情報で行うので、パーツは最大で255個までということになります。

上表で説明した描画指定の定数は、下位バイトは全て0で上位バイトに値が設定されています。
例えば定数SBT_NOBORDERSは「0x0100」と定義されています。
「0x00ff」と「0x0100」をビットOR演算すれば「0x01ff」ですから、互いに値が干渉しないように定義されています。

正式に定義する場合はLOBYTEマクロとHIBYTEマクロ、およびMAKEWORDマクロを使用して以下のように記述します。
(得られる値は同じです)


SendMessage(
	hStatusbar,
	SB_SETTEXT,
	MAKEWORD(LOBYTE(SB_SIMPLEID), HIBYTE(SBT_NOBORDERS)),
	(LPARAM)L"テキスト");

WM_SIZEメッセージ

ここまでの手順でステータスバーにテキストが表示されますが、ウィンドウサイズを変更したときにステータスバーのサイズは自動で変更されません。
サイズの調整は親ウィンドウでWM_SIZEメッセージが処理されるとき、ステータスバーにWM_SIZEメッセージを送信します。
パラメーター(WPARAM、LPARAM)はそのまま渡します。


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

	switch (message)
	{
	case WM_SIZE:
		SendMessage(hStatusbar, WM_SIZE, wParam, lParam);
		break;
	//以降省略

サンプルコード

全体のサンプルコードです。


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

#include <windows.h>
#include <strsafe.h>

#include <commctrl.h>

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

//ステータスバーを作成する
HWND CreateStatusbar(HWND hWnd)
{
	//コモンコントロールの初期化
	INITCOMMONCONTROLSEX icc;
	icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
	icc.dwICC = ICC_BAR_CLASSES;
	InitCommonControlsEx(&icc);

	//ステータスバー作成
	HWND hStatusbar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
		WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP,
		0, 0, 0, 0,
		hWnd, NULL, hInst, NULL);
	
	//簡易モードを設定
	SendMessage(hStatusbar, SB_SIMPLE, TRUE, 0);

	return hStatusbar;
}

#define BUFFERSIZE 256

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

	static int clickCount;
	static WCHAR text[BUFFERSIZE];

	switch (message)
	{
	case WM_CREATE: //ウィンドウの作成
		//ステータスバー作成
		hStatusbar = CreateStatusbar(hWnd);

		//ステータスバーにテキストを設定
		SendMessage(hStatusbar, SB_SETTEXT, SB_SIMPLEID | 0, (LPARAM)L"クリック数: 0");
		break;

	case WM_SIZE: //ウィンドウサイズ変更
		SendMessage(hStatusbar, WM_SIZE, wParam, lParam);
		break;

	case WM_LBUTTONUP:
		StringCchPrintf(text, BUFFERSIZE, L"クリック数: %d", ++clickCount);
		SendMessage(hStatusbar, SB_SETTEXT, SB_SIMPLEID | 0, (LPARAM)text);
		break;

	case WM_RBUTTONUP:
		clickCount = 0;
		SendMessage(hStatusbar, SB_SETTEXT, SB_SIMPLEID | 0, (LPARAM)L"クリック数: 0");
		break;

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

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

このコードはウィンドウ上をクリックした回数をステータスバーに表示します。
右クリックで回数をリセットします。
ステータスバーのサンプル

分割モード

ステータスバーの領域を分割するにはSB_SIMPLEメッセージのWPARAMにFALSEを指定して送信し、分割モードに設定します。

SB_SETPARTS

次に、SB_SETPARTSメッセージでパーツ数とパーツサイズを設定します。

WPARAMはパーツ数を指定します。
パーツ数は255以下である必要があります。

LPARAMは各パーツのサイズを示す整数値の配列を指定します。
配列の要素数はパーツと同じだけ用意し、要素の数値はパーツの右端の位置を意味します。
要素に-1を指定すると、右端位置はウィンドウの右端に設定されます。


//分割モードを設定
SendMessage(hStatusbar, SB_SIMPLE, FALSE, 0);

//パーツ数の指定
int sbSizes[3] = { 100, 250, -1 };
SendMessage(hStatusbar, SB_SETPARTS, 3, (LPARAM)sbSizes);

この例では3つのパーツに分割しています。
サイズは左から「100」「150」「ウィンドウサイズ - 250」となり、一番右のパーツだけ可変サイズになります。

最後に各パーツに文字列を設定します。
SB_SETTEXTメッセージWPARAMで文字列を設定するパーツのインデックスを指定します。


SendMessage(hStatusbar, SB_SETTEXT, 0 | 0, (LPARAM)L"左端");
SendMessage(hStatusbar, SB_SETTEXT, 1 | 0, (LPARAM)L"真ん中");
SendMessage(hStatusbar, SB_SETTEXT, 2 | 0, (LPARAM)L"右端");

パーツ数を変更すると設定していたテキストは消去されるので注意してください。
(パーツのサイズだけを変更する場合は消去されません)

サンプルコード

全体のサンプルコードです。


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

#include <windows.h>
#include <strsafe.h>

#include <commctrl.h>

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

//ステータスバーを作成する
HWND CreateStatusbar(HWND hWnd)
{
	//コモンコントロールの初期化
	INITCOMMONCONTROLSEX icc;
	icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
	icc.dwICC = ICC_BAR_CLASSES;
	InitCommonControlsEx(&icc);

	//ステータスバー作成
	HWND hStatusbar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
		WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP,
		0, 0, 0, 0,
		hWnd, NULL, hInst, NULL);
	
	//分割モードを設定
	SendMessage(hStatusbar, SB_SIMPLE, FALSE, 0);

	//パーツ数の指定
	//実際の位置はWM_SIZEメッセージで処理する
	int sbSizes[3] = { 0, 0, 0 };
	SendMessage(hStatusbar, SB_SETPARTS, 3, (LPARAM)sbSizes);

	return hStatusbar;
}

#define BUFFERSIZE 256

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

	static int clickCount;
	static WCHAR text[BUFFERSIZE];

	int sbSizes[3];

	switch (message)
	{
	case WM_CREATE: //ウィンドウの作成
		//ステータスバー作成
		hStatusbar = CreateStatusbar(hWnd);

		//ステータスバーにテキストを設定
		SendMessage(hStatusbar, SB_SETTEXT, 0 | 0, (LPARAM)L"左端");
		SendMessage(hStatusbar, SB_SETTEXT, 1 | 0, (LPARAM)L"真ん中");
		SendMessage(hStatusbar, SB_SETTEXT, 2 | 0, (LPARAM)L"右端");
		break;

	case WM_SIZE: //ウィンドウサイズ変更
		SendMessage(hStatusbar, WM_SIZE, wParam, lParam);

		//パーツの位置を設定
		sbSizes[0] = LOWORD(lParam) - 200;
		sbSizes[1] = LOWORD(lParam) - 100;;
		sbSizes[2] = -1;
		SendMessage(hStatusbar, SB_SETPARTS, 3, (LPARAM)sbSizes);
		break;

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

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

ウィンドウサイズ変更時にステータスバーの各パーツのサイズも調整したいので、WM_SIZEメッセージ処理内でSB_SETPARTSメッセージを送信しています。
WM_SIZEメッセージでは、LPARAMの下位ワードがウィンドウの横幅なので、この値を元に各パーツのサイズを決定します。
このコードでは左端パーツサイズは可変、真ん中と右端パーツのサイズを「100」にしています。
ステータスバーを分割するサンプル