Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 310
  • Last Modified:

run time nested menu items?

Hi all...

I am in a big dilemma and i would need some of your suggestions.

I have an app where one of the menu items will have dynamically generated sub-menu items (collected from an array, etc.).

I figured how to make a control array in the menu editor, and I just set the captions and make those sub-menus visible or not.


The problem comes if I want to add a nested sub-menu to those dynamically generated sub-menus.

Here is a diagram to explain myself:


Tools(main menu item on the menu-bar)
|
|_Dynamic Sub01
|           |_Item A
|           |_Item B
|           |_Item C
|
|_Dynamic Sub02
|           |_Item A
|           |_Item B
|           |_Item C
|
|_Dynamic Sub03
            |_Item A
            |_Item B
            |_Item C



1. As you see, "Dynamic Sub01 - Dynamic Sub03" are my dynamically generated submenu items. Their caption (and how many of them) is set at runtime.

2. The nested sub-menus (Item A-Item C) of the "Submenu 01 - Submenu 03" have always the same captions for all Dynamic Submenus same order, etc. The only thing is they will point to different subs.

So I don't know what's the best strategy for this, where to start, etc.

As I said. I have the first part down already and running - that's the first level of "Dynamic Sub01 - Dynamic Sub03"... The problem are my nested sub-menus (Item A-Item C).

Examples are MORE than welcome!

Thanks a lot,
Gabi.
0
gabibucataru
Asked:
gabibucataru
  • 2
  • 2
1 Solution
 
JoaTexCommented:
Hi
Try this litle Program:

on Menu Editor Make this Menu:
Menu
Caption=Menu
Name = MenuTeste
Visible=false [Increase one Level]

...SubMenu1
Caption=1
Name=Menu1
index=1
Visible=True

...SubMenu2
Caption=2
Name=Menu1
index=2
Visible=True

...SubMenu3
Caption=3
Name=Menu1
index=3
Visible=True
OK

Code:

Option Explicit
Dim M As String
Dim N As Byte
Dim Subm(3)

Private Sub Form_Click()
   MenuTeste.Caption = M
   MenuTeste.Visible = True
   For N = 1 To 3
      Menu1(N).Caption = Subm(N)
      Menu1(N).Visible = True
   Next N
End Sub

Private Sub Form_Load()
   M = "Teste"
   Subm(1) = "Teste1"
   Subm(2) = "Teste2"
   Subm(3) = "Teste3"
End Sub

Hope this suite you
Jo
0
 
SweatCommented:
gabibucataru,

I searched on the newsgroups and found the following.  With it, you can dynamically create any number of first level menus and then any number of second level menus below those.  It's a bit complex and you should step through it all to be sure you understand it.

First.  On a new project, create a First level menu item.

Second.  Paste the following code inside the form:

Private Sub Form_Load()
    Call SubClassWnd(Form1.hwnd)
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Call UnSubClass(Form1.hwnd)
End Sub

Third.   Add a new module to the project, just a standard module and paste this code into it:

Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
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 CreatePopupMenu Lib "user32" () As Long
Private 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
Private Declare Function DestroyMenu Lib "user32" (ByVal hMenu As Long) As Long

Dim OldProc As Long
Dim NewMenu As Long

Private Type typProcInf
    piHandle As Long
    piProc As Long
End Type

Private Const GWL_WNDPROC = (-4)
Private Const WM_COMMAND = &H111

' A bunch of menu styles for you
Private Const MF_ENABLED = &H0&
Private Const MF_GRAYED = &H1&
Private Const MF_DISABLED = &H2&
Private Const MF_CHECKED = &H8&
Private Const MF_SEPARATOR = &H800&
Private Const MF_POPUP = &H10&

Private Const BaseMenu = &H100

Public Function SubClassWnd(inWnd As Long) As Boolean
    Dim hMenu As Long

    'Get the existing menu handle
    hMenu = GetMenu(inWnd)

    ' Get the first menu (Try commenting this line to see why it's here)
'    hMenu = GetSubMenu(hMenu, 0)

    ' Create a new menu
    NewMenu = CreatePopupMenu()

<<<<<>>>>>
This will create the first level menu next to the menu
you created originally.  With each appendmenu, you are
creating the sub items within the new first level menu.
<<<<<>>>>>
    ' Add some items to our new menu
    AppendMenu NewMenu, MF_ENABLED, BaseMenu, "One"
    AppendMenu NewMenu, MF_ENABLED, BaseMenu + 1, "Two"
    AppendMenu NewMenu, MF_SEPARATOR, BaseMenu + 2, "-"
    AppendMenu NewMenu, MF_CHECKED, BaseMenu + 3, "Three"

    ' Add the menu to the existing one
    AppendMenu hMenu, MF_POPUP, ByVal NewMenu, "New menu"

<<<<<>>>>>
This creates another instance of the first level menu
next to the one above which was dynamically created.
Continue in your loop or however many menus you need until
you are done
<<<<<>>>>>
    ' Create a new menu
    NewMenu = CreatePopupMenu()

    ' Add some items to our new menu
    AppendMenu NewMenu, MF_ENABLED, BaseMenu, "One-One"
    AppendMenu NewMenu, MF_ENABLED, BaseMenu + 1, "Two-Two"
    AppendMenu NewMenu, MF_SEPARATOR, BaseMenu + 2, "-"
    AppendMenu NewMenu, MF_CHECKED, BaseMenu + 3, "Three-Three"

    ' Add the menu to the existing one
    AppendMenu hMenu, MF_POPUP, ByVal NewMenu, "Another New menu"

    ' Sub-class the window
    OldProc = SetWindowLong(inWnd, GWL_WNDPROC, AddressOf WndProc)
End Function

Public Function UnSubClass(inWnd As Long) As Long
    ' Destroy the custom menu
    Call DestroyMenu(NewMenu)

    ' Un-sub-class the window
    SetWindowLong inWnd, GWL_WNDPROC, OldProc
End Function

Public Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As Long
    If (uMsg = WM_COMMAND) Then ' Command item was selected from the menu
        Select Case ((wParam And &HFFFF) - BaseMenu) ' Item index
            Case 0: MsgBox "Clicked ""One"""
            Case 1: MsgBox "Clicked ""Two"""
            Case 2: MsgBox "Clicked seperator" ' Shouldn't ever fire
            Case 3: MsgBox "Clicked ""Three"""
        End Select
    End If

    ' Send everything past default WndProc() too
    WndProc = CallWindowProc(OldProc, hwnd, uMsg, wParam, lParam)
End Function


Credit for this solution goes to:
    Mike
 - Microsoft Visual Basic MVP -
WWW: Http://EDais.earlsoft.co.uk/
Work E-Mail: EDais@btclick.com
Other E-Mail: Mike.Sutton@btclick.com

from the:
microsoft.public.vb.general.discussion
newsgroup

Sweat


0
 
gabibucataruAuthor Commented:
Great example!!!! outstanding!
0
 
gabibucataruAuthor Commented:
Awsome!!! Outstanding answer!!!!
0
 
SweatCommented:
Gabi,

Thank you.  Just trying to help.

Sweat

0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now