● メニュー文字列を階層順に列挙する ●

オーナードローメニューで使えるかも…

この関数をいい感じに改造した関数があるサンプル → オーナードロー系サンプル

Private Type MENUITEMINFO
    cbSize As Long
    fMask As Long
    fType As Long
    fState As Long
    wID As Long
    hSubMenu As Long
    hbmpChecked As Long
    hbmpUnchecked As Long
    dwItemData As Long
    dwTypeData As String
    cch As Long
End Type

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 GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long

Private Declare Function GetMenuString Lib "user32" Alias "GetMenuStringA" (ByVal hMenu As Long, ByVal wIDItem As Long, ByVal lpString As String, ByVal nMaxCount As Long, ByVal wFlag As Long) As Long

Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Long, lpMenuItemInfo As MENUITEMINFO) As Long

Private Const MF_BYCOMMAND = &H0&
Private Const MF_BYPOSITION = &H400&
Private Const MF_STRING = &H0&
Private Const MF_SEPARATOR = &H800&

Private Const MIIM_STATE = &H1
Private Const MIIM_ID = &H2
Private Const MIIM_SUBMENU = &H4
Private Const MIIM_CHECKMARKS = &H8
Private Const MIIM_TYPE = &H10
Private Const MIIM_DATA = &H20
Private Const MIIM_STRING = &H40
Private Const MIIM_BITMAP = &H80
Private Const MIIM_FTYPE = &H100

'---------------------------------------------------------------
' 関数名: EnumMenuString
' 機能  : メニュー文字列を列挙する
' 引数  : (in)hMenu … メニューのハンドル
' 返り値: なし
' 備  考:面倒なのでその場にDebug.Printしている。必要であれば
'         引数に配列を渡すなどして改造してください。
'---------------------------------------------------------------
Public Sub EnumMenuString(ByVal hMenu As Long)

    Dim MenuCount As Long
    Dim i As Long

    If hMenu = 0 Then Exit Sub

    'サブメニューのアイテムの数を取得
    MenuCount = GetMenuItemCount(hMenu)
    If MenuCount = (-1) Then Exit Sub

    'メニューの数だけループ
    For i = 0 To MenuCount - 1
        Dim udtMI As MENUITEMINFO

        '↓これでも可能だが、こうするとセパレータが空文字となってしまう
        'Dim MenuString >As String
        'Call GetMenuString(hMenu, i, MenuString, Len(MenuString), MF_BYPOSITION)
        'Debug.Print Left$(MenuString, InStr(MenuString, Chr$(0)) - 1)

        '面倒だが確実にセパレータを拾う場合はこっち
        'ということで MENUITEMINFO 構造体にせっせと値を設定
        With udtMI
            .cbSize = Len(udtMI)
            .fMask = MIIM_TYPE Or MIIM_STATE Or MIIM_DATA Or MIIM_ID Or _
                     MIIM_CHECKMARKS Or MIIM_SUBMENU
            .fType = MF_STRING
            .dwTypeData = String$(80, 0)
            .cch = Len(.dwTypeData)
        End With

        'メニュー情報取得
        Call GetMenuItemInfo(hMenu, i, True, udtMI)

        'セパレータである
        If (udtMI.fType And MF_SEPARATOR) = MF_SEPARATOR Then
            Debug.Print "------------------"
        'セパレータでない
        Else
            Debug.Print Left$(udtMI.dwTypeData, InStr(udtMI.dwTypeData, Chr$(0)) - 1)
        End If

        '再帰呼び出し(当該サブメニューの子メニュー検索)
        Call EnumMenuString(GetSubMenu(hMenu, i))
    Next i
End Sub

じゃあ、実行

Private Declare Function GetMenu Lib "user32" (ByVal hWnd As Long) As Long

Private Sub Command1_Click()

    Call EnumMenuString(GetMenu(Me.hWnd))

End Sub


戻る