第58章 ステータスバーを作る その2


前章では、シンプルなステータスバーを作りました。 今回は、より一般的なステータスバーを作ります。 ステータスバーの中にいくつかの小部屋(パーツ)を作ります。 作り方は簡単です。

まず、int型配列を用意します。そして、たとえば 各区画の長さが50,60,70のものを作りたいとします。 その場合、

int sb_size[] = {50, 110, 180};

というように初期化します。そして、SB_SETPARTSメッセージを 送信します。

SB_SETPARTS wParam = (WPARAM) nParts; lParam = (LPARAM) (LPINT) aWidths;

nPartsは区画の数、aWidthsは、配列のポインタを表します。

各区画に表示したいときはSB_SETTEXTメッセージを使います。 このメッセージについての解説はすでに前章で行っていますので 参照してください。

今回は、ステータスバーに3つの小区画を作って、 それぞれに、日付、曜日、時刻を表示させるプログラムを作ってみます。 前回とほとんど同じなのでソースを見ればわかると思います。

// status02.cpp #define STRICT #include <windows.h> #include <commctrl.h> #include <string.h> #define ID_STATUS 100 #define ID_MYTIMER 32767 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HWND CreateMyStatusbar(HWND); //ステータスバー作成関数 char szClassName[] = "status02"; //ウィンドウクラス int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!hPrevInst) { if (!InitApp(hCurInst)) return FALSE; } if (!InitInstance(hCurInst, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

#include <commctrl.h>を忘れずに入れてください。 また、comctl32.libをプロジェクトに参加させておいてください。

//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); }

これは、いつもと同じです。

//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるステータスバー",//タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

これも毎度おなじみのものです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static HWND hStatus; SYSTEMTIME STime; char str0[64], str1[64], str2[64]; char *str0_org = "%4d年%2d月%2d日"; char *str2_org = "%2d時%2d分%2d秒"; static char *yobi[] = {"日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"}; switch (msg) { case WM_CREATE: hStatus = CreateMyStatusbar(hWnd); SetTimer(hWnd, ID_MYTIMER, 500, NULL); break; case WM_SIZE: SendMessage(hStatus, WM_SIZE, wp, lp); break; case WM_TIMER: GetLocalTime(&STime); wsprintf(str0, str0_org, STime.wYear, STime.wMonth, STime.wDay); SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | 0, (LPARAM)(LPSTR)str0); strcpy(str1, yobi[STime.wDayOfWeek]); SendMessage(hStatus, SB_SETTEXT, (WPARAM)1 | 0, (LPARAM)(LPSTR)str1); wsprintf(str2, str2_org, STime.wHour, STime.wMinute, STime.wSecond); SendMessage(hStatus, SB_SETTEXT, (WPARAM)2 | SBT_POPOUT, (LPARAM)(LPSTR)str2); break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: KillTimer(hWnd, ID_MYTIMER); PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }

親ウィンドウが作られたらすぐに(WM_CREATE)ステータスバー作成 関数(自作)とSetTimer関数を呼び出します。

WM_SIZEメッセージが来たらそっくりそのまま、 ステータスバー・ウィンドウに通知します。

WM_TIMERメッセージが来たら現在時刻、日付等を取得します。
GetLocalTime関数については第34章を参照してください。

ステータスバーの最初の区画に文字列を表示するには、

SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | 0, (LPARAM)(LPSTR)str0);

2番目の区画に表示するには

SendMessage(hStatus, SB_SETTEXT, (WPARAM)1 | 0, (LPARAM)(LPSTR)str1);

というように、SendMessage関数の第3引数で表します。(「|」記号の前)これから わかるように0番目から始まります。

表示する文字をくぼみにするときは第3引数の「|」記号の後ろを0にします。 浮き上がらせる場合はSBT_POPOUTにします。

SetTimer関数を使い終わったら必ずKillTimer関数で殺しておいてください。 この場合、PostQuit関数の呼ばれる直前で呼び出しています。

HWND CreateMyStatusbar(HWND hWnd) { HWND hSBWnd; HINSTANCE hInst; int sb_size[] = {100, 200, 300}; InitCommonControls(); hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); hSBWnd = CreateWindowEx( 0, //拡張スタイル STATUSCLASSNAME, //ウィンドウクラス NULL, //タイトル WS_CHILD | SBS_SIZEGRIP, //ウィンドウスタイル 0, 0, //位置 0, 0, //幅、高さ hWnd, //親ウィンドウ (HMENU)ID_STATUS, //ウィンドウのID hInst, //インスタンスハンドル NULL); SendMessage(hSBWnd, SB_SETPARTS, (WPARAM)3, (LPARAM)(LPINT)sb_size); ShowWindow(hSBWnd, SW_SHOW); return hSBWnd; }

コモンコントロールを使うときは

InitCommonControls();を忘れないでください。 前回同様CreateWindowEx関数で、ステータスバーを作ります。 また、小区画の長さを格納するint型配列を用意しておきます。 上の場合、3つの区画の長さはどれも100にしてあります。

ステータスバーを作ったらSB_SETPARTSメッセージを送って パーツを作ります。

上の例の場合ウィンドウのスタイルにWS_VISIBLEを入れていないので 後からShowWindow関数を呼んで見えるようにしています。

最後の時刻の小区画は浮き上がって見えています。(SBT_POPOUT)


[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Jul/18/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。