Code: Select all
{ ;Multitier_Popup_Menu_From_CSV_Example.v2.ahk - v2 -
; Language: English
; Platform: Windows11
; Script Function: Example of how to build a multitier menu from a CSV data string
; REFERENCE: https://www.autohotkey.com/docs/v2/lib/Menu.htm
; NOTES: I am not sure how many levels of submenus are allowed in version 2.
; I believe that in version 1.1 submenus were limited to 6 levels.
; Use [View] - [Toggle All Folds] in SciTE4AutoHotkey
}
{ ;DIRECTIVES AND SETTINGS
#Requires AutoHotkey >=2.0-<2.1
#SingleInstance Force ; Recommended so only one copy is runnnig at a time
aMenus := [] ; DEFINE ARRAY aMenus TO HOLD sMenus DATA
MyMenu := Map() ; DEFINE Map() MyMenu TO HOLD MENU ENTRIES
MyMenu.CaseSense := "Off" ; TURN Off CASE SENSITIVITY FOR MENU (1 TO 8 x FASTER THAN Locale)
; - GET DATA -
sMenus := csvdata() ; READ MENU CSV DATA csvdata() AS A STRING INTO sMenus
csvs2a(sMenus,&aMenus) ; CONVERT sMenus TO AN ARRAY aMenus
;csva2lv("aMenus", aMenus,bMyHeader := false) ;DEBUG - SHOW aMenus IN A LISTVIEW TO CONFIRM THE CONVERSION
; - BUILD MENU -
MyMenuName := BuildMyMenu(&aMenus, &MyMenu) ;BUILD MENU (MyMenu) FROM aMenu RETURNS MyMenuName
Loop { ;ENDLESS LOOP - CHOOSE AND ENTRY AND FOLLOW INSTRUCTIONS TO EXIT
MyMenu[MyMenuName].Show()
}
Return
} ;MAIN PROGRAM - ENDS HERE *******************************************************************************************
BuildMyMenu(&aMenus, &MyMenu) { ;BUILD MyMenu FROM aMenus
for row in aMenus {
RowLength := row.Length
RowNumber := A_Index
Loop RowLength {
if (A_Index == 1) { ;A_Index == 1
if (!MyMenu.Has(row[A_Index])) { ;IF MyMenu DOES NOT CONTAIN row[1] THEN DEFINE MyMenu[row[1]]
MainName := row[A_Index]
MyMenu[MainName] := Menu()
}
} else { ;A_Index > 1
ParentName := row[(A_Index - 1)]
ChildName := row[A_Index]
if (!MyMenu.Has(ParentName)) { ;IF MyMenu DOES NOT CONTAIN ParentName THEN DEFINE ParentName AS Menu()
MyMenu[ParentName] := Menu()
}
if (!MyMenu.Has(ChildName)) { ;IF MyMenu DOES NOT CONTAIN ChildName THEN DEFINE ChildName AS Menu()
MyMenu[ChildName] := Menu()
if (A_Index < RowLength) { ;IF A_Index < RowLength THEN ADD ChildName,MyMenu[ChildName] TO ParentName
MyMenu[ParentName].Add(ChildName,MyMenu[ChildName])
}
}
if (A_Index == RowLength) { ;IF A_Index == RowLength THEN ADD ChildName, MenuHandler TO ParentName
MyMenu[ParentName].Add(ChildName, MenuHandler)
}
}
}
}
return MainName
}
csvdata() { ;CSV DATA - MENU EXAMPLE
;NOTE: THE AMPERSANDS ARE NOT NECESSARY BUT ALLOW YOU TO WALK THROUGH THE MENU USING KEYSTROKES
sMyCSV := "
( Ltrim Join`n
Main
Main,Main &1
Main,Main &2,Sub 2&a
Main,Main &2,Sub 2&b,Sub 2b&1
Main,Main &2,Sub 2&b,Sub 2b&2
Main,Main &2,Sub 2&b,Sub 2b&3
Main,Main &2,Sub 2&c
Main,Main &3
Main,Main &4,Sub 4&a
Main,Main &4,Sub 4&b
Main,Main &5
)"
return(sMyCSV)
}
csvdata2() { ;CSV DATA VERSION 2 - MENU EXAMPLE
;NOTE: TO RUN: IN MAIN PROGRAM - REPLACE sMenus := csvdata() WITH sMenus := csvdata2()
; EXAMPLE WITHOUT AMPERSANDS
sMyCSV := "
( Ltrim Join`n
Main
Main,Main 1
Main,Main 2,Sub 2a
Main,Main 2,Sub 2b,Sub 2b1
Main,Main 2,Sub 2b,Sub 2b2
Main,Main 2,Sub 2b,Sub 2b3
Main,Main 2,Sub 2c
Main,Main 3
Main,Main 4,Sub 4a
Main,Main 4,Sub 4b
Main,Main 5
)"
return(sMyCSV)
}
csvs2a(sMyCSV,&aMyCSV) { ;CSV STRING TO ARRAY: Convert sCSV (string) to aCSV (array)
aMyCSV := []
Loop Parse sMyCSV, "`n`r" {
aElements := []
Loop Parse A_LoopField, ","
aElements.Push(A_LoopField)
aMyCSV.Push(aElements)
}
}
csva2lv(MyTitle,aMyCSV,bMyHeader := true) { ;CSV ARRAY TO LISTVIEW:
;INPUTS: Title (String), aMyCSV (Array), bHeader (Bolean).
;OUTPUT: Shows aMyCSV (array) in a listview.
; NOTE: IF bHeader=true use header
MyGui := gui(,MyTitle)
for row in aMyCSV {
if (A_Index = 1) {
if (bMyHeader = true)
lv := MyGui.addListView("", [row*]) ;NOTE: "row" could be used in place of [row*].
else {
MaxRowLength := 0
for row in aMyCSV {
RowLength := row.Length
if (RowLength > MaxRowLength)
MaxRowLength := RowLength
}
HeaderWidth := Floor(RowLength/10) + 1
sFormat := "COL{1:0" . HeaderWidth . "i}"
aHeader := []
Loop MaxRowLength {
aHeader.Push(Format(sFormat, A_Index))
}
lv := MyGui.addListView("", [aHeader*])
lv.Add("", row*)
}
} else {
lv.Add("", row*)
}
}
MyGui.show("x100 y100 w300")
MsgBox "Close to continue"
MyGui.Destroy()
return
}
MenuHandler(ItemName, *) { ;MENU HANDLER FOR VALID SELECTIONS
MsgBox("You selected: " . ItemName . "`n`nPUSH <ESC> TO EXIT", "Info", 0+64+0+4096)
}
Esc:: { ;<ESC> IS HOTKEY TO EXIT APPLICAITON
ExitApp
Return
}