SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザイン性に優れた拡張メニューコントロール

LuxMenuで見栄えのよいメニューを作ろう

デザイン性に優れた拡張メニューコントロール 第1回


LuxMenuが提供するインターフェイス

 メニュー付きウィンドウが簡単に作れることを確認したところで、本丸の拡張メニューコントロール「LuxMenu」のインターフェイス構造に焦点を合わせましょう。

ILuxMenuインターフェイス

 親メニューを管理します。下記に示すメソッドを持ち合わせます。

ILuxMenuインターフェイスのメソッド
メソッド名 説明
QueryInterfaceAddRefRelease 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クラスを継承しつつ、下記のメソッドをオーバーライドすることで親メニューとは異なる独自の機能を提供しています。

ILuxSubMenuインターフェイスのメソッド
メソッド名 説明
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インターフェイス用のポインタ変数をソースコードの先頭位置に定義します。

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

' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。

Dim pobj_MainMenu As *ILuxMenu

WM_CREATEメッセージ処理(Createイベント)

 RADツールからCreateイベントのプロシージャを生成するか、もしくは下記のソースコードを「MainWnd.sbp」の末端に追加しましょう。

Createイベントのコーディング
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()」の一行を付け加えます。

Destroyイベントのコーディング
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利用者側はこれらのメソッドを呼び出すだけなので、とても簡単です。

WM_MEASUREITEM、WM_DRAWITEMに対応する
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

実行してみよう

 コーディング作業はこれで終わりです。早速実行してみましょう。

MenuTest.exeの実行画面
MenuTest.exeの実行画面

メニューアイテムにアイコンを付けてみる

 LuxMenuが簡単に実装できることは分かりましたね。しかしながら、先ほどのサンプルはあまりにもお粗末です。ということで、メニューアイテムにアイコンを付けてみたりして、見た目を華やかにしてみましょう。

 ちなみに、LuxMenuで読み込むことができるアイコンは、内部処理の都合上、16*16、24ビットフルカラーのみになります。アイコンの自作が困難な方は、「Petite Priere」というサイトから高品質なアプリケーションアイコンを得ることができます。ぜひ、参考にしてみてください。

アイコンリソースを追加する

 MenuTestプロジェクトを開き、プロジェクトビューのMaterialタブを表示させます。「Icon リソース」フォルダを右クリックし、[アイコンを挿入]をクリックします。追加したいアイコンを選択します。

 今回は、下記の3つのアイコンを追加していきたいと思います。

「開く」コマンドのアイコン(ID:IDI_OPEN)
「開く」コマンドのアイコン(ID:IDI_OPEN)
「保存」コマンドのアイコン(ID:IDI_SAVE)
「保存」コマンドのアイコン(ID:IDI_SAVE)
「オプション」コマンドのアイコン(ID:IDI_OPTION)
「オプション」コマンドのアイコン(ID:IDI_OPTION)

MainWnd.sbpのコーディング

 アイコンの指定はCreateイベント内、既存メニューのインポートが完了した直後にILuxMenuインターフェイスのSetIconメソッドで行います。

Createイベントのコーディング
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

実行してみよう

 コーディング作業はこれで終わりです。早速実行してみましょう。

MenuTest.exeの実行画面(アイコン編)
MenuTest.exeの実行画面(アイコン編)

次のページ
VC++でLuxMenuを実装する

この記事は参考になりましたか?

デザイン性に優れた拡張メニューコントロール連載記事一覧

もっと読む

この記事の著者

山本 大祐(ヤマモト ダイスケ)

普段はActiveBasicと周辺ツールの開発を行っています。最近は諸先輩方を見習いながら勉強中の身。AB開発日記

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/500 2008/08/26 13:40

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー