第184章 レバーコントロールにツールバーを置く


レバーコントロールに置く代表的なものは何と言ってもツールバーでしょう。 今までの知識ですぐにでもツールバーを置けそうな気がします。しかし、 実際にプログラムするとちょっとした事でうまく表示されず苦労するものです。



左の図のようなツールバーをレバーコントロールに乗せます。 プログラム起動時にツールバーは新しい列に行くようにしています。 もちろんユーザーがこれを1列にしたり、3列にしたりすることもできます。



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

// rebar02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Toolbar // IDR_TOOLBAR1 TOOLBAR DISCARDABLE 16, 15 BEGIN BUTTON IDM_KUME BUTTON IDM_I BUTTON IDM_YASU BUTTON IDM_TAKA END ///////////////////////////////////////////////////////////////////////////// // // Bitmap // IDR_TOOLBAR1 BITMAP DISCARDABLE "toolbar1.bmp"

リソースエディタで4つのボタンを作ると上のようなリソース・スクリプトが できます。適当な図柄のボタンを作っておいてください。ボタンのIDなどは 上のスクリプトと同じにしておいて下さい。リソースエディタを使わない人は (16*4)*15のサイズのビットマップ(toolbar1.bmp)を自分で作る必要があります。

// rebar02.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <commctrl.h> #include "resource.h" #define ID_BUT1 100 #define ID_COMBO 101 #define ID_TOOLBAR 102 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HWND MakeMyRebar(HWND); HWND MakeMyCombo(HWND); HWND MakeMyTool(HWND); char szClassName[] = "rebar02"; //ウィンドウクラス HINSTANCE hInst; TBBUTTON tb[] = { {0, IDM_KUME, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, {1, IDM_I, TBSTATE_ENABLED , TBSTYLE_BUTTON, 0, 0, 0}, {2, IDM_YASU, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, {3, IDM_TAKA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0} };

このへんは特に説明は不要と思います。

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 = NULL; //メニュー名 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座標 320, //幅 150, //高さ 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, no; INITCOMMONCONTROLSEX ic; static HWND hRebar, hBut, hCombo, hTool; REBARBANDINFO rbBand; HDC hdc; PAINTSTRUCT ps; static char szStr[256]; char szData[16]; RECT rc; LPNMHDR lpnmhdr; switch (msg) { case WM_CREATE: ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES; InitCommonControlsEx(&ic); hRebar = MakeMyRebar(hWnd); ZeroMemory(&rbBand, sizeof(REBARBANDINFO)); rbBand.cbSize = sizeof(REBARBANDINFO); rbBand.fMask = RBBIM_TEXT | RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE; rbBand.fStyle = RBBS_CHILDEDGE; rbBand.cxMinChild = 0; rbBand.cyMinChild = 25; hBut = CreateWindow("BUTTON", "押す", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, hRebar, (HMENU)ID_BUT1, hInst ,NULL); rbBand.lpText = "ボタン"; rbBand.hwndChild = hBut; rbBand.cx = 100; SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); hCombo = MakeMyCombo(hRebar); rbBand.lpText = "コンボボックス"; rbBand.hwndChild = hCombo; GetWindowRect(hRebar, &rc); rbBand.cx = rc.right - rc.left - 100; SendMessage(hRebar, RB_INSERTBAND,(WPARAM)-1, (LPARAM)&rbBand); hTool = MakeMyTool(hRebar); rbBand.fStyle |= RBBS_BREAK; //バンドの列を変える rbBand.lpText = "ツールバー"; rbBand.hwndChild = hTool; GetWindowRect(hRebar, &rc); rbBand.cx = rc.right - rc.left; SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); break; case WM_SIZE: SendMessage(hRebar, WM_SIZE, wp, lp); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); GetWindowRect(hRebar, &rc); TextOut(hdc, 5, rc.bottom - rc.top + 5, szStr, strlen(szStr)); EndPaint(hWnd, &ps); break; case WM_COMMAND: switch (LOWORD(wp)) { case ID_BUT1: MessageBox(hWnd, "ボタンが押されました", "OK", MB_OK); break; case ID_COMBO: if (HIWORD(wp) == CBN_SELCHANGE) { no = SendMessage(hCombo, CB_GETCURSEL, 0, 0); SendMessage(hCombo, CB_GETLBTEXT, (WPARAM)no, (LPARAM)szData); wsprintf(szStr, "選択されているのは「%s」です", szData); InvalidateRect(hWnd, NULL, TRUE); UpdateWindow(hRebar); } break; case IDM_KUME: MessageBox(hWnd, "「粂」が押されました", "OK", MB_OK); break; case IDM_I: MessageBox(hWnd, "「井」が押されました", "OK", MB_OK); break; case IDM_YASU: MessageBox(hWnd, "「康」が押されました", "OK", MB_OK); break; case IDM_TAKA: MessageBox(hWnd, "「孝」が押されました", "OK", MB_OK); break; } break; case WM_NOTIFY: lpnmhdr = (LPNMHDR)lp; if (lpnmhdr->hwndFrom == hRebar && lpnmhdr->code == RBN_HEIGHTCHANGE) { InvalidateRect(hWnd, NULL, TRUE); UpdateWindow(hRebar); } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hBut); DestroyWindow(hCombo); DestroyWindow(hRebar); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEのところが大事です。 ツールバーを使うのでINITCOMMONCONTROLSEX構造体に ICC_BAR_CLASSESを追加するのを忘れないでください。 またツールバーを作って、その後

