The Hotkey Command Adds Immense Flexibility to AutoHotkey Scripts, But You Should Know How and When to Use It!
As I review the Hotkey command for my upcoming explorations, I note that it offers many capabilities which add flexibility and power to Hotkeys (and in some cases to Hotstrings). The advantage to the Hotkey instruction is that unlike the basic double-colon Hotkey definition (!#^h::command) which gets defined in the first phase of AutoHotkey file processing, it can run at any later time—either while loading in the auto-execute section or after the file loads in any subroutine or function.
* * *
New to AutoHotkey? See “Introduction to AutoHotkey: A Review and Guide for Beginners.”
* * *
Since the standard double-colon Hotkeys are defined at the same time as Hotstrings and the hashtag (#) directives in the initial AutoHotkey script loading scan (as discussed in an earlier blog), except for the Hotkey command, they would be etched into programming code—unchangeable once the script is loaded. (In fact, this is the case for Hotstrings which, once an app is running, don’t have the benefit of a similar corresponding command for Hotstring manipulation.) The inclusion of the Hotkey command (AutoHotkey’s namesake) turns the regular double-colon Hotkey (a huge part of what distinguishes AutoHotkey from AutoIt) into a flexible force for Windows automation. Understanding how and when to apply the Hotkey command is critical to making the best use of AutoHotkey Hotkeys in your scripts.
There are three forms of the Hotkey command:
Hotkey, KeyName [, Label, Options] Hotkey, IfWinActive/Exist [, WinTitle, WinText] Hotkey, If [, Expression]
The first form is by far the most flexible and useful allowing you to create or reassign Hotkeys, turn them off and on, assign subroutines (Labels) to them, and implement special AtlTab features. The second use (e.g. Hotkey, IfWinActive) is similar in form and effect to the #IfWinActive directive discussed in the previous blog. Finally, the last format (Hotkey, If) works in conjunction with the #If directive to create special conditional Hotkeys using expressions.
The Hotkey command offers so much that it’s difficult to know where to start. Therefore, I will continue with the Windows shortcut blocking action discussed in previous blogs, then diverge into other aspects of the Hotkey command in the future.
Last time, I used the GroupAdd command to place particular browser windows into a single group of shortcut-blocking Hotkeys preloaded by the context-sensitive #IfWinActive directive. The GroupAdd commands are later loaded in the auto-execute section of the script:
GroupAdd, BrowserGroup, ahk_class Chrome_WidgetWin_1 GroupAdd, BrowserGroup, ahk_class MozillaWindowClass GroupAdd, BrowserGroup, ahk_class ApplicationFrameWindow GroupAdd, BrowserGroup, ahk_class IEFrame #IfWinActive ahk_group BrowserGroup ^W::MsgBox Oops! You pressed CTRL+W !F4::MsgBox Oops! You pressed ALT+F4 ^F4::MsgBox Oops! You pressed CTRL+F4 #IfWinActive
The new group BrowserGroup created with the GroupAdd command accounts for Google Chrome (Chrome_WidgetWin_1), Mozilla Firefox (MozillaWindowClass), Microsoft Edge (ApplicationFrameWindow), and Internet Explorer (ahk_class IEFrame) windows. To add more programs to the shortcut blocking list, I merely add another line to the GroupAdd commands. This is a relatively simple way to create context-sensitive Hotkeys, but once loaded the directives cannot be directly modified.
The same blocking can be accomplished with the Hotkey command by removing the preloaded #IfWinActive directive and replacing it with the second form of the Hotkey command (Hotkey, IfWinActive):
GroupAdd, BrowserGroup, ahk_class Chrome_WidgetWin_1 GroupAdd, BrowserGroup, ahk_class MozillaWindowClass GroupAdd, BrowserGroup, ahk_class ApplicationFrameWindow GroupAdd, BrowserGroup, ahk_class IEFrame Hotkey, IfWinActive, ahk_group BrowserGroup Hotkey, ^W, Oops Hotkey, !F4, Oops Hotkey, ^F4, Oops Hotkey, IfWinActive Oops: MsgBox, Oops! You pressed %A_ThisHotkey% Return
Now, the snippet is composed entirely of AutoHotkey commands which only run after the initial scan of the AHK file. While this code most likely would appear in the auto-execute section in the beginning of the script, it could just as easily placed in a subroutine or function set to run later.
Just like the #IfWinAction directive, the Hotkey, IfWinActive command is positional. Meaning that after issuing the first command (Hotkey, IfWinActive, ahk_group BrowserGroup), it affects every following Hotkey command until a closing Hotkey, IfWinActive (or another similar active window limiting line) is encountered.
The three shortcut blocking keys, CTRL+W (^c), ALT+F4 (!F4), and CTRL+F4 (^F4), are bound between the two Hotkey, IfWinActive commands—each using the first form of the command to create a new Hotkey. The major difference between using the standard double-colon method for setting up Hotkeys and using the Hotkey command is that the command form cannot use other AutoHotkey commands. Rather, it calls a Label subroutine of commands which runs whenever the assigned keyboard combination is exercised. The Label subroutine must be available in the file at the time the Hotkey command is issued. (Fortunately, AutoHotkey throws a “Missing Label” error when you attempt to run the file without the called subroutine available.)
In the example above, each new Hotkey uses the same Label subroutine (Oops). They could just as easily each use a different Label (Oops1, Oops2, and Oops3), however, that would require writing three separate subroutines. By using the same Label whenever possible, the code is often shortened.
Writing an AutoHotkey Label
While a called AutoHotkey Label name never includes an added colon (Hotkey, ^W, Oops), the subroutine itself must append the colon (Opps:). The basic format for any Label subroutine includes its name followed by a colon (LabelName:), the subroutine code (starting on the next line), then terminates with the Return command on the last line:
Oops: MsgBox, Oops! You pressed %A_ThisHotkey% Return
In this case, the subroutine code consists of one MsgBox command which displays “Oops! You pressed ^W” (or whichever Hotkey combination you pressed). This introduces the built-in AutoHotkey variable A_ThisHotkey which stores the value of the Hotkey combination. By using the A_ThisHotkey variable the need for multiple lines of code and conditional Ifs is eliminated, but the result is a little more cryptic.
In the original script, the #IfWinActive directive allows us to directly add the MsgBox command to each Hotkey combination:
#IfWinActive ahk_group BrowserGroup ^W::MsgBox Oops! You pressed CTRL+W !F4::MsgBox Oops! You pressed ALT+F4 ^F4::MsgBox Oops! You pressed CTRL+F4 #IfWinActive
The term CTRL+W is certainly easier to grasp than ^W (at least when starting out). However, to emulate the same output with the Hotkey, IfWinActive command, we need to add If conditionals to the Oops: subroutine:
Oops: If A_ThisHotkey = ^W MsgBox Oops! You pressed CTRL+W If A_ThisHotkey = ^F4 MsgBox Oops! You pressed CTRL+F4 If A_ThisHotkey = !F4 MsgBox Oops! You pressed ALT+F4 Return
The A_ThisHotkey variable determines the value of the pressed Hotkey combination, then takes the appropriate action. Now it becomes clear how one Label subroutine can be tailored to act differently for each Hotkey combination.
Hotkey Command Tip: Unlike the use of basic double-colon Hotkeys, both the A_ThisHotkey variable and Hotkey command Label names in the Hotkey command are sensitive to the original order of the keys and their spelling in the initial setup. For example, if the combination initiates as ^!W, calling !^W with the first two modifiers reversed will not be reflected in the A_ThisHotkey variable—causing the above snippet of code to fail.
Changing the Purpose of a Hotkey for Each Program
In the previous example, we changed the output for different Hotkey combinations while using the same Label subroutine. Now, we’ll look at using the same Hotkey for different purposes with different classes of program windows. The setup for an #IfWinActive directive is as follows:
#IfWinActive, ahk_class Notepad ^y::MsgBox, This is Notepad! #IfWinActive, ahk_class Notepad++ ^y::MsgBox, This is Notepad++! #IfWinActive, ahk_class WordPadClass ^y::MsgBox, This is WordPad! #IfWinActive ^y::MsgBox, I'm not sure what this is!
The key combination CTRL+Y (^Y) changes Hotkey output for Notepad, Notepad++, WordPad, and, as a default, everything else (I’m not sure what this is!).
In most cases, I recommend applying this #Directive approach for adding Hotkeys to your scripts. It’s the simplest method usually requiring less code than resorting to the Hotkey command techniques. (At times, replicating basic double-colon Hotkey setups with the Hotkey command can get quite involved while providing less consistent results. Problems usually relate to the Hotkey command requirement that Labels rather than commands be called.) However, if you need to later modify (or turn off or on) an established Hotkey while the script is running, then the Hotkey command is the only tool for the job.
The same action as shown above can be replicated with the Hotkey command:
Hotkey, IfWinActive, ahk_class Notepad Hotkey, ^y, LabelNotepad Hotkey, IfWinActive, ahk_class Notepad++ Hotkey, ^y, LabelNotepadPlus Hotkey, IfWinActive, ahk_class WordPadClass Hotkey, ^y, LabelWordPad Hotkey, IfWinActive Hotkey, ^y, LabelOthers
The problem here is that each Hotkey definition requires the writing of a new Label subroutine. Plus, the A_ThisHotkey variable does not differentiate the Hotkeys since it always contains the same value (^y). If the Hotkeys are to remain unchanged throughout the script, then stick with the #IfWinActive directive. In fact, even if you later plan to change the output of some Hotkeys, there are a number of good reasons to start with the standard double-colon Hotkey definitions and #Directives. (These additional reasons will become more apparent as they are discussed in more detail in future blogs.) The Hotkey command is best reserved for those times when established Hotkey combinations must be altered or toggled during runtime.
Note: There are times when you might want to create temporary Hotkeys after a script is running. In that situation, the Hotkey command would certainly do the job. However, you could always create the Hotkeys in advance using the standard double-colon method, then later issue Hotkey commands turning them off in the auto-execute section of the script. That would allow you to turn them on and off with the Hotkey command without first creating them.
The major advantage to the Hotkey command is the flexibility it adds to your existing (preloaded) Hotkeys. For example, the function of established Hotkeys can be changed after the script is loaded:
Hotkey, IfWinActive, ahk_class Notepad Hotkey, ^y, WishWordPad Hotkey, IfWinActive Return ; In response to comment below WishWordPad: MsgBox, I wish this were WordPad! Return
This snippet of code changes the action of the already existing CTRL+Y (^y) key combination in any Notepad window. (If the Hotkey does not exist, it is created.) The Label subroutine WishWordPad contains the new action. The true power of the Hotkey command is in this interactive effect. Using this approach, the Hotkey output can be changed to any other action merely by changing the assigned Label.
Rather than creating new Hotkeys with the Hotkey command, as a matter of habit, use it to modify existing preset Hotkeys. Other advantages to this approach will become clear in future blogs.
Next time, we’ll look at a quick little script which turns your mouse wheel into a volume control and convert it to the Hotkey, If command format.