#HotIf

Creates context-sensitive hotkeys and hotstrings. Such hotkeys perform a different action (or none at all) depending on any condition (an expression).

#HotIf Expression

Parameters

Expression

Type: Boolean

Any valid expression. This becomes the return value of an implicit function which has one parameter (ThisHotkey). As with hotkey functions, variable references are local by default, so to use a global variable, declare it outside of the expression.

Basic Operation

The #HotIf directive sets the expression which will be used by subsequently created hotkeys to determine whether they should activate. This expression is evaluated when the key, mouse button or combination is pressed, or at other times when the program needs to know whether the hotkey is active.

To make context-sensitive hotkeys and hotstrings, simply precede them with the #HotIf directive. For example:

global MyWinTitle := "Example window title"
#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle)
#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle

The #HotIf directive is positional: it affects all hotkeys and hotstrings physically beneath it in the script, until the next #HotIf directive.

Note: Unlike if statements, braces have no effect with the #HotIf directive.

To turn off context sensitivity, specify #HotIf without any expression. For example:

#HotIf

When a mouse or keyboard hotkey is disabled via #HotIf, it performs its native function; that is, it passes through to the active window as though there is no such hotkey. There is one exception: Joystick hotkeys: although #HotIf works, it never prevents other programs from seeing the press of a button.

#HotIf can also be used to alter the behavior of an ordinary key like Enter or Space. This is useful when a particular window ignores that key or performs some action you find undesirable. For example:

#HotIf WinActive("Reminders ahk_class #32770")  ; The "reminders" window in Outlook.
Enter::Send "!o"  ; Have an "Enter" keystroke open the selected reminder rather than snoozing it.
#HotIf

Variant (Duplicate) Hotkeys

A particular hotkey or hotstring can be defined more than once in the script if each definition has different #HotIf criteria. These are known as hotkey variants. For example:

#HotIf WinActive("ahk_class Notepad")
^!c::MsgBox "You pressed Control+Alt+C in Notepad."
#HotIf WinActive("ahk_class WordPadClass")
^!c::MsgBox "You pressed Control+Alt+C in WordPad."
#HotIf
^!c::MsgBox "You pressed Control+Alt+C in a window other than Notepad/WordPad."

If more than one variant is eligible to fire, only the one closest to the top of the script will fire. The exception to this is the global variant (the one with no #HotIf criteria): It always has the lowest precedence; therefore, it will fire only if no other variant is eligible (this exception does not apply to hotstrings).

When creating duplicate hotkeys, the order of modifier symbols such as ^!+# does not matter. For example, ^!c is the same as !^c. However, keys must be spelled consistently. For example, Esc is not the same as Escape for this purpose (though the case does not matter). Also, any hotkey with a wildcard prefix (*) is entirely separate from a non-wildcard one; for example, *F1 and F1 would each have their own set of variants.

A window group can be used to make a hotkey execute for a group of windows. For example:

GroupAdd "MyGroup", "ahk_class Notepad"
GroupAdd "MyGroup", "ahk_class WordPadClass"

#HotIf WinActive("ahk_group MyGroup")
#z::MsgBox "You pressed Win+Z in either Notepad or WordPad."

To create hotkey variants dynamically (while the script is running), see HotIf.

Expression Evaluation

When the key, mouse or joystick button combination which forms a hotkey is pressed, the #HotIf expression is evaluated to determine if the hotkey should activate.

Note: Scripts should not assume that the expression is only evaluated when the key is pressed (see below).

The expression may also be evaluated whenever the program needs to know whether the hotkey is active. For example, the #HotIf expression for a custom combination like a & b:: might be evaluated when the prefix key (a in this example) is pressed, to determine whether it should act as a custom modifier key.

Note: Use of #HotIf in an unresponsive script may cause input lag or break hotkeys (see below).

There are several more caveats to the #HotIf directive:

ThisHotkey, A_ThisHotkey and A_TimeSinceThisHotkey are set based on the hotkey for which the current #HotIf expression is being evaluated.

A_PriorHotkey and A_TimeSincePriorHotkey temporarily contain the previous values of the corresponding "This" variables.

Optimization

#HotIf is optimized to avoid expression evaluation for simple calls to WinActive or WinExist, thereby reducing the risk of lag or other issues in such cases. Specifically:

If the expression meets these criteria, it is evaluated directly by the program and does not appear in ListLines.

Before the Hotkey function is used to modify an existing hotkey variant, typically the HotIf function must be used with the original expression text. However, the first unique expression with a given combination of criteria can also be referenced by that criteria. For example:

HotIfWinExist "ahk_class Notepad"
Hotkey "#n", "Off"  ; Turn the hotkey off.
HotIf 'WinExist("ahk_class Notepad")'
Hotkey "#n", "On"   ; Turn the same hotkey back on.

#HotIf WinExist("ahk_class Notepad")
#n::WinActivate

Note that any use of variables will disqualify the expression. If the variable's value never changes after the hotkey is created, there are two strategies for minimizing the risk of lag or other issues inherent to #HotIf:

General Remarks

#HotIf also restores prefix keys to their native function when appropriate (a prefix key is the A key in a hotkey such as a & b). This occurs whenever there are no enabled hotkeys for a given prefix.

When a hotkey is currently disabled via #HotIf, its key or mouse button will appear with a "#" character in KeyHistory's "Type" column. This can help debug a script.

Alt-tab hotkeys are not affected by #HotIf: they are in effect for all windows.

The Last Found Window can be set by #HotIf. For example:

#HotIf WinExist("ahk_class Notepad")
#n::WinActivate  ; Activates the window found by WinExist().

Related

#HotIfTimeout may be used to override the default timeout value.

Hotkey function, Hotkeys, Hotstrings, Suspend, WinActive, WinExist, SetTitleMatchMode, DetectHiddenWindows

Examples

#1: Adjust volume by scrolling the mouse wheel over the taskbar:

; Example 0: WinActive.
#HotIf WinActive("ahk_class Notepad")
^!a::MsgBox "You pressed Ctrl-Alt-A while Notepad is active."
#c::MsgBox "You pressed Win-C while Notepad is active."
::btw::This replacement text for "btw" will occur only in Notepad.
#HotIf
#c::MsgBox "You pressed Win-C in a window other than Notepad."

#HotIf MouseIsOver("ahk_class Shell_TrayWnd")
WheelUp::Send "{Volume_Up}"
WheelDown::Send "{Volume_Down}"

MouseIsOver(WinTitle) {
    MouseGetPos ,, Win
    return WinExist(WinTitle " ahk_id " Win)
}

#2: Simple word-delete shortcuts for all Edit controls:

#HotIf ActiveControlIsOfClass("Edit")
^BS::Send "^+{Left}{Del}"
^Del::Send "^+{Right}{Del}"

ActiveControlIsOfClass(Class) {
    FocusedControl := 0
    try FocusedControl := ControlGetFocus("A")
    FocusedControlClass := ""
    try FocusedControlClass := WinGetClass(FocusedControl)
    return (FocusedControlClass=Class)
}

#3: Context-insensitive Hotkey.

#HotIf
Esc::ExitApp

#4: Dynamic Hotkeys. This example requires the MousIsOver function from example #1:

NumpadAdd::
{
    static doubleup := false
    HotIf 'MouseIsOver("ahk_class Shell_TrayWnd")'
    if (doubleup := !doubleup)
        Hotkey "WheelUp", "DoubleUp"
    else
        Hotkey "WheelUp", "WheelUp"
    return
    ; Nested function:	
    DoubleUp(ThisHotkey) => Send("{Volume_Up 2}")
}