Autohotkey Tutorial - hotkeys

Autohotkey Tutorial - hotkeys

posted in productivity on • last updated on

First we’ll cover the basic Autohotkey hotkey syntax. Which is arguably already pretty confusing for newcomers in and by itself.

But we don’t stop there as after adding more and more hotkeys, it will also become harder and harder to think of new key combinations that are somehow still memorable. There is only so much you can do with the # (Windows) key etc.

Time for some creative hotkey combinations! ‘Advanced Hotkeys’ covers code snippets on how to run different scripts on single, double or triple key presses as well as how to differentiate between long(ish) key presses or mouse clicks. And more…


; Single line hotkey
^#D::MsgBox Pressed Control + Win + D (%A_ThisHotKey%)

; Control + Win + C: Multi line script
Run, notepad.exe
WinWait, Untitled - Notepad, , 3
Send, Dear sir,{enter}{enter}

Basic Syntax


Shorthand Full Desc
+ Shift  
^ Control or Ctrl  
# Win Windows
! Alt  
<# LWin Left Windows
+> RShift Right Shift
<^>! AltGr  
  AppsKey Menu key


  • F[1-24], Tab, Space, Enter/Return, Backspace/BS
  • Left, Up, Down, Right
  • Esc, Ins, Delete/Del, Home, End, PgUp, PgDn
  • PrintScreen, ScrollLock, CtrlBreak
  • Sleep, Pause


  • Numlock ON: Numpad[0-9],
  • Numlock OFF: NumpadIns, NumpadEnd, NumpadMult, NumpadEnter, …


  • Browser_Stop, Media_Next, Volume_Up, Launch_App2, …


  • LButton, RButton, MButton
  • XButton1 (Browser_Back), XButton2 (Browser_Forward)
  • WheelUp, WheelDown, WheelLeft, WheelRight


  • JoyX, JoyPOV, JoyInfo, …

JoystickTest: A simple script for determining the exact mapping of your joystick.

Find the full KeyList here. If your keyboard has keys that are not in the full keylist, it might still be possible to map them to a script.

You can also let Autohotkey itself do the figuring out for you. Its builtin command KeyHistory opens a window where you can figure out which is which.

Native function

Prefix a hotkey with ~ to not block the native function.

#IfWinActive, ahk_class CabinetWClass
; Control + Shift + 6: Details View in Windows Explorer
; Resize columns so that filenames are completely visible
~^+6::Send, {Control Down}{NumpadAdd}{Control Up}

Custom combinations

To combine keys that do not have a shorthand use &. Keys on the left side of such custom combinations lose their native function. They are called prefix keys.

Example: Search google for text on the clipboard by pressing Capslock and X.

Capslock & X::Run,


Key Down and Up
Add UP to a hotkey combination to run the script on key release rather than on keypress.

AppsKey::ToolTip Press < or > to cycle through tabs.
AppsKey Up::ToolTip
~AppsKey & <::Send ^+{tab}
~AppsKey & >::Send ^{tab}

* acts as a key modifier wildcard.

*#c::Msgbox Triggered by Win+C, Shift+Win+C, Ctrl+Win+C, etc

$ is necessary when you need to send the same hotkey and not execute your script again.

