第191章 トラックバーの情報を表示する


前章では基本的なトラックバーの作り方や取り扱い方を 示しました。今回はリソースエディタでトラックバーを作り、トラックバーの情報を ダイアログボックスとこれを呼び出した親ウィンドウのクライアント領域に リアルタイムに表示するプログラムを作ります。また、トラックバーはサブクラス化 しないで使います。



左の図のようにトラックバーは縦型にしてみました。つまみを動かすと 「現在位置」のところに現在のつまみ位置がリアルタイムに表示されます。 「範囲選択開始」ボタンをおすと範囲の選択が開始されます。 つまみを動かした後、「範囲選択終了」ボタンを押すとそこが 選択範囲の終点となります。選択範囲もリアルタイムに表示されます。



ダイアログボックス上のトラックバーの操作は、親ウィンドウ でもリアルタイムでモニタできます。



では、プログラムを見てみましょう。

ダイアログぽっくす上のトラックバーはリソースエディタで 作ります。VC++の人はトラックバーのプロパティを次のようにしてください。

「一般」ID=IDC_SLIDER1, 「可視」「タブストップ」にチェックをつけておきます。

「スタイル」方向=「垂直方向」, ポイント= 「下/右」, 「マークの設定」「選択可能」 「自動設定」にチェックをつけておきます。

「拡張スタイル」には特にチェックをつけません。

// track02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 102, 177 STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "トラックバー" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "閉じる",IDOK,44,7,50,14 CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_AUTOTICKS | TBS_VERT | TBS_ENABLESELRANGE | WS_TABSTOP,7,7,28,157 LTEXT "現在の位置:",IDC_STATIC,42,25,36,8 LTEXT "POS",IDC_POS,81,25,14,8 GROUPBOX "選択範囲",IDC_STATIC,46,40,49,57 LTEXT "終了",IDC_STATIC,49,76,15,8 LTEXT "",IDC_END,77,76,8,8 PUSHBUTTON "範囲選択開始",IDC_RANGESTART,44,105,50,14 PUSHBUTTON "範囲選択終了",IDC_RANGEEND,44,128,50,14 PUSHBUTTON "選択範囲クリア",IDC_CLEARSEL,44,151,50,14 LTEXT "開始",IDC_STATIC,49,57,15,8 LTEXT "",IDC_START,77,57,8,8 END ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "ダイアログ(&D)" BEGIN MENUITEM "トラックバー(&T)", IDM_TRACK END END

IDC_START, IDC_END, IDC_POSのスタティックコントロールに 範囲の開始位置、終了位置、現在の位置が表示されることになります。

// track02.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <commctrl.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "track02"; //ウィンドウクラス HINSTANCE hInst; int iPosStart, iPosEnd, iPos;

リソースエディタでトラックバーを 作る場合Comctl32.libのリンクは不要です。しかし、commctrl.hのインクルードは 必要です。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); 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; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるトラックバー", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 210,//幅 115,//高さ 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; INITCOMMONCONTROLSEX ic; char szStr[256]; HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_CREATE: ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_BAR_CLASSES; break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); wsprintf(szStr, "つまみ位置= %d", iPos); TextOut(hdc, 5, 5, szStr, lstrlen(szStr)); wsprintf(szStr, "選択範囲開始位置= %d", iPosStart); TextOut(hdc, 5, 25, szStr, lstrlen(szStr)); wsprintf(szStr, "選択範囲終了位置=%d", iPosEnd); TextOut(hdc, 5, 45, szStr, lstrlen(szStr)); EndPaint(hWnd, &ps); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_TRACK: DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEのところで一応コモンコントロールの初期化を しておきました。(リソースエディタで作った場合不要??)

