CMenuItemDataクラス
一般的なWindowsメニューコントロールであれば、GetMenuItemInfo関数でメニューに関する詳細情報を取得できますが、LuxMenuは拡張データをすべて自前で持ち、いざと言うときに引き出して描画などの処理を行わなければなりません。そこで、アイテム単位で詳細なデータを管理するためのクラスとしてCMenuItemDataの定義を行います。
CLuxMenuまたはCLuxSubMenuのインスタンスがCMenuItemDataクラスのインスタンスを複数個(アイテムの個数分)所有する形になります。以下に示すメンバを持ちます。
| メンバ名 | 説明 |
item_index |
メニューアイテムの位置(一番上のアイテムが0)。 |
dwItemID |
メニューアイテムのID。 |
str |
表示する文字列。 |
pobj_ThisMenu |
このアイテムが所属するCLuxMenuクラスのインスタンスへのポインタ。 |
pobj_SubMenu |
メニューアイテムがポップアップ可能な場合の、CLuxSubMenuクラスのインスタンスへのポインタ。 |
hIcon |
アイコンハンドル。 |
hGrayIcon |
淡色表示時のアイコンハンドル。 |
また、メニューアイテムに対してWM_MEASUREITEM、WM_DRAWITEMの各メッセージを処理する必要があるため、CLuxMenuの各メソッドに処理を引き渡すためのコードも用意しておきます。
ここで、メッセージの流れをおさらいしておきましょう。
WM_MEASURE → CLuxMenu.MeasureItem → CMenuItemData.GetItemSize →CLuxMenu.GetItemSize
WM_DRAWITEM → CLuxMenu.DrawItem → CMenuItemData.OwnerDraw → CLuxMenu.OwnerDraw
'------------------------------------------------------- ' アイテムが属するメニューのサイズ取得メソッドの呼び出し '------------------------------------------------------- Virtual Sub GetItemSize(ByRef size As SIZE) pobj_ThisMenu->GetItemSize(item_index,size) End Sub '------------------------------------------------------- ' アイテムが属するメニューの描画メソッドの呼び出し '------------------------------------------------------- Virtual Sub OwnerDraw(hdc As HDC, ByRef ref_rc As RECT, bSelect As BOOL) pobj_ThisMenu->OwnerDraw(hdc,ref_rc,bSelect,item_index) End Sub
COMインターフェイスの提供
CLuxMenuクラス、CLuxSubMenuクラスを以下のようなインターフェイスとして外部から呼び出せるようにしてみましょう。
CLuxMenuクラス …ILuxMenuインターフェイスCLuxSubMenuクラス …ILuxSubMenuインターフェイス
Interfaceステートメントを利用して各メソッドを定義していきます。特筆することはありませんが、順番を間違えないようにしましょう。COMインターフェイスは順番を間違えるとひどい事態になりかねないので……。
ILuxSubMenuはILuxMenuと同等のメソッドを持っているため、そっくりそのまま継承してしまいましょう。また、LuxMenu_CreateInstance関数、LuxSubMenu_CreateInstance関数を定義して各インターフェイスの生成を可能にします。これらの関数はDLL用にコンパイルした場合に外部から呼び出せるよう、Export修飾子をつけてエクスポート関数に指定しておきます。
'---------------------------------- ' ILuxMenu インターフェイス '---------------------------------- 'CLSID Dim IID_ILuxMenu=[&H30B65E5A,&HB400,&H49A2, _ [&HB0,&HE5,&H61,&H19,&HB7,&H53,&H4C,&H4A]] As GUID 'インターフェイス Interface ILuxMenu Inherits IUnknown Sub ImportMenu(hMenu As HMENU) Function GetMenuHandle() As HMENU Function MeasureItem(lParam As LPARAM) As BOOL Function DrawItem(lParam As LPARAM) As BOOL Function CreateNewMenu() As BOOL Function EnableItem(itemIDorPosition As DWord, fEnable As DWord) As BOOL Function CheckItem(itemIDorPosition As DWord, fCheck As DWord) As BOOL Function IsChecked(itemIDorPosition As DWord, fByPosition As DWord) As BOOL Function RemoveItem(itemIDorPosition As DWord, fByPosition As DWord) As BOOL Function InsertItem(item_index As Long, pszText As LPSTR, dwItemID As DWord) As BOOL Function InsertPopupItem(item_index As Long, pszText As LPSTR, pobj_SubMenu As *ILuxSubMenu) As BOOL Function SetIcon(dwItemID As DWord, hIcon As HICON) As BOOL End Interface 'インスタンス生成用の関数 Function Export LuxMenu_CreateInstance() As *ILuxMenu Dim pobj_Menu As *CLuxMenu pobj_Menu=New CLuxMenu() pobj_Menu->QueryInterface(IID_ILuxMenu, VarPtr(LuxMenu_CreateInstance)) End Function '---------------------------------- ' ILuxSubMenu インターフェイス '---------------------------------- 'CLSID Dim IID_ILuxSubMenu=[&HDAD2F3BA,&HD34B,&H4fc2, [&H8A,&HDF,&H8C,&HD9,&H3F,&H05,&H0B,&HA6]] As GUID 'インターフェイス(ILuxMenuと同様) Interface ILuxSubMenu Inherits ILuxMenu End Interface 'インスタンス生成用の関数 Function Export LuxSubMenu_CreateInstance() As *ILuxSubMenu Dim pobj_SubMenu As *CLuxSubMenu pobj_SubMenu=New CLuxSubMenu() pobj_SubMenu->QueryInterface(IID_ILuxSubMenu, VarPtr(LuxSubMenu_CreateInstance)) End Function
まとめ
今回、説明した内容がLuxMenuコントロールのすべてです。クラスの設計、独自描画モジュールの設計、インターフェイスの提供など、一連の流れにていねいに触れていきましたが、いかがだったでしょうか?
これをお読みになって、ABを用いてCOMコンポーネントの開発をされる方が増えれば筆者としては嬉しい限りです。また、今回LuxMenuを通じてCOMコンポーネントについて説明しましたが、COMはまだまだ奥が深く、ABが提供するCOM機能もこれから向上していく可能性のある分野です。今後、COMコンポーネントを開発される皆さまのフィードバッグを受け止め、よりコンポーネント開発に特化した開発環境を提供できればと考えています。
