第72章 プログレスバー


今回は、プログレスバーの取り扱いについて解説します。 プログレスバーとは、アプリケーションのインストールの時などに よく見かけます。作業がどの位進んでいるかを表示するものです。
今回は、ダイアログボックスにプログレスバーを付けてみます。 VC++の場合、「ダイアログの新規作成」のとき、コントロールとして 「プログレスバー」のアイコンが出てきます。ボタンなどを 付けるのと同じ要領で任意の場所に、任意の大きさで付けることができます。

1.コモンコントロールの準備 2.PBM_SETRANGメッセージを送信して、範囲を指定する 3.PBM_SETSTEPを送信して、1ステップの増分を指定 4.PBM_STEPITを送信して1ステップだけ増加させる

たったこれだけです。この方法は1回の増加分が決まっている方法です。

PBM_SETRANGE wParam = 0; lParam = MAKELPARAM(nMinRange, nMaxRange);

これで、プログレスバーの範囲を決めます。 デフォルトでは0から100までとなっています。

PBM_SETSTEP wParam = (WPARAM) nStepInc; lParam = 0;

これで、1回の増分を指定します。

PBM_STEPIT wParam = 0; lParam = 0;

これを送信すると1ステップ分だけ進みます。 満タンになったときはまた、0から始まります。

では、さっそくサンプルのプログラムを見てみましょう。 この例では、SetTimer関数を使ってWM_TIMERメッセージを 受け取る度にプログレスバーを進ませるようにしました。

// prog01.rcの一部 自分で作るときはwindows.hと自前のヘッダーファイルを // 忘れないでください。 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "オプション(&O)" BEGIN MENUITEM "ダイアログ(&D)", IDM_DLG END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 187, 81 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "プログレスバー" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,60,50,14 PUSHBUTTON "キャンセル",IDCANCEL,130,60,50,14 CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",WS_BORDER, 26,16,137,15 LTEXT "0%",IDC_STATIC,22,7,12,8 LTEXT "100%",IDC_STATIC,150,7,22,8 LTEXT "現在",IDC_STATIC,56,42,15,8 LTEXT "0",IDC_MYSTATIC,83,41,12,8 LTEXT "%です",IDC_STATIC,108,42,21,8 END

自分でリソース・スクリプトを作る人はこれにwindows.hと自前のヘッダーファイル (シンボル定義)のインクルードをしてください。

// prog01.cpp #define STRICT #include <windows.h> #include <commctrl.h> #include "resource.h" #define ID_MYTIMER 32767 #define PB_MIN 0 #define PB_MAX 100 #define PB_STEP 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); void SetProgBar(HWND); int iProg; // 現在のプログレスバーの位置 char szClassName[] = "prog01"; //ウィンドウクラス 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; }

いつもと代わり映えしませんが、PB_MIN, PB_MAX, PB_STEP などは筆者が勝手に定義した数値です。後でメッセージと 間違えないでください(間違える人はいないか・・ (^-^;) )。

//ウィンドウ・クラスの登録 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 = "MYMENU"; //メニュー名 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; HINSTANCE hInst; switch (msg) { case WM_CREATE: InitCommonControls(); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0L); break; case IDM_DLG: hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); break; } break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }

親ができたらすぐに(WM_CREATE)コモンコントロールを初期化します。 メニューからIDM_DLGが選ばれたら、ダイアログボックスを表示します。

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { char str[16]; switch (msg) { case WM_INITDIALOG: SetProgBar(hDlg); SetTimer(hDlg, ID_MYTIMER, 1000, NULL); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: iProg = 0; KillTimer(hDlg, ID_MYTIMER); EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: iProg = 0; SendMessage(GetDlgItem(hDlg, IDC_PROGRESS1), PBM_SETPOS, (WPARAM)0, 0); return TRUE; } return FALSE; case WM_TIMER: SendMessage(GetDlgItem(hDlg, IDC_PROGRESS1), PBM_STEPIT, 0, 0); iProg += PB_STEP; if (iProg > 100) { iProg = 0; SendMessage(GetDlgItem(hDlg, IDC_PROGRESS1), PBM_SETPOS, 0, 0); } _itoa(iProg, str, 10); SetWindowText(GetDlgItem(hDlg, IDC_MYSTATIC), (LPCTSTR)str); return TRUE; } return FALSE; }

ダイアログボックスができたらすぐに(WM_INITDIALOG) 自作のSetProgBar関数を呼んで、範囲とステップを 指定します。また、タイマーをセットします。

OKボタンが押されたら、iProg(プログレスバーの位置を 記憶しておく変数)を0にします。0にしておかないと このプログラムの場合、iProgはグローバル変数なので次回 プログレスバーが出たときに0から始まらなくなります。

キャンセルボタンが押されたら、iProgを0に戻して プログレスバーを0位置に設定します。

PBM_SETPOS wParam = (WPARAM) nNewPos; lParam = 0;

WM_TIMERメッセージを捕まえたら、PBM_STEPITで1ステップ 進ませます。満タンになったらiProgを0に戻します。 また、iProgをIDC_MYSTATICコントロールに表示します。

void SetProgBar(HWND hDlg) { HWND hProg; hProg = GetDlgItem(hDlg, IDC_PROGRESS1); SendMessage(hProg, PBM_SETRANGE, (WPARAM)0, MAKELPARAM(PB_MIN, PB_MAX)); SendMessage(hProg, PBM_SETSTEP, (WPARAM)PB_STEP, 0); return; }

プログレスバーの範囲とステップを指定する関数を 独立して作ってみました。

今回は、簡単でした。 プログレスバーをダイアログボックスにではなく 直接親ウィンドウに貼り付けるにはどうすれば よいのでしょうか。例によってCreateWindowEx 関数を使います。ウィンドウクラスはPROGRESS_CLASS にします。後は、もうわかりますね。


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

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