Wrapping Menus

In an application, when we try to add more submenus for a menu item, some of the submenus may not be displayed if they cross the screen boundary. There is a work around to show all the menus by wrapping. We have to use some dlls to achieve this.

Lets try the following example. Lets say we would like to create 40 submenus under a menu called 'Test Menu'. Create this 'Test Menu' using menu editor, under this one create a sub menu, call it as 'Sample Menu', set its index to 0.

'*** Include the following statements in declaration
Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Boolean, lpmii As MENUITEMINFO) As Long
Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA" (ByVal hMenu As Long, ByVal uItem As Long, ByVal fByPosition As Long, lpmii As MENUITEMINFO) As Long

Const MIIM_TYPE = &H10
Const MIIM_DATA = &H20
Const MFT_RADIOCHECK = &H200&
Const RGB_STARTNEWCOLUMNWITHVERTBAR = &H20&
Const RGB_STARTNEWCOLUMN = &H40&
Const MFT_STRING = &H0&

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

'*** Include the following statements in the form load event, this will create 40 sub menus for menu 'Test Menu'
Public Sub Form_Load()
    Dim i%
    For i = 1 To 40
        Load Form1.mnuFontNames(i)
        Form1.mnuFontNames(i).Caption = "Sample Menu " & i
    Next
End Sub

'Place a command button and write the following statements in the click event of the command button, this is to wrap the sub menus.

Public Sub Command1_Click()
    Dim i As Integer
    Dim r As Long
    Dim hSubMenu As Long
    Dim mInfo As MENUITEMINFO

    'Get the handle of the sub menu
    hSubMenu = GetSubMenu(GetMenu(Form1.hwnd), 0)

    'Set the necessary attributes
    mInfo.cbSize = Len(mInfo)
    mInfo.fMask = MIIM_TYPE
    mInfo.fType = MFT_STRING
    mInfo.dwTypeData = Space$(256)
    mInfo.cch = Len(mInfo.dwTypeData)

    'Get the menu information of the 30th menu from which we need a break and wrap
    r = GetMenuItemInfo(hSubMenu, 30, True, mInfo)

    'modify it's attributes for the 30th menu, telling the menu to insert a break
    'before the member in the MENUITEMIFO structure.
    mInfo.fType = RGB_STARTNEWCOLUMNWITHVERTBAR

    'we just want to change the style, so reset fMask
    mInfo.fMask = MIIM_TYPE

    'add a break
    r = SetMenuItemInfo(hSubMenu, 30, True, mInfo)
End Sub

When the form is loaded, it will create 40 menus. If the user clicks the command button, it will insert a break at the 30th menu and wraps the remaining in the next column.