LuxMenuが提供するインターフェイス
メニュー付きウィンドウが簡単に作れることを確認したところで、本丸の拡張メニューコントロール「LuxMenu」のインターフェイス構造に焦点を合わせましょう。
ILuxMenuインターフェイス
親メニューを管理します。下記に示すメソッドを持ち合わせます。
| メソッド名 | 説明 |
QueryInterface、AddRef、Release |
COMインターフェイスとして最低限必要なIUnknownメソッドです。特別なことはしないので、あくまでもCOMの仕様に併せた実装を行っています。 |
ImportMenu |
既存のメニューハンドルをパラメータとして受け取り、LuxMenuの機能を有効にします。 |
GetMenuHandle |
インスタンスのメニューハンドルを返します。 |
MeasureItem |
ウィンドウにWM_MEASUREITEMメッセージが送られたときに呼び出します。 |
DrawItem |
ウィンドウにWM_DRAWITEMメッセージが送られたときに呼び出します。 |
CreateNewMenu |
Win32APIのCreateMenu関数相当のメソッドです。新たにメニューを生成します。 |
EnableItem |
Win32APIのEnableMenuItem関数相当のメソッドです。メニューアイテムの有効化・無効化を行います。 |
CheckMenu |
Win32APIのCheckMenuItem関数相当のメソッドです。メニューアイテムのチェックのオン・オフを行います。 |
RemoveItem |
Win32APIのRemoveMenuItem関数相当のメソッドです。メニューアイテムを削除します。 |
InsertItem |
任意の場所に、新たにメニューアイテムを追加します。 |
InsertPopupItem |
InsertItemメソッドと似ていますが、こちらはポップアップメニューアイテムの追加用メソッドです。既に存在するサブメニューを指定しなければなりません。 |
SetIcon |
メニューアイテムの左側に表示される16×16アイコンを指定します(内部で自動的に淡色アイコンの生成も行っています)。 |
ILuxSubMenuインターフェイス
ポップアップメニューを管理します。ILuxMenuクラスを継承しつつ、下記のメソッドをオーバーライドすることで親メニューとは異なる独自の機能を提供しています。
| メソッド名 | 説明 |
CreateNewMenu |
内部でCreatePopupMenu関数を呼び出すようにします。 |
GetItemSize |
サブメニューアイテムの描画サイズを計算します。 |
OwnerDraw |
サブメニューアイテムの描画を行います。 |
ABでLuxMenuを実装してみる
LuxMenuコントロールのインターフェイスを学習したところで、早速これらのインターフェイスを活用して実装を行ってみたいと思います。
まずはABでの実装となりますが、ABであればCOM DLLを介さなくても、LuxMenuライブラリ(LuxMenu.sbp)をプロジェクトに追加することで、各種モジュールの呼び出しが可能になります。
記事冒頭のリンクから、「LuxMenu.zip」をダウンロードしてください。「LuxMenu.zip」をダウンロードしたら、「LuxMenu.sbp」を取り出して、先ほど作成した「MenuTest」プロジェクトと同じディレクトリに保存しておきましょう。
ここから開発作業に入ります。まずは[MenuTest]プロジェクトをABで開いてください。プロジェクトビューのFileタブを表示し、Source Filesフォルダを右クリックします。[ファイルを挿入]をクリックし、ダウンロードした「LuxMenu.sbp」を選択します。
LuxMenuを実装するためには、下記のポイントをコーディングする必要があります。たいした量ではないので、順番に進めていきましょう。ちなみに、これらすべてのコーディングは「MainWnd.sbp」に対して行います。
ILuxMenuインターフェイス ポインタの定義- WM_CREATE ……
ILuxMenuインターフェイスの生成 - WM_DESTROY ……
ILuxMenuインターフェイスの解放 - WM_MEASUREITEM …… オーナー描画用のアイテム領域の設定
- WM_DRAWITEM …… オーナー描画
ILuxMenuインターフェイス ポインタ変数の定義
「MainWnd.sbp」を開き、ILuxMenuインターフェイス用のポインタ変数をソースコードの先頭位置に定義します。
'--------------------------------------------------------------------- ' イベント プロシージャ '--------------------------------------------------------------------- ' このファイルには、ウィンドウ [MainWnd] に関する ' イベントをコーディングします。 ' ウィンドウ ハンドル: hMainWnd ' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。 Dim pobj_MainMenu As *ILuxMenu
WM_CREATEメッセージ処理(Createイベント)
RADツールからCreateイベントのプロシージャを生成するか、もしくは下記のソースコードを「MainWnd.sbp」の末端に追加しましょう。
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) 'ILuxMenuインスタンスを生成 pobj_MainMenu=LuxMenu_CreateInstance() '既存メニューのインポート pobj_MainMenu->ImportMenu(GetMenu(hMainWnd)) End Sub
LuxMenu_CreateInstanceは、ILuxMenuインターフェイスを生成するためのLuxMenuライブラリが提供する関数です。ILuxMenu生成直後、早速、既存のメニューコントロールをインポートさせています。
WM_DESTROYメッセージ処理(Destroyイベント)
「MainWnd.sbp」内にあるMainWnd_Destroyプロシージャに「pobj_MainMenu->Release()」の一行を付け加えます。
Sub MainWnd_Destroy() pobj_MainMenu->Release() MenuTest_DestroyObjects() PostQuitMessage(0) End Sub
WM_MEASUREITEM、WM_DRAWITEMの2つのメッセージを処理する
「MainWnd.sbp」内のMainWndProcプロシージャを下記のように書き直します。これら2つのメッセージの内部的な処理に関しては、ILuxMenuインターフェイスのMeasureItemメソッド、DrawItemメソッドが請け負います(描画関係をすべて行ってくれます)。LuxMenu利用者側はこれらのメソッドを呼び出すだけなので、とても簡単です。
Function MainWndProc(hWnd As HWND, dwMsg As DWord, _ wParam As WPARAM, lParam As LPARAM) As LRESULT ' TODO: この位置にウィンドウメッセージを ' 処理するためのコードを記述します。 Dim size As SIZE Dim pobj_MenuItemData As *CMenuItemData Select Case(dwMsg) Case WM_MEASUREITEM If pobj_MainMenu->MeasureItem(lParam) Then MainWndProc=0 Exit Function End If Case WM_DRAWITEM If pobj_MainMenu->DrawItem(lParam) Then MainWndProc=0 Exit Function End If End Select ' イベントプロシージャの呼び出しを行います。 MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam) End Function
実行してみよう
コーディング作業はこれで終わりです。早速実行してみましょう。