WM_PAINTメッセージが来たらクライアント領域に トラックバーの情報を表示します。

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hTrack, hPos, hStart, hEnd, hRangeStart, hRangeEnd, hRangeClear; char szStr[16]; static HWND hParent; switch (msg) { case WM_INITDIALOG: hParent = GetParent(hDlg); hTrack = GetDlgItem(hDlg, IDC_SLIDER1); hPos = GetDlgItem(hDlg, IDC_POS); hStart = GetDlgItem(hDlg, IDC_START); hEnd = GetDlgItem(hDlg, IDC_END); hRangeStart = GetDlgItem(hDlg, IDC_RANGESTART); hRangeEnd = GetDlgItem(hDlg, IDC_RANGEEND); hRangeClear = GetDlgItem(hDlg, IDC_CLEARSEL); SendMessage(hTrack, TBM_SETRANGE, 0, MAKELPARAM(0, 100)); SendMessage(hTrack, TBM_SETTICFREQ, (WPARAM)10, 0); iPos = SendMessage(hTrack, TBM_GETPOS, 0, 0); wsprintf(szStr, "%d", iPos); SetWindowText(hPos, szStr); SetWindowText(hStart, ""); SetWindowText(hEnd, ""); EnableWindow(hRangeEnd, FALSE); EnableWindow(hRangeClear, FALSE); SetFocus(hTrack); break; case WM_VSCROLL: iPos = SendMessage(hTrack, TBM_GETPOS, 0, 0); wsprintf(szStr, "%d", iPos); SetWindowText(hPos, szStr); InvalidateRect(hParent, NULL, TRUE); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: case IDCANCEL: EndDialog(hDlg, IDOK); return TRUE; case IDC_RANGESTART: iPosStart = SendMessage(hTrack, TBM_GETPOS, 0, 0); SendMessage(hTrack, TBM_SETSELSTART, (WPARAM)FALSE, (LPARAM)iPosStart); wsprintf(szStr, "%d", iPosStart); SetWindowText(hStart, szStr); EnableWindow(hRangeStart, FALSE); EnableWindow(hRangeEnd, TRUE); InvalidateRect(hParent, NULL, TRUE); SetFocus(hTrack); return TRUE; case IDC_RANGEEND: iPosEnd = SendMessage(hTrack, TBM_GETPOS, 0, 0); if (iPosStart > iPosEnd) { MessageBox(hDlg, "範囲終了位置は開始位置より下方にして下さい", "範囲設定エラー", MB_OK); return TRUE; } SendMessage(hTrack, TBM_SETSELEND, (WPARAM)TRUE, (LPARAM)iPosEnd); wsprintf(szStr, "%d", iPosEnd); SetWindowText(hEnd, szStr); EnableWindow(hRangeStart, TRUE); EnableWindow(hRangeEnd, FALSE); EnableWindow(hRangeClear, TRUE); InvalidateRect(hParent, NULL, TRUE); SetFocus(hTrack); return TRUE; case IDC_CLEARSEL: SendMessage(hTrack, TBM_CLEARSEL, (WPARAM)TRUE, 0); iPosStart = 0; iPosEnd = 0; EnableWindow(hRangeStart, TRUE); EnableWindow(hRangeEnd, FALSE); EnableWindow(hRangeClear, FALSE); SetWindowText(hStart, ""); SetWindowText(hEnd, ""); InvalidateRect(hParent, NULL, TRUE); SetFocus(hTrack); return TRUE; } return FALSE; } return FALSE; }

ダイアログボックスのプロシージャです。

WM_INITDIALOGが来たらコントロール類の初期設定を行います。 コントロール類のウィンドウハンドルをスタティック変数に 取得しておくと後の作業が楽です。また、このプロシージャ内で 親ウィンドウのハンドルが必要なのでGetParent関数で最初に 取得しておきます。今回はトラックバーの最大、最小値を0から100までと して少し細かく設定できるようにしました。また、TBM_SETTICFREQメッセージは はメモリの頻度を指定します。

TBM_SETTICFREQ wParam = (WPARAM) wFreq; lParam = (LPARAM) 0;

wFreqにメモリのインターバルを指定します。

このプログラムではダイアログボックスが 出るたびに前回の設定は無視されて、本当の初期状態になります。 余裕のある人は、前回の設定が反映されるように書き換えてみてください。

さて、縦型スクロールバーではつまみが動かされるとその親ウィンドウに WM_VSCROLLメッセージが届きます。この時wParamの下位ワード値 に通知メッセージが含まれます。通知メッセージが TB_THUMBTRACKとTB_THUMBPOSITIONの時はwParamの上位ワード値がつまみ位置を示します。 ここでは、WM_VSCROLLが来るたびにつまみ位置をTBM_GETPOSメッセージで グローバル変数iPosに取得して親のクライアント領域を再描画しています。

「範囲選択開始」「範囲選択終了」ボタンが押されるとその時の ボタン位置を取得して範囲を設定します。親ウィンドウを再描画して 情報を更新させます。終了位置が開始位置より大きい場合はエラーメッセージを 出すようにしてあります

「選択範囲クリア」ボタンが押されたらTBM_CLEARSELメッセージで 選択範囲をクリアします。

今回はごちゃごちゃしていて少し面倒くさいプログラムでしたが プログラム的には単純でした。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

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