Add Submenus to the Auto-Startup Menu to Increase Options (AutoHotkey Startup Control)

Submenus Allow AutoHotkey Users to Add Features to Apps Without Needing More Screen Space

Last time in “Adding Startup Folder Shortcuts to a System Tray Menu,” I inserted the Startup folder shortcuts into a System Tray right-click menu. This gave me a method for quickly accessing an auto-load script even when it doesn’t display an icon in the System Tray.

A click of the menu item either opens the script (.ahk) in Notepad or opens the target folder for a compiled executable (.exe) file. While the original menu does the basic job of keeping track of the auto-startup scripts, it only executes one action—opening a script or folder. To expand the capabilities of the Startup Control, we need to add submenus.

Basic Menu Limitations

I use menus extensively in a number of my scripts. (QuickLinks, SynonymLookup, etc). Menus pop-up without interfering with other activities, quickly accessing a variety of tasks, then disappear out of view. However, when implementing basic AutoHotkey menu structures, you live with serious limitations for passing data. The menu structure only offers three built-in variables and no easy method for adding more.

The built-in variables A_ThisMenuItem and A_ThisMenuItemPos contain the name and position of the custom menu item most recently selected by the user (blank if none). Similarly, A_ThisMenu is the name of the menu from which A_ThisMenuItem was selected. These variables are useful when building a menu whose contents are not always the same. In such a case, it is usually best to point all such menu items to the same label and have that label refer to the above variables to determine what action to take.

AutoHotkey Documentation

In the past, I either added extra data to the menu item text (i.e. the A_ThisMenuItem variable), later parsing the result to extract the needed data (e.g. the EmojiMenu.ahk script), or used the function BoundFunc Object to bind alternative variable data to a menu item. (See “Increase the Flexibility of Menus by Passing Data with the BoundFunc Object.”) But, making do in a script with the built-in menu variables saves a great deal of time and a number of complications.

Fortunately for this Startup Control application, the information needed for most actions resides in the Windows shortcuts sitting in the Startup folder. Accessible through the FileGetShortcut command, the name of the shortcut enables AutoHotkey to extract all that embedded data—including the path and filename of the target program, or script, plus icon information.

Using the Windows Shortcut Name

In the main File Loop (discussed last time), I assigned the Windows shortcut’s filename to the top-level System Tray icon context menu as a menu item (A_ThisMenuItem). Then, whenever right-clicking on the icon and selecting a menu item, AutoHotkey immediately accessed that filename using that built-in variable. This made it easy to locate the shortcut file and extract the information in the MenuAction subroutine:

MenuAction:
    Shortcut := A_Startup "/" A_ThisMenuItem
    FileGetShortcut, %A_Startup%/%A_ThisMenuItem%
            , Location
    If InStr(Location,".ahk")
        Run, Notepad %Location%
    If InStr(Location,".exe")
    {
        explorerpath := "explorer /select," Location
        Run, %explorerpath%
    }
Return

No special programming gymnastics needed.

However, this time I plan to access the same routine via a submenu item. I could possibly give the submenu item the same name as the top menu item but that would cause considerable confusion when adding more submenu items for other features. I don’t see a built-in AutoHotkey variable for returning the top menu’s item name.

Taking advantage of the built-in A_ThisMenu variable, I assign the shortcut filename to the name of the submenu. This allows me directly access the shortcut filename without using it as a redundant submenu item name—which would generate an error.

To add a submenu, first build the submenu as a separate structure:

Menu, [Shortcut Filename], Add, Open, MenuAction
Menu, [Shortcut Filename], Add, Reload, ProgRestart

Next, attach it to a top-level menu item using the same name as assigned to the submenu:

Menu, Tray, Add , [Shortcut Filename], :[Shortcut Filename]

This trick makes the shortcut filename readily available by using it for both the top-level menu item name and the submenu name. Whenever I click a submenu item, the built-in variable (A_ThisMenu) holds the target shortcut’s filename. The modification to the Startup folder loop only needed the redundant use of the A_LoopFileName variable:

files := ""
Loop %A_Startup%\*.*
{
	FileGetShortcut, %A_LoopFileFullPath%
                , Location
                , OutDir
                , OutArgs
                , OutDescription
                , OutIcon
                , OutIconNum
                , OutRunState
	If ErrorLevel
		Continue
	files = %files%%Location%`n%A_LoopFileName%`n
	Menu, %A_LoopFileName%, Add, Open, MenuAction
	Menu, %A_LoopFileName%, Add, Restart, ProgRestart
	Menu, Tray, Add, %A_LoopFileName%, :%A_LoopFileName%
	If (OutIcon != "")
            Menu, Tray, Icon, %A_LoopFileName%
                , %OutIcon%, %OutIconNum%
}
Menu, Tray, Icon, Shell32.dll, 85
Return

Lines 15 and 16 create the submenu while line 17 attaches it to the top-level.

A Couple of Helpful Commands

In the course of testing, I noted a couple of error messages hindering the running of the script during reloading. Two statements eliminated aggravating error messages.

Submenu Subroutine for Restarting AutoHotkey Scripts

On occasion, I’ve noticed that an AutoHotkey icon or two may disappear from the System Tray. (Go figure!) The scripts continue to run and function, yet I can no longer access the associated right-click menu. (I assume that it’s a bug in Windows 10 but I have no idea how to fix it.) Generally, I reload the script to bring back the icon and its menu, but that usually requires me to open the Startup or home folder to relaunch it.

Now that I have a basic Startup Control script, I can add a subroutine for restarting any of the listed programs or scripts. I found the following code in the AutoHotkey RunAs documentation and modified it to force the restart of any targeted program (.exe) or script (.ahk):

ProgRestart:
FileGetShortcut, %A_Startup%/%A_ThisMenu%, Location
If InStr(Location,".ahk")
    Run *RunAs "%A_AhkPath%" /restart "%Location%"
If InStr(Location,".exe")
     Run *RunAs "%Location%" /restart
Return

This reliably restores any System Tray icon loaded by the Startup folder.

It also works for the AutoStartupControl.ahk script—except when its icon disappears. For that instance, I added the Hotkey combination CTRL+WIN+5:

^#5::Reload

Since the Reload command does not initiate an administrator’s action warning, the Hotkey combination has an advantage over clicking the System Tray Restart menu item.

I’ve posted the current version of the AutoStartupControl.ahk script.

Click the Follow button at the top of the sidebar on the right of this page for e-mail notification of new blogs. (If you’re reading this on a tablet or your phone, then you must scroll all the way to the end of the blog—pass any comments—to find the Follow button.)

jack

This post was proofread by Grammarly
(Any other mistakes are all mine.)

(Full disclosure: If you sign up for a free Grammarly account, I get 20¢. I use the spelling/grammar checking service all the time, but, then again, I write a lot more than most people. I recommend Grammarly because it works and it’s free.)

Find my AutoHotkey books at ComputorEdge E-Books!

Find quick-start AutoHotkey classes at “Robotic Desktop Automation with AutoHotkey“!

2 thoughts on “Add Submenus to the Auto-Startup Menu to Increase Options (AutoHotkey Startup Control)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s