今回は、Windowsアプリでは非常に需要が高い、ツールバーについて話を進めます。
ステータスバーに続き、今回のツールバーもアプリケーションの雰囲気や使い勝手を大幅に向上させることができるでしょう。

今回作成するプログラムのサンプルファイルを置いておきますので、参考にしたい方はどうぞ☆
Toolbar.zip(プロジェクトに必要なファイルがすべて入っています)



ツールバーを生成するにはCreateToolbarEx関数を!

このCreateToolbarEx関数、パラメータが多くて面倒ですが、難しい内容はありません。一つ一つ見ていきましょう。


CreateToolbarEx ( _
   hWnd As DWord, _           '親ウィンドウのハンドル
   ws As DWord, _             'ツールバーのウィンドウスタイル(WM_???)
   wID As DWord, _            'ツールバーのID
   nBitmaps As Long, _        'ボタンイメージの数
   hBMInst As DWord, _        'インスタンスハンドル(GetModuleHandle関数で取得)
   wBMID As DWord, _          'ビットマップのリソースID
   lpButtons As VoidPtr, _    'TBBUTTON構造体配列へのポインタ
   iNumButtons As Long, _     'ボタンの個数
   dxButton As Long, _        'ボタンの幅
   dyButton As Long, _        'ボタンの高さ
   dxBitmap As Long, _        '一つのボタンに対するビットマップの幅
   dyBitmap As Long, _        '一つのボタンに対するビットマップの高さ
   uStructSize As DWord _     'TBBUTTON構造体のサイズ
   ) As DWord
これらのパラメータでは、ボタンやビットマップの違いに注意しながら記述していきましょう。
ツールバーのウィンドウハンドルが戻り値になります。

ボタンごとの情報を格納するのがTBBUTTON構造体


Type TBBUTTON
   iBitmap As Long          '左から何番目のビットマップを使うか
   idCommand As Long        'コマンドID
   fsState As Byte          'ボタンの状態(表示・非表示や有効・無効など)
   fsStyle As Byte          'ボタンのスタイル(ボタンスタイル、セパレータスタイルなど)
   bReserved[1] As Byte     'このメンバは無視して下さい
   dwData As DWord          'アプリケーション定義データ(今回は利用しません)
   iString As Long          'ボタン文字列(今回は利用しません)
End Type
fsStateメンバには、TBSTATE_ENABLED(有効)、TBSTATE_HIDDEN(非表示)などの情報を指定します。
fsStyleメンバには、通常ボタンなら TBSTYLE_BUTTON を、セパレータ(区切り空白)ならTBSTYLE_SEP を指定します。



ツールバー作成を実践!

"Toolbar" などという名前のプロジェクトを新規作成しておいて下さい。ノーマルウィンドウベースで、プロジェクト オプション内の「コモンコントロールを使用する」にチェックを入れておきます。

次に、ボタン用のビットマップを用意します。通常、一つのボタンは 16*15 のサイズであり、横一列にボタンイメージが並べられたビットマップが有効です。
今回は、下のようなボタン画像を使用するので、あらかじめプロジェクト フォルダ内に保存しておきましょう。
例: (このボタン画像をダウンロードする)
保存できたら、このビットマップファイルをリソースデータに追加します。ProjectViewのMaterialタブの「Bitmapリソース」フォルダを右クリックし、ファイルを挿入します。ID は IDB_BITMAP1 などとしておきましょう。

メニューを作る

「Menu」フォルダ内に "MainMenu" を作成し、下のような構成になるよう、メニューの追加を行っていきます。メニュー項目を挿入する場合は、挿入したい場所の1つ上の項目を選択し、「挿入」ボタンをクリックしていくことを思い出しましょう。メニューの編集方法は、ステップ6、ステップ7で解説しています。
また、メニューの作成が完了したら忘れないうちに "MainWnd" のRAD画面を開き、ウィンドウ プロパティ内の「Menu」を "MainMenu" にセットしておいて下さい。


キャプション ID 備考
ファイル(&F) - ポップアップ
新規作成(&N) IDM_NEW -
  • - セパレータ
開く(&O) IDM_OPEN -
保存(&S) IDM_SAVE -
  • - セパレータ
終了(&X) IDM_EXIT -
ヘルプ(&H) - ポップアップ
バージョン情報(&A) IDM_ABOUT -



ここからコーディング