; Send Control + C => Copy text
Send, ^c
ClipWait, 1
fileExists := FileExist(clipboard)
if (fileExists = "D") {
    ; Open explorer in path on clipboard
    Run % "explorer.exe /root," clipboard

} else if (fileExists) {
    ; Open explorer with file selected
    Run % "explorer.exe /select," clipboard

} else {
    ; No path on clipboard, just open explorer
    Send #e

Advanced Hotkeys

Creating more advanced hotkey combinations.

Context sensitive hotkeys

Control in which applications a hotkey is (not) active with the keywords IfWinActive, IfWinExist, IfWinNotActive and IfWinNotExist.

#IfWinActive, ahk_class Notepad
^a::MsgBox You pressed Ctrl-A while Notepad is active. Pressing Ctrl-A in any other window will pass the Ctrl-A keystroke to that window.
#c::MsgBox You pressed Win-C while Notepad is active.

#c::MsgBox You pressed Win-C while any window except Notepad is active.

#If MouseIsOver("ahk_class Shell_TrayWnd") and true
WheelUp::Send {Volume_Up}     ; Wheel over taskbar: increase/decrease volume.
WheelDown::Send {Volume_Down} ;

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

IfWinActive ahk_class Notepad
    return  ; i.e. do nothing, which causes Control-P to do nothing in Notepad.

Send ^p

Find out the ahk_class of a program with Window Spy (AU3_Spy.exe) which comes bundled with Autohotkey itself.

Combining 2 hotkeys

Check if a hotkey combination is pressed twice

; Esc twice to close an application
If (A_PriorHotKey = A_ThisHotKey and A_TimeSincePriorHotkey < 500)

Gotcha: the A_PriorHotkey will only hold values of combinations that are also defined as a hotkey. The value of A_PriorHotkey will be exactly as the hotkey is defined.

Follow a hotkey up with an additional keypress

; AltGr + C: Change the case of the selected text
; Follow up with (U)PPER, l(ower) or T(itle)
clipboard =
Send, ^c
ClipWait, 1
Input keyPressed, I L1
if (keyPressed = "u") {
    StringUpper toUpperCase, clipboard
    Send %toUpperCase%
} else if (keyPressed = "l") {
    StringLower toLowerCase, clipboard
    Send %toLowerCase%
} else if (keyPressed = "p" or keyPressed = "t") {
    StringUpper toTitleCase, clipboard, T
    Send %toTitleCase%

Input option L1 is the maximum allowed length. (L1 -> L5)

Double, triple and long key presses

Simple double keypress

Map a double µ keypress to a smiley.

; File needs to be encoded in UTF8 BOM
; for a binding of "µ" to work.
    KeyWait, µ
    KeyWait, µ, D T0.2
    if ErrorLevel
        ; No second µ keypress
        SendInput µ
        ; Replace double keypress
        ; with something else
        SendInput 😀

The whole shebang

DoubleClickTime := DllCall("GetDoubleClickTime") ; in milliseconds

; Wait for 'c' to be released
KeyWait, c
if (A_TimeSinceThisHotkey > DoubleClickTime) {
    Msgbox Longpress

; Wait for 'c' to be pressed down again (option "d")
; But timeout after T0.5 seconds (If DoubleClickTime is 500)
KeyWait, c, % "d T"DoubleClickTime/1000
If ! Errorlevel
    Msgbox Doublepress
    Msgbox Singlepress

KeyWait docs or more info on the forum.

Long middle mouse click with GetKeyState

HowLong = 0
    Sleep, 10
    GetKeyState, MButton, MButton, P
    IfEqual, MButton, U, Break
IfLess, HowLong, 20, Return

; Do stuff when middle mouse button was pressed longer than 20ms

Triple, quadruple etc keypresses

; Example #3: Detection of single, double, and triple-presses of a hotkey. This
; allows a hotkey to perform a different operation depending on how many times
; you press it:
if winc_presses > 0 ; SetTimer already started, so we log the keypress instead.
    winc_presses += 1
; Otherwise, this is the first press of a new series. Set count to 1 and start
; the timer:
winc_presses = 1
SetTimer, KeyWinC, -400 ; Wait for more presses within a 400 millisecond window.

if winc_presses = 1 ; The key was pressed once.
    Run, c:\  ; Open a folder.
else if winc_presses = 2 ; The key was pressed twice.
    Run, c:\windows  ; Open a different folder.
else if winc_presses > 2
    MsgBox, Three or more clicks detected.
; Regardless of which action above was triggered, reset the count to
; prepare for the next series of presses:
winc_presses = 0

Morse hotkeys

The forum thread on hold patterns.

Morse(timeout = 400) {
   tout := timeout/1000
   key := RegExReplace(A_ThisHotKey,"[\*\~\$\#\+\!\^]")
   Loop {
      t := A_TickCount
      KeyWait %key%
      Pattern .= A_TickCount-t > timeout
      KeyWait %key%,DT%tout%
      If (ErrorLevel)
         Return Pattern

; Use Backspace
BS::MsgBox % "Morse press pattern " Morse()

; Alt + Z
p := Morse()
If (p = "0")
  MsgBox Short press
Else If (p = "00")
  MsgBox Two short presses
Else If (p = "01")
  MsgBox Short+Long press
  MsgBox Press pattern %p%


Waiting for something

Wait for something to happen with SetTimer

; Example #2: Wait for a certain window to appear and then alert the user:
SetTimer, Alert1, 500

IfWinNotExist, Video Conversion, Process Complete

; Otherwise:
SetTimer, Alert1, Off  ; i.e. the timer turns itself off here.
SplashTextOn, , , The video conversion is finished.
Sleep, 3000


; Toggle script suspension
^#s:: ; Control + Win + S
Msgbox % "Script is now " (A_IsSuspended ? "suspended" : "running")

The Pause keyword would halt the current thread while Suspend stops all hotkeys from triggering.

Start a script with Suspend, Permit to have that hotkey still trigger even while the script is suspended.

Stuff that came into being during the making of this post
Other interesting reads
  • 28 March 2023 : Added double keypress hotkey example
  • 25 August 2018
Tags: autohotkey