山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他ステータスバー
概要
ステータスバーは、下図のようなウィンドウの下部に情報を表示します。
ステータスバーは、CreateWindowEx APIを用いるか、CreateStatusWindow APIを使用します。
CreateStatusWindow APIを使用する場合は、プロジェクトにcomctl32.libを加える必要があります。
本プログラムではENABLE_FUNCマクロを定義したばあい、CreateStatusWindow APIを使用、定義しない場合はCreateStatus関数経由でCreateWindowEx APIを使用します。
ウィンドウサイズが変化した時、自動的にステータスバーの位置や大きさは変わらないのでWM_SIZEメッセージを処理する若干のコードが必要になります。
また、ステータスバー分の高さが減るので描画もそれを考慮する必要があります。面倒なのでステータスバーを除いた高さのウィンドウを新たに作成し描画するのが簡単かと思いますが、本プログラムは複雑な描画をするわけではないのでステータスバーを差し引いて描画しています。 ウィンドウにはクライアントサイズの半分の楕円を描画、 ステータスバーにはウィンドウサイズを表示してみました。
ステータスバーは、CreateWindowEx APIを用いるか、CreateStatusWindow APIを使用します。
CreateStatusWindow APIを使用する場合は、プロジェクトにcomctl32.libを加える必要があります。
本プログラムではENABLE_FUNCマクロを定義したばあい、CreateStatusWindow APIを使用、定義しない場合はCreateStatus関数経由でCreateWindowEx APIを使用します。
ウィンドウサイズが変化した時、自動的にステータスバーの位置や大きさは変わらないのでWM_SIZEメッセージを処理する若干のコードが必要になります。
また、ステータスバー分の高さが減るので描画もそれを考慮する必要があります。面倒なのでステータスバーを除いた高さのウィンドウを新たに作成し描画するのが簡単かと思いますが、本プログラムは複雑な描画をするわけではないのでステータスバーを差し引いて描画しています。 ウィンドウにはクライアントサイズの半分の楕円を描画、 ステータスバーにはウィンドウサイズを表示してみました。
テスト環境
コンパイラ
Visual C++ 2008 Standard 32/64bitVisual C++ 2013 Express 32/64bit
プロジェクトの作成
Win32プロジェクト Windowsアプリケーション実行環境
Windows 7 EnterPrise Service Pack 1 64bitWindows 10 Home 32/64bit
プログラムソースの概要
_tWinMain関数
Windowsから最初に_tWinMain関数が呼び出されます。 ウィンドウを作成する場合は、RegisterClass APIによりウィンドウクラスを定義してからCreateWindow APIを呼び出しウィンドウを作成します。 Windowsは入力等のイベントが発生するとアプリケーションにメッセージを送付します。 メッセージはキューに保管されます。アプリケーションはメッセージを取り出し、該当ウィンドウにメッセージを配信します。 メッセージの取り出しから配信までループで処理を行いウィンドウから終了メッセージが届くと、ループを抜けるように記述します。 これらの一連の処理は、通常にCreateWindow APIの後に記述しこれをメッセージループと呼んでいます。 詳細は以下を参照してください。メッセージループについて
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)ウィンドウプロシージャー
RegisterClass APIにより登録することによりWindowsから呼び出されます。 第2引数にメッセージの種類が格納されていますので、switchステートメントによりメッセージごとの処理を振り分けます。 自分で処理しないメッセージはDefWindowProc APIに渡せばWindowsが標準的な処理を行ってくれます。case WM_CREATE:
ウィンドウの初期化時に呼び出されます。CreateStatusWindow API又はCreateStatus関数を呼び出しステータスバーを作成しステータスバーのハンドルを取得します。ハンドルは後で使用するのでスタティック変数に保存しておきます。
ステータスバーにSB_SETPARTSメッセージを送信し、ステータスバーの分割数と各区画の右座標を設定します。
右座標ですので大きさを設定する配列の値は順番に大きくなっていなければ表示されません。最後に-1を設定するとウィンドウの右端という意味になります。
GetWinRect関数を呼び出しクライアント領域の大きさを取得しスタティック変数に保存しておきます。
ShowWindow APIを呼び出しステータスバーの表示を更新します。
case WM_SIZE:
ウィンドウのサイズが変更されたときに呼び出されます。ウィンドウサイズが変更されたときステータスバーの位置や大きさは自動的に変更されません。
ステータスバーにWM_SIZEメッセージを渡せば位置や大きさを調整してくれます。
本プログラムでは、ステータスバーにウィンドウサイズを表示していますので、SB_SETTEXTメッセージをステータスバーに送信することにより文字を表示させます。
クライアント領域は、ステータスバーの高さを引いた大きさになりますので、GetWinRectでステータスバーの大きさを取得しステータスバーを除いたウィンドウサイズを計算しスタティック変数wx,wyに保存します。
case WM_DESTROY:
ウィンドウが閉じるときに呼び出されます。 PostQuitMessage APIにより終了コードを指定して、ウィンドウプロシージャーを終了させます。case WM_CLOSE:
プログラムを終了するときに呼び出されます。DestroyWindow APIによりステータスバーとウィンドウを閉じます。
case WM_PAINT:
ウィンドウを再描画する必要があるときに呼び出されます。 他のウィンドウに隠れ再びフォアグラウンドになった場合などウィンドウの再描画はWindowsが面倒を見ないのでプログラマの仕事となっています。 BeginPaint APIを呼び出して、描画に必要なデバイスコンテキストのハンドルを取得します。 BeginPaint APIの第2引数のポインタにはPAINTSTRUCT構造体のポインタを渡します。 BeginPaint API終了後、PAINTSTRUCT構造体には再描画が必要な領域の座標等の値が格納されています。 Ellipse APIによりウィンドウサイズの半分の大きさの楕円を描画します。プログラムソース
statusbar1.cpp
// ステータスバーの表示
// Visual C++ 2008/2013 Express 32/64bit UNICODE/マルチバイト
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <tchar.h>
// CreateStatusWindowを使用する場合は以下の定義を有効にする。使用しない場合はコメントアウトする。
#define ENABLE_FUNC 1
#ifdef ENABLE_FUNC
#pragma comment(lib,"comctl32.lib")
#else
HWND CreateStatus(HWND hWnd);
#endif
TCHAR szClassName[] = _TEXT("StatusBar1"); //ウィンドウクラス
#define ID_STATUS 100 // ステータスバーのID
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void GetWinRect(HWND hWnd, int *x, int *y);
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst,
TCHAR* lpszCmdLine, int nCmdShow){
HWND hWnd;
MSG lpMsg;
WNDCLASS myProg;
if (!hPreInst) {
myProg.style = CS_HREDRAW | CS_VREDRAW;
myProg.lpfnWndProc = WndProc;
myProg.cbClsExtra = 0;
myProg.cbWndExtra = 0;
myProg.hInstance = hInstance;
myProg.hIcon = NULL;
myProg.hCursor = LoadCursor(NULL, IDC_ARROW);
myProg.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
myProg.lpszMenuName = NULL;
myProg.lpszClassName = szClassName;
if (!RegisterClass(&myProg))
return FALSE;
}
hWnd = CreateWindow(szClassName,
TEXT("StatusBar1"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&lpMsg, NULL, 0, 0)){
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
return int(lpMsg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
HPEN hPen, hOldPen;
HBRUSH hBrush, hOldBrush;
HDC hdc;
TCHAR buf[64];
PAINTSTRUCT ps;
static HWND hStatus;
static int wx, wy;
int sx, sy;
int sb_size[] = { 100, 200, -1 };
switch (msg) {
case WM_CREATE:
#ifdef ENABLE_FUNC
hStatus = CreateStatusWindow(WS_CHILD | SBARS_SIZEGRIP | CCS_BOTTOM | WS_VISIBLE, _TEXT(""), hWnd, ID_STATUS);
#else
hStatus = CreateStatus(hWnd);
#endif
SendMessage(hStatus, SB_SETPARTS, (WPARAM)3, (LPARAM)(LPINT)sb_size);
GetWinRect(hWnd, &wx, &wy);
ShowWindow(hStatus, SW_SHOW);
break;
case WM_SIZE:
wx = LOWORD(lParam);
wy = HIWORD(lParam);
GetWinRect(hStatus, &sx, &sy);
wy -= sy;
SendMessage(hStatus, WM_SIZE, wParam, lParam);
_stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("%.4d"), wx);
SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | 0, (LPARAM)(LPSTR)buf);
_stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("%.4d"), wy);
SendMessage(hStatus, SB_SETTEXT, (WPARAM)1 | 0, (LPARAM)(LPSTR)buf);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
DestroyWindow(hStatus);
DestroyWindow(hWnd);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
hOldPen = (HPEN)SelectObject(hdc, hPen);
hBrush = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0));
hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Ellipse(hdc, wx/4, wy/4, wx*3/4, wy*3/4);
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);
DeleteObject(hPen);
DeleteObject(hBrush);
EndPaint(hWnd, &ps);
break;
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0);
}
void GetWinRect(HWND hWnd, int *x, int *y){
RECT rc;
GetClientRect(hWnd, &rc);
*x = rc.right - rc.left;
*y = rc.bottom - rc.top;
return;
}
#ifndef ENABLE_FUNC
HWND CreateStatus(HWND hWnd){
HINSTANCE hInst;
hInst = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
HWND hStatus = CreateWindowEx(
0,
STATUSCLASSNAME,
NULL,
WS_CHILD | SBARS_SIZEGRIP | CCS_BOTTOM | WS_VISIBLE,
0,
0,
0,
0,
hWnd,
(HMENU)ID_STATUS,
hInst,
NULL);
return hStatus;
}
#endif
ソースファイルと実行ファイルのダウンロード
Copyright (C) 2012 山本ワールド All Rights Reserved.