"MainWnd.sbp" を開きコーディングを行っていきます。

' ----------------------------------------------------------------------------
' イベント プロシージャ
' ----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd

' メモ - 以下の領域を、変数、構造体、定数、関数を宣言するための、
' グローバル領域として利用することができます。
' ----------------------------------ここから----------------------------------

Const ID_TOOLBAR = 70 'ツールバーのID

Sub SetTbButtonData(ByRef ptb As TBBUTTON,
   iBitmap As Long,
   idCommand As Long,
   fsState As Byte,
   fsStyle As Byte)
   'ptb(TBBUTTON構造体)にボタン情報を格納する
   With ptb
       .iBitmap=iBitmap
       .idCommand=idCommand
       .fsState=fsState
       .fsStyle=fsStyle
       .dwData=0
       .iString=0
   End With
End Sub

' ----------------------------------ここまで----------------------------------

↑プログラムの先頭部分には、ツールバーIDの定数とSetTbButtonData関数を定義します。
SetTbButtonData関数は、TBBUTTON構造体のメンバを格納しやすくするための役割を果たします。

Sub MainWnd_Destroy()
   Toolbar_DestroyObjects()
   PostQuitMessage(0)
End Sub

↑Destroyイベントに変更点はありません。

Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
   Dim ic As INITCOMMONCONTROLSEX
   Dim tbb[4] As TBBUTTON

   'コモンコントロールの初期化
   ic.dwSize=Len(ic)
   ic.dwICC=ICC_BAR_CLASSES
   InitCommonControlsEx(ic)

   'ボタン情報をセット
   SetTbButtonData(tbb[0],0,IDM_NEW,TBSTATE_ENABLED,TBSTYLE_BUTTON)
   SetTbButtonData(tbb[1],1,IDM_OPEN,TBSTATE_ENABLED,TBSTYLE_BUTTON)
   SetTbButtonData(tbb[2],2,IDM_SAVE,TBSTATE_ENABLED,TBSTYLE_BUTTON)
   SetTbButtonData(tbb[3],0,0,TBSTATE_ENABLED,TBSTYLE_SEP)
   SetTbButtonData(tbb[4],3,IDM_ABOUT,TBSTATE_ENABLED,TBSTYLE_BUTTON)

   'ツールバーを生成
   CreateToolbarEx(hMainWnd, _
       WS_CHILD or WS_VISIBLE, _
       ID_TOOLBAR, _
       4, _                        'ビットマップの個数
       GetModuleHandle(0), _
       IDB_BITMAP1, _              'ビットマップのリソースID
       tbb, _
       5, _                        'ボタンの個数
       0,0, _                      'ボタンサイズ(0指定で自動セットに)
       16,15, _                    'ビットマップサイズ
       Len(tbb[0]))
End Sub

↑Createイベントでは、tbb(TBBUTTON構造体配列)にボタンデータを格納し、CreateToolbarEx関数でツールバーの生成を行います。
ビットマップ・ボタンの個数・サイズは少しややこしいかもしれませんが、間違いのないよう、念入りにチェックしておきましょう。今回は、セパレータを1つ含むため、ビットマップの個数よりもボタンの個数のほうが1つだけ多くなっています。

Sub MainWnd_IDM_NEW_MenuClick()
   MessageBox(hMainWnd, "新規作成", "Test of Toolbar", MB_OK)
End Sub

Sub MainWnd_IDM_OPEN_MenuClick()
   MessageBox(hMainWnd, "開く", "Test of Toolbar", MB_OK)
End Sub

Sub MainWnd_IDM_SAVE_MenuClick()
   MessageBox(hMainWnd, "保存", "Test of Toolbar", MB_OK)
End Sub

Sub MainWnd_IDM_EXIT_MenuClick()
   SendMessage(hMainWnd,WM_CLOSE,0,0)
End Sub

Sub MainWnd_IDM_ABOUT_MenuClick()
   MessageBox(hMainWnd, "ツールバーテスト Ver1.0", "バージョン情報", MB_OK)
End Sub

↑各メニューイベントにはダミーを作っておきます。IDM_EXITについてはWM_CLOSEメッセージで終了動作を行いますが、他のメッセージでは、MessageBox関数でコマンド内容を表示するだけにしておきます。



これですべての作業は完了です。しっかりとツールバーが表示され、イベントメッセージが送られるかどうかをチェックしてみましょう☆