#If
From Auto Hotkey
#If
Creates context-sensitive hotkeys and hotstrings. Such hotkeys perform a different action (or none at all) depending on the result of an expression.
#If Expression
Parameters
- Expression
Any valid expression.
Basic Operation
The #If 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 #If directive. For example:
#If WinActive("ahk_class Notepad") or WinActive(MyWindowTitle)
#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle
The #If directive is positional: it affects all hotkeys and hotstrings physically beneath it in the script, until the next #If directive.
Note: Unlike if statements, braces have no effect with the #If directive.
To turn off context sensitivity, specify #If without any expression. For example:
#If
When a mouse or keyboard hotkey is disabled via #If, 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 #If works, it never prevents other programs from seeing the press of a button.
#If 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:
#If 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.
#If
Variant (Duplicate) Hotkeys
A particular hotkey or hotstring can be defined more than once in the script if each definition has different #If criteria. These are known as hotkey variants. For example:
#If WinActive("ahk_class Notepad") ^!c::MsgBox "You pressed Control+Alt+C in Notepad." #If WinActive("ahk_class WordPadClass") ^!c::MsgBox "You pressed Control+Alt+C in WordPad." #If ^!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 #If 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.
To have the same hotkey subroutine executed by more than one variant, the easiest way is to create a stack of identical hotkeys, each with a different #If directive above it. For example:
#If WinActive("ahk_class Notepad")
#z::
#If WinActive("ahk_class WordPadClass")
#z::
MsgBox "You pressed Win+Z in either Notepad or WordPad."
return
Alternatively, a window group can be used via #If WinActive("ahk_group MyGroup").
To create hotkey variants dynamically (while the script is running), see Hotkey "If".
Expression Evaluation
When the key, mouse or joystick button combination which forms a hotkey is pressed, the #If 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 #If 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 #If in an unresponsive script may cause input lag or break hotkeys (see below).
There are several more caveats to the #If directive:
- Keyboard or mouse input is typically buffered (delayed) until expression evaluation completes or times out.
- Expression evaluation can only be performed by the script's main thread (at the OS level, not a quasi-thread), not directly by the keyboard/mouse hook. If the script is busy or unresponsive, such as if a FileCopy is in progress, expression evaluation is delayed and may time out.
- If the system-defined timeout is reached, the system may stop notifying the script of keyboard or mouse input (see #IfTimeout for details).
- Sending keystrokes or mouse clicks while the expression is being evaluated (such as from a function which it calls) may cause complications and should be avoided.
A_ThisHotkey and A_TimeSinceThisHotkey are set based on the hotkey for which the current #If expression is being evaluated.
A_PriorHotkey and A_TimeSincePriorHotkey temporarily contain the previous values of the corresponding "This" variables.
Optimization
#If 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:
- The expression must contain exactly one call to WinExist or WinActive.
- Each parameter must be a single quoted string, and no more than two parameters may be used.
- The result may be inverted with
notor!, but no other operators may be used. - Whitespace and parentheses are fully handled when the expression is pre-compiled and therefore do not affect this optimization.
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 Hotkey "If" 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:
Hotkey "IfWinExist", "ahk_class Notepad"
Hotkey "#n", "Off" ; Turn the hotkey off.
Hotkey 'If', 'WinExist("ahk_class Notepad")'
Hotkey "#n", "On" ; Turn the same hotkey back on.
#if 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 #If:
- Use
Hotkey "IfWin...", MyTitleVarto set the criteria andHotkey KeyName, Labelto create the hotkey variant. - Use a constant expression such as
#if WinActive("ahk_group MyGroup")and define the window group withGroupAdd "MyGroup", MyTitleVarelsewhere in the script.
General Remarks
#If 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 Gosub or Goto is used to jump to a hotkey or hotstring label, it jumps to the variant closest to the top of the script.
When a hotkey is currently disabled via #If, 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 #If: they are in effect for all windows.
The Last Found Window can be set by #If. For example:
#If WinExist("ahk_class Notepad") #n::WinActivate ; Activates the window found by WinExist().
Related
#IfTimeout may be used to override the default timeout value.
Hotkey function, Hotkeys, Hotstrings, Suspend, WinActive, WinExist, SetTitleMatchMode, DetectHiddenWindows
Examples
; Example 0: WinActive.
#If 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.
#If
#c::MsgBox "You pressed Win-C in a window other than Notepad."
; Example 1: Adjust volume by scrolling the mouse wheel over the taskbar.
#If MouseIsOver("ahk_class Shell_TrayWnd")
WheelUp::Send "{Volume_Up}"
WheelDown::Send "{Volume_Down}"
MouseIsOver(WinTitle) {
MouseGetPos ,, Win
return WinExist(WinTitle " ahk_id " Win)
}
; Example 2: Simple word-delete shortcuts for all Edit controls.
#If ActiveControlIsOfClass("Edit")
^BS::Send "^+{Left}{Del}"
^Del::Send "^+{Right}{Del}"
ActiveControlIsOfClass(Class) {
FocusedControl := ControlGetFocus("A")
FocusedControlHwnd := ControlGetHwnd(FocusedControl, "A")
FocusedControlClass := WinGetClass("ahk_id " FocusedControlHwnd)
return (FocusedControlClass=Class)
}
; Example 3: Context-insensitive hotkey.
#If
Esc::ExitApp
; Example 4: Dynamic hotkeys. Requires Example 1.
NumpadAdd::
Hotkey "If", 'MouseIsOver("ahk_class Shell_TrayWnd")'
if (doubleup := !doubleup)
Hotkey "WheelUp", "DoubleUp"
else
Hotkey "WheelUp", "WheelUp"
return
DoubleUp:
Send "{Volume_Up 2}"
return