メニューアイテムにアイコンを付けてみる
LuxMenuが簡単に実装できることは分かりましたね。しかしながら、先ほどのサンプルはあまりにもお粗末です。ということで、メニューアイテムにアイコンを付けてみたりして、見た目を華やかにしてみましょう。
ちなみに、LuxMenuで読み込むことができるアイコンは、内部処理の都合上、16*16、24ビットフルカラーのみになります。アイコンの自作が困難な方は、「Petite Priere」というサイトから高品質なアプリケーションアイコンを得ることができます。ぜひ、参考にしてみてください。
アイコンリソースを追加する
MenuTestプロジェクトを開き、プロジェクトビューのMaterialタブを表示させます。「Icon リソース」フォルダを右クリックし、[アイコンを挿入]をクリックします。追加したいアイコンを選択します。
今回は、下記の3つのアイコンを追加していきたいと思います。



MainWnd.sbpのコーディング
アイコンの指定はCreateイベント内、既存メニューのインポートが完了した直後にILuxMenuインターフェイスのSetIconメソッドで行います。
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) 'ILuxMenuインスタンスを生成 pobj_MainMenu=LuxMenu_CreateInstance() '既存メニューのインポート pobj_MainMenu->ImportMenu(GetMenu(hMainWnd)) 'アイコンをセット pobj_MainMenu->SetIcon(IDM_OPEN, LoadImage(GetModuleHandle(0),MAKEINTRESOURCE(IDI_OPEN), _ IMAGE_ICON,16,16,0)) pobj_MainMenu->SetIcon(IDM_SAVE, LoadImage(GetModuleHandle(0),MAKEINTRESOURCE(IDI_SAVE), _ IMAGE_ICON,16,16,0)) pobj_MainMenu->SetIcon(IDM_OPTION, LoadImage(GetModuleHandle(0),MAKEINTRESOURCE(IDI_OPTION), _ IMAGE_ICON,16,16,0)) End Sub
実行してみよう
コーディング作業はこれで終わりです。早速実行してみましょう。

