モノクロで描画されたフラットツールバーですが・・・
マウスでポイントすると、左の図のようにカラー表示になります。
たったこれだけで実現します。ちょっと気をつけなくておくことは、 ホットイメージを作る時透明化したい部分の色を決めて、その色で 塗りつぶしておくことです。ここでは、丸や三角形の外部を「白」で 塗りつぶしておきました。これをしておかないとシステムの配色が 変えられた時にみっともない状態になります。1.フラットツールバーを作る 2.ホットイメージをリソースエジタで作る(ツールバーとして作ると簡単) 3.ImageList_LoadBitmapマクロでホットイメージからイメージリストを作る 4.ツールバーに対してTB_SETHOTIMAGELISTメッセージを送る
では、プログラムを見てみましょう。
IDR_TOOLBAR1が通常時のツールバーです。IDR_TOOLBAR2が ホット時のツールバーです。ホット時のボタンのID(IDM_MARUなど)は実際には 使われないので何でもよいです。// newtool1.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Toolbar // IDR_TOOLBAR2 TOOLBAR DISCARDABLE 16, 15 BEGIN BUTTON IDM_MARU BUTTON IDM_SANKAKU BUTTON IDM_SHIKAKU END IDR_TOOLBAR1 TOOLBAR DISCARDABLE 16, 15 BEGIN BUTTON IDM_MARU BUTTON IDM_SANKAKU BUTTON IDM_SHIKAKU END ///////////////////////////////////////////////////////////////////////////// // // Bitmap // IDR_TOOLBAR2 BITMAP DISCARDABLE "toolbar2.bmp" IDR_TOOLBAR1 BITMAP DISCARDABLE "toolbar1.bmp"
commctrl.hのインクルードを忘れないでください。また、プロジェクトに Comctl32.libをリンクするのを忘れないでください。// newtool1.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <commctrl.h> #include "resource.h" #define ID_TOOL 1 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HWND CreateMyToolbar(HWND); char szClassName[] = "newtool1"; //ウィンドウクラス HINSTANCE hInst; HIMAGELIST hImage; TBBUTTON tb[] = { {0, IDM_MARU, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, {1, IDM_SANKAKU, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, {2, IDM_SHIKAKU, 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座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }
WM_CREATEのところでちょっと注意しなくてはいけません。 イメージリストを使うのでコモンコントロールの初期化が 必要ですがINITCOMMONCONTROLSEX 構造体のdwICCメンバに ICC_IMAGELIST_CLASSESなどというのは存在しません。 仕方がないので古い関数であるInitCommonControlsを呼んでいます。 その後、新しい関数でツールバーの初期化をしています。 (これでよいのかどうかは不明。こうするより他に方法がない。)//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static HWND hTool; INITCOMMONCONTROLSEX ic; switch (msg) { case WM_CREATE: InitCommonControls(); ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_BAR_CLASSES; InitCommonControlsEx(&ic); hTool = CreateMyToolbar(hWnd); break; case WM_SIZE: SendMessage(hTool, WM_SIZE, wp, lp); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_MARU: MessageBox(hWnd, "「丸」が押されました", "丸", MB_OK); break; case IDM_SANKAKU: MessageBox(hWnd, "「三角」が押されました", "三角", MB_OK); break; case IDM_SHIKAKU: MessageBox(hWnd, "「四角」が押されました", "四角", MB_OK); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { ImageList_Destroy(hImage); DestroyWindow(hTool); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
終了時にイメージリストの破棄を忘れないでください。 イメージリストについて忘れてしまった方は 第70章を参照して下さい。
さて、これが今回のメインの部分です。HWND CreateMyToolbar(HWND hWnd) { HWND hTool; LONG lStyle; hTool = CreateToolbarEx(hWnd, //親ウィンドウ WS_CHILD | WS_VISIBLE | CCS_NODIVIDER, //ウィンドウスタイル ID_TOOL, //コントロールID 3, //ボタンイメージの数 hInst, //インスタンスハンドル IDR_TOOLBAR1, //リソースID tb, //TBBUTTON構造体のアドレス 3, //ボタンの数 0, 0, //ボタンの幅、高さ 0, 0, //ボタンイメージの幅、高さ sizeof(TBBUTTON)); //TBBUTTON構造体の大きさ lStyle = GetWindowLong(hTool, GWL_STYLE); lStyle |= TBSTYLE_FLAT; SetWindowLong(hTool, GWL_STYLE, lStyle); hImage = ImageList_LoadBitmap(hInst, MAKEINTRESOURCE(IDR_TOOLBAR2), 16, 0, RGB(255,255,255)); SendMessage(hTool, TB_SETHOTIMAGELIST, 0, (LPARAM)hImage); return hTool; }
ビットマップリソースからイメージリストを作るマクロです。HIMAGELIST ImageList_LoadBitmap( HINSTANCE hi, LPCTSTR lpbmp, int cx, int cGrow, COLORREF crMask );
hiはビットマップリソースが含まれているインスタンスのハンドルです。
lpbmpはロードするイメージのIDです。
cxは各イメージの幅です。
cGrowは初期イメージを超過した時に割り当てる新しいイメージの数を指定します。
crMaskはマスクの生成に使う色を指定します。
今回はホットイメージの透明化したい部分を「白」で塗っているので crMaskにはRGB(255,255,255)を指定しています。
戻り値は以前のホットボタンのイメージリストのハンドルです。以前に存在しなかった時は NULLを返します。TB_SETHOTIMAGELIST wParam = 0; lParam = (LPARAM)(HIMAGELIST) himlNewHot;
himlNewHotはセットするイメージリストのハンドルです。
今回は簡単でした。ボタンがホットになった時、ぜんぜん違うイメージを表示するように しても面白いです。
Update 27/Mar/1999 By Y.Kumei