ポップアップメニューを表示する

ポップアップメニューを表示するテクニックです。
ポップアップメニューは TrackPopupMenu 関数を使用して表示する事ができます。

2003.7.18追記

SetForegroundWindow関数でウィンドウをアクティブにする処理を追加しました。
ポップアップメニューを表示する前に、この処理を追加しないとポップアップメニューの外側をクリックしてもポップアップメニューが閉じません。

サンプル(32bit) ダウンロード

'ポップアップメニュー用API&構造体
Private Type RECT
     Left As Long
     Top As Long
     Right As Long
     Bottom As Long
End Type
Private menRect As RECT
    
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, lprc As RECT) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long


Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    
    'タスクトレイのマウスのクリックイベント処理
    'PictureBoxのScaleModeプロパティを"3 - ピクセル"にしないと正常に動作しません
    
    Dim hMenu As Long, hSubMenu As Long
    Dim nRC As Long
    Dim vRC
    
    Select Case X
           Case WM_LBUTTONUP
                '左クリックされた場合
                Me.Show
                'タスクトレイのアイコンを削除
                Call NotifyIcon("DELETE")
           Case WM_RBUTTONUP
                '右クリックされた場合
                'Form1のメニューをマウスカーソルがあるところに表示
                menRect.Left = 0
                menRect.Top = 0
                menRect.Right = Screen.Width / Screen.TwipsPerPixelX
                menRect.Bottom = Screen.Height / Screen.TwipsPerPixelY
                nRC = GetCursorPos(lpPoint)
                hMenu = GetMenu(Form1.hwnd)
                hSubMenu = GetSubMenu(hMenu, 0)
                'ウィンドウをアクティブにする
                Call SetForegroundWindow(Form1.hwnd)
                'ポップアップメニューの表示
                nRC = TrackPopupMenu(hSubMenu, 0, lpPoint.X, lpPoint.Y, 0, Form1.hwnd, menRect)
    End Select

End Sub

サンプル解説

Picture1_MouseMoveの Case WM_RBUTTONUP 以下でポップアップメニューを表示しています。

ポップアップメニューの表示までには3つの段階があります。

  1. ポップアップ表示するメニューのハンドルの取得

    hMenu = GetMenu(Form1.hwnd) でメニューのハンドルを取得しています。

  2. ポップアップ表示するメニューのサブメニューのハンドルの取得

    hSubMenu = GetSubMenu(hMenu, 0) でサブメニューのハンドルを取得しています。

    1.で取得したメニューハンドルとサブメニュー番号を渡します。サブメニュー番号とは「左から何番目のメニューか?」と言う意味です。

    例えばメニューが↓の様に並んでた場合
    サブメニュー番号は
    • 「ファイル(F)」は、0
    • 「編集(E)」は、1
    • 「表示(V)」は、2

    となります。

  3. ウィンドウをアクティブにする

    ポップアップメニュー表示前に、SetForegroundWindow関数にフォームのハンドルを渡してウィンドウ(実際には見えていませんが)をアクティブにします。
    この処理を行わないとポップアップメニューの外側をクリックしてもポップアップメニューが閉じなくなってしまいます。

  4. ポップアップメニューの表示

    RC = TrackPopupMenu(hSubMenu, 0, lpPoint.X, lpPoint.Y, 0, Form1.hwnd, menRect)でポップアップメニューを表示しています。

    引数の内容は次の通りです。
    (引数の名前は、Declare Functionで指定したものです)

    メンバー I/O 説明
    hMenu In サブメニューのハンドル
    wFlags In 画面位置とマウスボタンのフラグを指定しますが、使う必要がほとんどないので割愛。
    X In ポップアップメニューを表示する、メニューのX座標。
    Y In ポップアップメニューを表示する、メニューのY座標。
    nReserved In 予約済み。0をセットします。
    hwnd In メニューがあるウィンドウのハンドル。
    lprc In メニューの表示可能な領域。
    サンプルでは、画面の解像度を渡しています。構造体になっています。

    各座標情報は、すべてスクリーン座標です。もちろん座標はピクセルに変換してセットします。
    サンプルはタスクトレイの上にポップアップメニューを表示させるため、GetCursorPos関数で画面上のマウスの位置を取得しています。


[ Window Close ]