rbBand.fStyle |= RBBS_BREAK;

としています。これは、バンドを新しい列に作らせる為です。 後は、プログラムを見ればわかると思います。

HWND MakeMyRebar(HWND hWnd) { HWND hRebar; REBARINFO rbi; hRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | RBS_BANDBORDERS | WS_CLIPCHILDREN | CCS_NODIVIDER, 0, 0, 0, 0, hWnd, NULL, hInst, NULL); ZeroMemory(&rbi, sizeof(REBARINFO)); rbi.cbSize = sizeof(REBARINFO); SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&rbi); return hRebar; } HWND MakeMyCombo(HWND hRebar) { HWND hCombo; hCombo = CreateWindow("COMBOBOX", "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 0, 0, 0, 120, hRebar, (HMENU)ID_COMBO, hInst, NULL); SendMessage(hCombo, CB_INSERTSTRING, -1, (LPARAM)"粂井康孝"); SendMessage(hCombo, CB_INSERTSTRING, -1, (LPARAM)"粂井櫻都"); SendMessage(hCombo, CB_INSERTSTRING, -1, (LPARAM)"粂井志麻"); SendMessage(hCombo, CB_INSERTSTRING, -1, (LPARAM)"粂井ひとみ"); SendMessage(hCombo, CB_SETCURSEL, 0, 0); return hCombo; }

この2つの自作関数は前章のものと全く同じです。

HWND MakeMyTool(HWND hRebar) { HWND hTool; hTool = CreateToolbarEx(hRebar, //親ウィンドウ WS_CHILD | WS_VISIBLE | CCS_NODIVIDER | CCS_NORESIZE | TBSTYLE_FLAT, //ウィンドウスタイル ID_TOOLBAR, //ID 4, //ボタンイメージの数 hInst, //ビットマップリソースの入っているモジュール IDR_TOOLBAR1, //ビットマップリソースのID tb, //TBBUTTON構造体のアドレス 4, //ツールバーに加えるボタンの数 0, 0, 0, 0, //ボタンの幅、高さ、イメージの幅、高さ sizeof(TBBUTTON)); //TBBUTTON構造体の大きさ return hTool; }

ツールバーを作る関数です。フラットツールバーの作り方は第148章 で解説してあります。ところで通常、親ウィンドウ(メインウィンドウ)の子供としてフラットツールバーを 作る場合はCreateToolbarEx関数やCreateWindowEx関数でTBSTYLE_FLATを指定しても うまくいきません。しかし、レバーコントロールに載せる場合は大丈夫です。

さて、ツールバーのウィンドウスタイルをWS_CHILD | WS_VISIBLE | TBSTYLE_FLATにしても レバーコントロールに載せるとうまく表示されません。CCS_NORESIZEスタイルを追加する 必要があります。VC++のヘルプでは、コモンコントロールのスタイルのところに 解説が出ているので非常にわかりにくいです。コモンコントロールのスタイルには 次のようなものがあります。

CCS_NOPARENTALIGNコントロールを親ウィンドウの上端または下端に 自動的に移動するのを防ぎます。
親のサイズが変わっても親ウィンドウ内の位置を保持します。
CCS_TOPかCCS_BOTTOMが使われている時は、高さはデフォルトに調整されますが 幅や位置は変わりません。
CCS_NOMOVEYWM_SIZEメッセージに応答して水平方向の位置・サイズを変更 しますが、垂直には変化しません。
CCS_NORESIZEが使われている時はこのスタイルは適用されません。
CCS_NOMOVEXWM_SIZEメッセージに応答して垂直方向の位置・サイズを変更 しますが、水平方向には変化しません。
CCS_NORESIZEが使われている時はこのスタイルは適用されません。
CCS_NORESIZE初期サイズや新しいサイズの設定時デフォルトの幅・高さを 使いません。
その代わり作成時や、サイズ変更時に指定された幅・高さを使います。
CCS_ADJUSTABLEユーザーがツールバーをカスタマイズできるようにします。
CCS_BOTTOMコントロールを親のクライアント領域の下端に設置します。
CCS_TOPコントロールを親のクライアント領域の上端に設置します。デフォルトです。
CCS_NOHILITEコントロールの先頭に表示される1ピクセルの強調表示をしません。
SDKでは使用できません。
CCS_NODIVIDERコントロールの先頭に表示される2ピクセルの強調表示をしません。
CCS_LEFTコントロールは親ウィンドウの左側に垂直に表示されます。
CCS_RIGHTコントロールは親ウィンドウの右側に垂直表示されます。
CCS_VERTコントロールは垂直に表示されます。

いろいろなスタイルを試してみてください。中にはよく意味のわからないスタイルも あると思います。


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

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