ステータスバーと同じようにツールバーにも作り方が大きく分けて
2種類あります。CreateWindowEx関数を使う方法とCreateToolbarEx関数を
使う方法です。今回はCreateToolbarEx関数を使います。まずは、できあがった
プログラムを見てみましょう。
4つのボタンがあります。真ん中(「井」と「康」の間)で少し隙間があいていることに注意してください。
また、ボタンに表示されているのはテキストではなくビットマップです。
(紛らわしい)。このビットマップは標準では16*15の大きさですが自分の
好きな大きさに変えても問題はありません。
では、具体的な作り方を説明します。
まず、作るボタンをTBBUTTON構造体に定義します。通常ボタンは複数あるので
構造体を配列にしておきます。
この章のサンプルであればfsStateはTBSTATE_ENABLEDになります。 また、fsStyleはTBSTYLE_BUTTONとなります。ボタンは4つありますからtypedef struct _TBBUTTON { //tbb int iBitmap; //ボタンイメージの番号 0から始まる int idCommand; // WM_COMMANDの時のID BYTE fsState; // ボタンの状態 使用可能かなど BYTE fsStyle; // ボタンスタイル DWORD dwData; // アプリケーション定義データ int iString; // ボタンストリング 0から始まる } TBBUTTON, NEAR* PTBBUTTON, FAR* LPTBBUTTON;
とこんな感じになります。2番目のボタンが押されたときは WM_COMMANDのなかでIDM_Iの処理をすればよいということがわかります。TBBUTTON tbb[] = { {0, IDM_KUME, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {1, IDM_I, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {2, IDM_YASU, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {3, IDM_TAKA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0} };
それと、ボタンに表示するビットマップを用意しなくてはいけませんが、 1つ1つのボタンのビットマップを作るのではなく、全部のボタンの ビットマップを横1列に並べてくっつけたようなものを用意します。 今回は1つのビットマップを16*15にしますので、これを 横に4つ並べた大きさのビットマップを作ります。(64*15) この大きさの中にそれぞれ、16*15のビットマップを作るのですが これが結構大変です。そこで、VC++を使っている場合はうまい方法があります。
実は、VC++では、リソースエジタでツールバーを作る場合はMFCを
想定しているようで「ツールバーの新規作成」ボタンを押すと「この機能は
MFCでないと使えないよ」というような意味の注意が表示されます。
筆者は、この注意が出たためにしばらくの間VC++ではSDKでツールバーは
使えないのかと早合点していました。しかしそんなことはありません。
ソースコードを書き始めたらすぐにこのボタンを押してください。
そうすると、VC++はSDKでプログラムを書いているということに
気が付かないのか注意が出ません。そして、1つ1つのビットマップを作ってください。
そうすると、全部がくっついた横長のビットマップが自動的にできます。
ただし、ツールバーリソースはSDKでは使いません。ResourceViewからツールバーリソースを
削除しておいてください。(削除しなくても害はありません)そして、リソースエジタが
作ってくれたビットマップ(横長なのでビットマップストリップといいます)を
ビットマップリソースとして使います。ただし、この技はソースファイルが*.cの場合は
使えないようです。*.cppにしておいてください。こんな変な技は解説書とかヘルプには
絶対書いてありません。
つぎに、ステータスバーの時と同じように親ウィンドウができたらすぐに
ツールバーを作ります。ツールバーはステータスバーと同じコモンコントロールなので
commctrl.hをインクルードしたり、comctl32.libをプロジェクトに参加させるのは同じです。
InitCommonControls関数を呼んでおくのも同じです。
その後でCreateToolbarEx関数を実行します。
これを実行すればツールバーが現れます。ボタンの幅、高さは0にしておけば 自動的にちょうどよい大きさになります。HWND CreateToolbarEx( HWND hwnd, //親ウィンドウのハンドル DWORD ws, //ウィンドウスタイル UINT wID, //ツールバーのコントロールID int nBitmaps, //hBMInsやwBMIDで特定されたビットマップにはいっているボタンイメージの数 HINSTANCE hBMInst, //ビットマップリソースが入っているモジュールのインスタンスハンドル UINT wBMID, //リソースID LPCTBBUTTON lpButtons,//TBBUTTON構造体の配列のポインタ int iNumButtons, //ツールバーのボタンの数 int dxButton, //ボタンの幅 int dyButton, //ボタンの高さ int dxBitmap, //ボタンイメージの幅 int dyBitmap, //ボタンイメージの高さ UINT uStructSize //TBBUTTON構造体の大きさ );
例題のようにボタンに隙間を あけるときは、TB_INSETRBUTTONメッセージを送ります。
iButtonこのボタン番号の左側にボタンが挿入されます。TB_INSERTBUTTON wParam = (WPARAM) iButton; lParam = (LPARAM) (LPTBBUTTON) lpButton;
lpButton挿入されるボタンの性質を記載したTBBUTTON構造体のポインタ
空白は{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0}のメンバをもつボタンと考えてください。
さて、前置きがすっかり長くなりましたがサンプルのプログラムを
見てみましょう。その前にビットマップストリップを示します。
今回は、リソーススクリプトも全部自前で作ることにしました。// tool00.rc #include "windows.h" #include "tool00.h" ///////////////////////////////////////////////////////////////////////////// // // Bitmap // ID_MYBMP BITMAP DISCARDABLE "mybmp.bmp"
ヘッダファイルも自前です。いつもは、リソース名は ダブルクオーテーションでくくったものを使用していましたが、 CreateToolbarEx関数の引数の都合上、整数値で表します。 (ID_MYBMP)// tool00.h #define ID_TOOLBAR 100 #define IDM_KUME 101 #define IDM_I 102 #define IDM_YASU 103 #define IDM_TAKA 104 #define ID_MYBMP 105
tbbの定義の仕方をよく見ておいてください。// tool00.cpp #define STRICT #include <windows.h> #include <commctrl.h> #include "tool00.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HWND hToolBar; // ツールバーのウィンドウハンドル char szClassName[] = "tool00"; //ウィンドウクラス TBBUTTON tbb[] = { {0, IDM_KUME, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {1, IDM_I, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {2, IDM_YASU, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {3, IDM_TAKA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0} }; TBBUTTON tb = {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0}; int APIENTRY 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; }
毎度おなじみのものです。//ウィンドウ・クラスの登録 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 = NULL; //メニュー名 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: hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); InitCommonControls(); hToolBar = CreateToolbarEx( hWnd, //親ウィンドウ WS_CHILD | WS_VISIBLE, //ウィンドウスタイル ID_TOOLBAR, // コントロールID 4, //イメージの数 hInst, ID_MYBMP, tbb, 4, // ボタンの数 0, //ボタンの幅 0, //ボタンの高さ 16, //イメージの幅 15, //イメージの高さ sizeof(TBBUTTON)); SendMessage(hToolBar, TB_INSERTBUTTON, 2, (LPARAM)&tb); break; case WM_SIZE: SendMessage(hToolBar, WM_SIZE, wp, lp); break; case WM_COMMAND: switch(LOWORD(wp)) { case IDM_KUME: MessageBox(hWnd, "「粂」ボタンを押したね", "ボタンの反応", MB_OK); break; case IDM_I: MessageBox(hWnd, "「井」ボタンを押したね", "ボタンの反応", MB_OK); break; case IDM_YASU: MessageBox(hWnd, "「康」ボタンを押したね", "ボタンの反応", MB_OK); break; case IDM_TAKA: MessageBox(hWnd, "「孝」ボタンを押したね", "ボタンの反応", MB_OK); 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; }
[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]
Update Jul/23/1997 By Y.Kumei