【VBA×WindowsAPI】AppendMenu関数の使い方

AppendMenu関数

AppendMenu関数は指定のメニューの末尾に新規の項目を作成するための関数です。
ここでいうメニューとはメニューバー、ドロップダウンメニュー、サブメニュー、またはコンテキスト(ショートカット)メニューなどを指します。AppendMenu関数で追加するメニュー項目は下画像の通り、文字列の設定だけではなくアイコン設定やサブメニューを設定することができます。

この関数を使うことでCreateMenu関数CreatePopupMenu関数などで新規作成したメニューに対して、新規メニュー項目を追加することができます。このとき、追加されるメニュー項目はメニューの最後尾に追加されます(イメージとしてはCollectionのAddメソッド)。位置を指定して追加したい場合はInsertMenu関数を使うことでインデックスを指定したメニュー項目の追加が可能になります。

VBAで本関数を使う場合、ユーザーがクリックしたイベントを検知するためUserFormやControlのClickイベントやMouseUpイベントなどを利用するのが一般的です。

使用方法

AppendMenu関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。

使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。

 icon-code  64bit  

Declare PtrSafe Function AppendMenu Lib “user32” Alias “AppendMenuA” _
(ByVal hMenu As LongPtr, ByVal wFlags As Long, _

ByVal wIDNewItem As LongPtr, ByVal lpNewItem As Any) As Long

icon-code  32bit  

Declare Function AppendMenu Lib “user32” Alias “AppendMenuA” _
(ByVal hMenu As Long, ByVal wFlags As Long, _
ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long

上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。

 
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。

Private Declare PtrSafe Function~ :モジュール内でのみ呼び出し有効
Public Declare PtrSafe Function~ :モジュール外で呼び出し有効

 

構文

AppendMenu関数の構文は下記のように書きます。

icon-code AppendMenu関数 

lRet = AppendMenu(hMenu, wFlags, wIDNewItem, lpNewItem)

引数

 hMenu     (64bit:LongPtr型 / 32bit:Long型) 

項目を追加するメニューのハンドルです。
通常、CreateMenu関数やCreatePopupMenu関数等で作成されたメニューハンドルを入力します。
  

 wFlags     (Long型) 

追加する項目の外観や動作を制御するフラグです。
下表の定数値を組み合わせて設定することが可能です。(※その他のフラグはMicrosoft公式を参照)

フラグ (定数) 説明
MF_STRING (&H0) メニュー項目に文字列を設定する
MF_DISABLED (&H2) メニュー項目を選択不可状態にする
MF_BITMAP (&H4) メニュー項目にBMP画像を設定する
MF_CHECKED (&H8) メニュー項目をチェック付与状態にする
MF_POPUP (&H10) メニュー項目にサブメニューを付与する
MF_SEPARATOR (&H800) メニュー項目に水平分割線を設定する

フラグを複数設定させたい場合はOr演算子を使って設定が可能です。
ただし、下記のフラグの組み合わせについては設定することが出来ません。

 

 wIDNewItem     (64bit:LongPtr型 / 32bit:Long型) 

追加する項目の識別IDです。ユーザーが選択した項目はこの識別IDをして取得が可能です。
wFlagsに「MF_POPUP」を設定する場合、識別IDではなくサブメニューとして設定するメニューのハンドルを入力します。これにより、追加される項目はここで入力したハンドルが指すメニューをサブメニューをして持つ項目として追加されます。(この場合、項目自体の識別IDは存在しない)
 

 lpNewItem     (Any型) 

追加する項目の内容です。wFlagsに設定するフラグにより入力内容は変化します。
wFlagsに「MF_STRING」を設定する場合は、項目名となる文字列(String型)を入力します。
wFlagsに「MF_BITMAP」を設定する場合は、項目に設定する画像のハンドル(64bit:LongPtr型 / 32bit:Long型)を入力します。画像のハンドルはLoadImage関数等を利用することで取得可能です。

入力する引数がwFlagsにより文字列、数値と変化するため特定の型で宣言ができないことから、少し特殊な「Any型」として宣言されます。(ここでいう宣言とはDeclare~で始まる宣言文のこと)

Any型ではなくVariant型で宣言した場合、アプリケーションが強制終了するので注意が必要です。設定する項目が文字列だけの場合は「As Any」部分を「As String」としても正常に動作します。
 

戻り値

 lRet     (64bit:LongPtr型 / 32bit:Long型) 

戻り値は関数が成功すると「0以外」、失敗すると「0」が返ります。

サンプルコード

以下はAppendMenu関数FindWindow関数CreatePopupMenu関数DestroyMenu関数GetCursorPos関数TrackPopupMenu関数を使って、UserForm上で右クリックをしたらコンテキストメニューを表示するサンプルコードです。(※より詳細なAppendMenu関数実装例はコチラ)

下記コードをUserFormのコードにコピーペーストしてからUserFormを表示すれば、Initializeイベントでメニューがメモリ上に作成され、右クリックをするとそのメニューを表示することができます。

 

 icon-share-square  VBA×WindowsAPIまとめページ

その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。

 icon-share-square  参考

Microsoft公式:AppendMenuA 関数 (winuser.h) – Win32 apps

Excel, VBA, Windows API

Posted by Lic