Dynamic menu

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Calvin
Posts: 48
Joined: 22 Jul 2016, 01:11

Dynamic menu

01 Mar 2019, 08:03

Hallo

I try to bouid a menu dynamic.

Code: Select all

arrMenu[] := ["Menu 1", "Text to Menu 1", "Menu 2", "Text to menu 2"]

loop % arrMenu.MaxIndex()
{
	if (A_Index & 1) and !(A_Index =1) ; Check LSB: if set it's odd
	{

	Menu, FileMenu, Add, arrMenu[A_index], arrMenu[A_index]
	}
}

Menu, MyMenuBar, Add, &File, :FileMenu
Menu, MyMenuBar, Add, &Help, :HelpMenu

; Attach the menu bar to the window:
Gui, Menu, MyMenuBar
I like to make menu points from the array, but how ?

And what about make labels the menu points are calling.

I don´t know how to make dynamic labels:

Menu_point_1:
code

Menu_point_2:
Diffent code

??
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

01 Mar 2019, 10:34

Hello

An example:

Code: Select all

oMenu := {Main:[ {text: "Item1", icon: "Shell32,45", label: "MenuHandler1"}
               , {text: "Item2", icon: "Shell32,46", label: "MenuHandler1"}
               , {}
               , {text: "Item3", icon: "Shell32,47", label: {SubMenu:[ {text: "Item1", icon: "Shell32,48", label: "MenuHandler2"} 
                                                                     , {text: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
menuName := CreateMenu(oMenu)
Menu, % menuName, Show
Return

CreateMenu(oMenu) {
   for k, v in oMenu {
      for i, v in v {
         if !IsObject(v.label)
            Menu, % k, Add, % v.text, % v.label
         else 
            Menu, % k, Add, % v.text, % ":" CreateMenu(v.label)
         if v.icon {
            RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
            Menu, % k, Icon, % v.text, % _file, % _num
         }
      }
   }
   Return k
}

MenuHandler1() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

MenuHandler2() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}
Last edited by teadrinker on 02 Mar 2019, 08:09, edited 2 times in total.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Dynamic menu

01 Mar 2019, 10:55

@teadrinker, that is very nice! Thank you for sharing it.
Regards, burque505
Calvin
Posts: 48
Joined: 22 Jul 2016, 01:11

Re: Dynamic menu

01 Mar 2019, 12:51

Thank you - nice code.
Calvin
Posts: 48
Joined: 22 Jul 2016, 01:11

Re: Dynamic menu

01 Mar 2019, 13:19

Sorry but I´m a noobie.

I can see that you code works fine. But how does it fit into my menu

Code: Select all

; Create the sub-menus for the menu bar:
Menu, FileMenu, Add, &Windows7, Windows7
Menu, FileMenu, Add, &Windows8, Windows8
Menu, FileMenu, Add  ; Separator line.
Menu, FileMenu, Add, &Windows10, Windows10
Menu, HelpMenu, Add, &About, HelpAbout

; Create the menu bar by attaching the sub-menus to it:
Menu, MyMenuBar, Add, &File, :FileMenu
Menu, MyMenuBar, Add, &Help, :HelpMenu

; Attach the menu bar to the window:
Gui, Menu, MyMenuBar

Gui, +Resize  ; Make the window resizable.
Gui, add, text , vTextSpace WantTab W600 R20, %strGlobalWelcomeText%
Gui, Show,, Untitled

How do I get you fine code into this ?
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

02 Mar 2019, 07:48

It could be done like this:

Code: Select all

oMenu := {MyMenuBar: [ {text: "&File", label: {FileMenu: [ {text: "&Windows7",  icon: "", label: "Windows7"}
                                                         , {text: "&Windows8",  icon: "", label: "Windows8"}
                                                         , {} ; separator
                                                         , {text: "&Windows10", icon: "", label: "Windows10"} ]}}
                     , {text: "&Help", label: {HelpMenu: [ {text: "&About",     icon: "", label: "HelpAbout"} ]}} ]}
                     
Gui, +Resize  ; Make the window resizable.
Gui, Menu, % CreateMenu(oMenu)
Gui, Add, Text, vTextSpace WantTab W600 R20, %strGlobalWelcomeText%
Gui, Show,, Untitled
Return

GuiClose:
   ExitApp
                   
Windows7() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Windows8() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Windows10() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

HelpAbout() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}
                   
CreateMenu(oMenu) {
   for k, v in oMenu {
      for i, v in v {
         if !IsObject(v.label)
            Menu, % k, Add, % v.text, % v.label
         else 
            Menu, % k, Add, % v.text, % ":" CreateMenu(v.label)
         if v.icon {
            RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
            Menu, % k, Icon, % v.text, % _file, % _num
         }
      }
   }
   Return k
}
I changed the CreateMenu() function slightly to support separators.
Calvin
Posts: 48
Joined: 22 Jul 2016, 01:11

Re: Dynamic menu

02 Mar 2019, 10:24

Thanks again. :-)
Ecimeric
Posts: 130
Joined: 11 Jan 2017, 02:23

Re: Dynamic menu

02 Jun 2021, 22:45

Code: Select all

RunProgram := Func("Run").Bind("program.exe")
oMenu := {Main:[ {name: "Item1", icon: "Shell32,45", label: RunProgram}
               , {name: "Item2", icon: "Shell32,46", label: "MenuHandler1"}
               , {}
               , {name: "Item3", icon: "Shell32,47", label: {SubMenu:[ {name: "Item1", icon: "Shell32,48", label: "MenuHandler2"} 
                                                                     , {name: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
Run(Target) {
    Run, % Target
    return
}
How can I replace MenuHandler1 with a BoundFunc object?
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

03 Jun 2021, 00:15

Like this:

Code: Select all

RunProgram := Func("Run").Bind("program.exe")
oMenu := {Main:[ {name: "Item1", icon: "Shell32,45", label: RunProgram}
...
RunProgram is a BoundFunc object.
Ecimeric
Posts: 130
Joined: 11 Jan 2017, 02:23

Re: Dynamic menu

03 Jun 2021, 00:30

Code: Select all

            Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
That's what I thought; however, I get a Submenu does not exist error at this line.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

03 Jun 2021, 05:08

Show your full code.
Ecimeric
Posts: 130
Joined: 11 Jan 2017, 02:23

Re: Dynamic menu

03 Jun 2021, 12:29

Code: Select all

RunCalc := Func("Run").Bind("calc.exe")
oMenu := {Main:[ {name: "Item1", icon: "Shell32,45", label: RunCalc}
               , {name: "Item2", icon: "Shell32,46", label: "MenuHandler1"}
               , {}
               , {name: "Item3", icon: "Shell32,47", label: {SubMenu:[ {name: "Item1", icon: "Shell32,48", label: "MenuHandler2"} 
                                                                     , {name: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
menuName := CreateMenu(oMenu)
Menu, % menuName, Show
Return

CreateMenu(oMenu) {
   for k, v in oMenu {
      for i, v in v {
         if !IsObject(v.label)
            Menu, % k, Add, % v.name, % v.label
         else 
            Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
         if v.icon {
            RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
            Menu, % k, Icon, % v.name, % _file, % _num
         }
      }
   }
   Return k
}

MenuHandler1() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

MenuHandler2() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Run(Target) {
    Run, % Target
    return
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

03 Jun 2021, 13:41

Code: Select all

RunCalc := Func("Run").Bind("calc.exe")
oMenu := {Main:[ {name: "Item1", icon: "Shell32,45", label: RunCalc}
               , {name: "Item2", icon: "Shell32,46", label: "MenuHandler1"}
               , {}
               , {name: "Item3", icon: "Shell32,47", label: {SubMenu:[ {name: "Item1", icon: "Shell32,48", label: "MenuHandler2"} 
                                                                     , {name: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
menuName := CreateMenu(oMenu)
Menu, % menuName, Show
Return

CreateMenu(oMenu) {
   for k, v in oMenu {
      for i, v in v {
         if !IsObject(v.label)
            Menu, % k, Add, % v.name, % v.label
         else if (v.label.Count() = "") {
            handler := v.label
            Menu, % k, Add, % v.name, % handler
         }
         else 
            Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
         if v.icon {
            RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
            Menu, % k, Icon, % v.name, % _file, % _num
         }
      }
   }
   Return k
}

MenuHandler1() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

MenuHandler2() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Run(Target) {
    Run, % Target
    return
}
Ecimeric
Posts: 130
Joined: 11 Jan 2017, 02:23

Re: Dynamic menu

03 Jun 2021, 13:55

Thank you; this will make my menu code much leaner :thumbup:
Ecimeric
Posts: 130
Joined: 11 Jan 2017, 02:23

Re: Dynamic menu

11 Jun 2021, 13:54

Tell me if I should create a new topic, but I am wondering how I might specify conditions in oMenu that determine if an item or menu are displayed or disabled; ie:
  1. Code: Select all

    if (displayconditions)
        Menu, % k, Add, % v.name, % handler
  2. Code: Select all

    if (displayconditions)
        Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
  3. Code: Select all

    if (disableconditions)
        Menu, % k, Disable, % v.name
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

11 Jun 2021, 15:37

I added two extra options: disabled and hidden.

Code: Select all

RunCalc := Func("Run").Bind("calc.exe")
oMenu := {Main:[ {name: "This menu will be disabled", icon: "Shell32,45", disabled: true, label: RunCalc}
               , {name:  "This menu won't be shown" , icon: "Shell32,46", hidden:   true, label: "MenuHandler1"}
               , {}
               , {name: "Item3", icon: "Shell32,47", label: {SubMenu:[ {name: "Item1", icon: "Shell32,48", label: "MenuHandler2"} 
                                                                     , {name: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
menuName := CreateMenu(oMenu)
Menu, % menuName, Show
Return

CreateMenu(oMenu) {
   for k, v in oMenu {
      for i, v in v {
         if v.hidden
            continue
         if !IsObject(v.label)
            Menu, % k, Add, % v.name, % v.label
         else if (v.label.Count() = "") {
            handler := v.label
            Menu, % k, Add, % v.name, % handler
         }
         else 
            Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
         if v.disabled
            Menu, % k, Disable, % v.name
         if v.icon {
            RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
            Menu, % k, Icon, % v.name, % _file, % _num
         }
      }
   }
   Return k
}

MenuHandler1() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

MenuHandler2() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Run(Target) {
    Run, % Target
    return
}
Ecimeric
Posts: 130
Joined: 11 Jan 2017, 02:23

Re: Dynamic menu

11 Jun 2021, 16:37

Excellent, thank you! Is hidden: (!FileExist("X:\") ? true : "") how you would specify any conditions?
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

11 Jun 2021, 17:17

Perhaps like this:

Code: Select all

hidden: !FileExist("X:\")
gregster
Posts: 8921
Joined: 30 Sep 2013, 06:48

Re: Dynamic menu

16 Jun 2021, 06:35

This was erroneously posted by an anonymous user as a report for this post (instead of making a regular post):
Anonymous wrote:It will be Error when the BoundFunc in the SubMenu ,like this:

Code: Select all

RunCalc := Func("Run").Bind("calc.exe")
oMenu := {Main:[ {name: "Item1", icon: "Shell32,45", label: RunCalc}
, {name: "Item2", icon: "Shell32,46", label: "MenuHandler1"}
, {}
, {name: "Item3", icon: "Shell32,47", label: {SubMenu:[ {name: "Item1", icon: "Shell32,48", label: "RunCalc"}
, {name: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
menuName := CreateMenu(oMenu)
Menu, % menuName, Show
Return

CreateMenu(oMenu) {
for k, v in oMenu {
for i, v in v {
if !IsObject(v.label)
Menu, % k, Add, % v.name, % v.label
else
Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
if v.icon {
RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
Menu, % k, Icon, % v.name, % _file, % _num
}
}
}
Return k
}

MenuHandler1() {
MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

MenuHandler2() {
MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Run(Target) {
Run, % Target
return
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Dynamic menu

16 Jun 2021, 07:56

gregster wrote:
Anonymous wrote:

Code: Select all

label: "RunCalc"
RunCalc shouldn't be enclosed in quotes since it's an object, must be label: RunCalc.

Code: Select all

RunCalc := Func("Run").Bind("calc.exe")
oMenu := {Main:[ {name: "Item1", icon: "Shell32,45", label: RunCalc}
               , {name: "Item2", icon: "Shell32,46", label: "MenuHandler1"}
               , {}
               , {name: "Item3", icon: "Shell32,47", label: {SubMenu:[ {name: "Item1", icon: "Shell32,48", label: RunCalc}
                                                                     , {name: "Item2", icon: "Shell32,49", label: "MenuHandler2"} ]}} ]}
menuName := CreateMenu(oMenu)
Menu, % menuName, Show
Return

CreateMenu(oMenu) {
   for k, v in oMenu {
      for i, v in v {
         if v.hidden
            continue
         if !IsObject(v.label)
            Menu, % k, Add, % v.name, % v.label
         else if (v.label.Count() = "") {
            handler := v.label
            Menu, % k, Add, % v.name, % handler
         }
         else 
            Menu, % k, Add, % v.name, % ":" CreateMenu(v.label)
         if v.disabled
            Menu, % k, Disable, % v.name
         if v.icon {
            RegExMatch(v.icon, "(?<file>[^,]+)(,(?<num>.+))?", _)
            Menu, % k, Icon, % v.name, % _file, % _num
         }
      }
   }
   Return k
}

MenuHandler1() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

MenuHandler2() {
   MsgBox, % "This Menu: " . A_ThisMenu . "`nMenu Item: " . A_ThisMenuItem
}

Run(Target) {
   Run, % Target
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: tiska and 106 guests