Concepts and Conventions

This document covers some general concepts and conventions used by AutoHotkey, with focus on explanation rather than code. The reader is not assumed to have any prior knowledge of scripting or programming, but should be prepared to learn new terminology.

For more specific details about syntax, see Scripting Language.

Table of Contents

Values

A value is simply a piece of information within a program. For example, the name of a key to send or a program to run, the number of times a hotkey has been pressed, the title of a window to activate, or whatever else has some meaning within the program or script.

AutoHotkey supports these types of values:

The Type function can be used to determine the type of a value.

Some other related concepts:

Strings

A string is simply text. Each string is actually a sequence or string of characters, but can be treated as a single entity. The length of a string is the number of characters in the sequence, while the position of a character in the string is merely that character's sequential number. By convention in AutoHotkey, the first character is at position 1.

A string of digits (or any other supported number format) is automatically interpreted as a number when a math operation or comparison requires it.

How literal text should be written within the script depends on the context. For instance, in an expression, strings must be enclosed in quotation marks. In directives (excluding #If) and auto-replace hotstrings, quotation marks are not needed.

For a more detailed explanation of how strings work, see String Encoding.

Numbers

AutoHotkey supports these number formats:

Hexadecimal numbers must use the 0x or 0X prefix, except where noted in the documentation. This prefix must be written after the + or - sign, if present, and before any leading zeroes. For example, 0x001 is valid, but 000x1 is not.

Numbers written with a decimal point are always considered to be floating-point, even if the fractional part is zero. For example, 42 and 42.0 are usually interchangeable, but not always. Scientific notation is also recognized (e.g. 1.0e4 and -2.1E-4), but always produces a floating-point number even if no decimal point is present.

The decimal separator is always a dot, even if the user's regional settings specify a comma.

When a number is converted to a string, it is formatted as decimal. Floating-point numbers are formatted with full precision (but discarding redundant trailing zeroes), which may in some cases reveal their inaccuracy. Use the Format function to produce a numeric string in a different format. Floating-point numbers can also be formatted by using the Round function.

For details about the range and accuracy of numeric values, see Pure Numbers.

Boolean

A boolean value can be either true or false. Boolean values are used to represent anything that has exactly two possible states, such as the truth of an expression. For example, the expression (x <= y) is true when x has lesser or equal value to y. A boolean value could also represent yes or no, on or off, down or up (such as for GetKeyState) and so on.

AutoHotkey does not have a specific boolean type, so it uses the integer value 0 to represent false and 1 to represent true. When a value is required to be either true or false, a blank or zero value is considered false and all other values are considered true. (Objects are always considered true.)

The words true and false are built-in variables containing 1 and 0. They can be used to make a script more readable.

Nothing

AutoHotkey does not have a value which uniquely represents nothing, null, nil or undefined, as seen in other languages. Instead, an empty string (a string of zero length) often has this meaning.

If a variable or parameter is said to be "empty" or "blank", that usually means an empty string (a string of zero length).

Objects

There are generally two ways of viewing objects:

The proper use of objects (and in particular, classes) can result in code which is modular and reusable. Modular code is usually easier to test, understand and maintain. For instance, one can improve or modify one section of code without having to know the details of other sections, and without having to make corresponding changes to those sections. Reusable code saves time, by avoiding the need to write and test code for the same or similar tasks over and over.

When you assign an object to a variable, as in myObj := {}, what you store is not the object itself, but a reference to the object. Copying that variable, as in yourObj := myObj, creates a new reference to the same object. A change such as myObj.ans := 42 would be reflected by both myObj.ans and yourObj.ans, since they both refer to the same object. However, myObj := Object() only affects the variable myObj, not the variable yourObj, which still refers to the original object.

Object Protocol

This section builds on these concepts which are covered in later sections: variables, functions

Objects work through the principle of message passing. You don't know where an object's code or variables actually reside, so you must pass a message to the object, like "give me foo" or "go do bar", and rely on the object to respond to the message. Objects in AutoHotkey support the following basic messages:

Each message can optionally have one or more parameters (and, for Set, the value). Usually there is at least one parameter, and it is interpreted as the name of a property or method, a key or an array index, depending on the object and how you're using it. The parameters of a message are specified using three different patterns: .Name, [Parameters] and (Parameters), where Name is a literal name or identifier, and Parameters is a list of parameters (as sub-expressions), which can be empty/blank ([] or ()).

For Get and Set, .Name and [Parameters] can be used interchangeably, or in combination:

myObj[arg1, arg2, ..., argN]
myObj.name
myObj.name[arg2, ..., argN]

For Call, .Name and [Parameter] can be used interchangeably, and must always be followed by (Parameters):

myObj.name(arg2, ..., argN)
myObj[arg1](arg2, ..., argN)

Notice that if name is present, it becomes the first parameter. myObj.name is equivalent to myObj["name"], while myObj.123 is equivalent to myObj[123]. This is true for every type of object, so it is always possible to compute the name of a property or method at runtime, rather than hard-coding it into the script.

Although name or arg1 is considered to be the first parameter, remember that these are just messages, and the object is free to handle them in any way. In a method call such as those shown above, usually the object uses name or arg1 to identify which method should be called, and then only arg2 and beyond are passed to the method. In effect, arg2 becomes the method's first apparent parameter.

Generally, Set has the same meaning as an assignment, so it uses the same operator:

myObj[arg1, arg2, ..., argN] := value
myObj.name := value
myObj.name[arg2, ..., argN] := value

Technically, value is passed as the last the parameter of the Set message; however, this detail is almost never relevant to script authors. Generally one can simply think of it as "the value being assigned".

Variables

A variable allows you to use a name as a placeholder for a value. Which value that is could change repeatedly during the time your script is running. For example, a hotkey could use a variable press_count to count the number of times it is pressed, and send a different key whenever press_count is a multiple of 3 (every third press). Even a variable which is only assigned a value once can be useful. For example, a WebBrowserTitle variable could be used to make your code easier to update when and if you were to change your preferred web browser, or if the title or window class changes due to a software update.

In AutoHotkey, variables are created simply by using them. Each variable is not permanently restricted to a single data type, but can instead hold a value of any type: string, number or object. Each variable starts off empty/blank; in other words, each newly created variable contains an empty string until it is assigned some other value.

A variable has three main aspects:

Certain restrictions apply to variable names - see Names for details. In short, it is safest to stick to names consisting of ASCII letters (which are case insensitive), digits and underscore, and to avoid using names that start with a digit.

A variable name has scope, which defines where in the code that name can be used to refer to that particular variable; in other words, where the variable is visible. If a variable is not visible within a given scope, the same name can refer to a different variable. Both variables might exist at the same time, but only one is visible to each part of the script. Global variables are visible in the "global scope" (that is, outside of functions), but must usually be declared to make them visible inside a function. Local variables are visible only inside the function which created them.

A variable can be thought of as a container or storage location for a value, so you'll often find the documentation refers to a variable's value as the contents of the variable. For a variable x := 42, we can also say that the variable x has the number 42 as its value, or that the value of x is 42.

It is important to note that a variable and its value are not the same thing. For instance, we might say "myArray is an array", but what we really mean is that myArray is a variable containing a reference to an array. We're taking a shortcut by using the name of the variable to refer to its value, but "myArray" is really just the name of the variable; the array object doesn't know that it has a name, and could be referred to by many different variables (and therefore many names).

Uninitialised Variables

To initialise a variable is to assign it a starting value. Although the program automatically initialises all variables (an empty string being the default value), it is good practice for a script to always initialise its variables before use. That way, anyone reading the script can see what variables the script will be using and what starting values they are expected to have.

It is usually necessary for the script to initialise any variable which is expected to hold a number. For example, x := x + 1 will not work if x has never been assigned a value, since the empty string is considered to be non-numeric. The script should have assigned a starting value, such as x := 0. There are some cases where empty values are assumed to be 0, but it is best not to rely on this.

Script authors can use the #Warn directive to help find instances where a variable is used without having been initialised by the script.

Built-in Variables

A number of useful variables are built into the program and can be referenced by any script. Except where noted, these variables are read-only; that is, their contents cannot be directly altered by the script. By convention, most of these variables start with the prefix A_, so it is best to avoid using this prefix for your own variables.

Some variables such as A_KeyDelay and A_TitleMatchMode represent settings that control the script's behavior, and retain separate values for each thread. This allows subroutines launched by new threads (such as for hotkeys, menus, timers and such) to change settings without affecting other threads.

Some special variables are not updated periodically, but rather their value is retrieved or calculated whenever the script references the variable. For example, Clipboard retrieves the current contents of the clipboard as text, and A_TimeSinceThisHotkey calculates the number of milliseconds that have elapsed since the hotkey was pressed.

Related: list of built-in variables.

Environment Variables

Environment variables are maintained by the operating system. You can see a list of them at the command prompt by typing SET then pressing Enter.

A script may create a new environment variable or change the contents of an existing one with EnvSet. Such additions and changes are not seen by the rest of the system. However, any programs or scripts which the script launches by calling Run or RunWait usually inherit a copy of the parent script's environment variables.

To retrieve an environment variable, use EnvGet. For example:

Path := EnvGet("PATH")

Caching

Although a variable is typically thought of as holding a single value, and that value having a distinct type (string, number or object), AutoHotkey automatically converts between numbers and strings in cases like "Value is " myNumber and MsgBox myNumber. As these conversions can happen very frequently, whenever a variable containing a number is converted to a string, the result is cached in the variable.

Currently, AutoHotkey v2 caches a pure number only when assigning a pure number to a variable, not when reading it. This preserves the ability to differentiate between strings and pure numbers (such as with the Type function, or when passing values to COM objects).

Related

Functions

A function is the basic means by which a script does something.

Functions can have many different purposes. Some functions might do no more than perform a simple calculation, while others have immediately visible effects, such as moving a window. One of AutoHotkey's strengths is the ease with which scripts can automate other programs and perform many other common tasks by simply calling a few functions. See the function list for examples.

Throughout this documentation, some common words are used in ways that might not be obvious to someone without prior experience. Below are several such words/phrases which are used frequently in relation to functions:

Call a function

Calling a function causes the program to invoke, execute or evaluate it. In other words, a function call temporarily transfers control from the script to the function. When the function has completed its purpose, it returns control to the script. In other words, any code following the function call does not execute until after the function completes.

However, sometimes a function completes before its effects can be seen by the user. For example, the Send function sends keystrokes, but may return before the keystrokes reach their destination and cause their intended effect.

Parameters

Usually a function accepts parameters which tell it how to operate or what to operate on. Each parameter is a value, such as a string or number. For example, WinMove moves a window, so its parameters tell it which window to move and where to move it to. Parameters can also be called arguments. Common abbreviations include param and arg.

Pass parameters

Parameters are passed to a function, meaning that a value is specified for each parameter of the function when it is called. For example, one can pass the name of a key to GetKeyState to determine whether that key is being held down.

Return a value

Functions return a value, so the result of the function is often called a return value. For example, StrLen returns the number of characters in a string. Commands do not return a result directly; instead, they store the result in a variable. Functions may also do this, such as when there is more than one result.

Command

A function call is sometimes called a command, such as if it commands the program to take a specific action. For historical reasons, command may refer to a particular style of calling a function, where the parentheses are omitted and the return value is discarded.

Functions usually expect parameters to be written in a specific order, so the meaning of each parameter value depends on its position in the comma-delimited list of parameters. Some parameters can be omitted, in which case the parameter can be left blank, but the comma following it can only be omitted if all remaining parameters are also omitted. For example, the syntax for ControlSend is:

ControlSend Keys , Control, WinTitle, WinText, ExcludeTitle, ExcludeText

Square brackets signify that the enclosed parameters are optional (the brackets themselves should not appear in the actual code). However, usually one must also specify the target window. For example:

ControlSend "^{Home}", "Edit1", "A"  ; Correct. Control is specified.
ControlSend "^{Home}", "A"           ; Incorrect: Parameters are mismatched.
ControlSend "^{Home}",, "A"          ; Correct. Control is omitted.

Methods

Methods are functions which operate on a particular object. While there can only be one function named Send (for example), there can be as many methods named Send as there are objects, as each object (or class of objects) can respond in a different way. For this reason, the target object (which may be a variable or sub-expression) is specified to left of the method name instead of inside the parameter list. For details, see Object Protocol.

Control Flow

Control flow is the order in which individual statements are executed. Normally statements are executed sequentially from top to bottom, but a control flow statement can override this, such as by specifying that statements should be executed repeatedly, or only if a certain condition is met.

Statement

A statement is simply the smallest standalone element of the language that expresses some action to be carried out. In AutoHotkey, statements include assignments, function calls and other expressions. However, directives, labels (including hotkeys and hotstrings), and declarations without assignments are not statements; they are processed when the program first starts up, before the script executes.

Execute

Carry out, perform, evaluate, put into effect, etc. Execute basically has the same meaning as in non-programming speak.

Body

The body of a control flow statement is the statement or group of statements to which it applies. For example, the body of an if statement is executed only if a specific condition is met.

For example, consider this simple set of instructions:

  1. Open Notepad
  2. Wait for Notepad to appear on the screen
  3. Type "Hello, world!"

We take one step at a time, and when that step is finished, we move on to the next step. In the same way, control in a program or script usually flows from one statement to the next statement. But what if we want to type into an existing Notepad window? Consider this revised set of instructions:

  1. If Notepad is not running:
    1. Open Notepad
    2. Wait for Notepad to appear on the screen
  2. Otherwise:
    1. Activate Notepad
  3. Type "Hello, world!"

So we either open Notepad or activate Notepad depending on whether it is already running. #1 is a conditional statement, also known as an if statement; that is, we execute its body (#1.1 - #1.2) only if a condition is met. #2 is an else statement; we execute its body (#2.1) only if the condition of a previous if statement (#1) is not met. Depending on the condition, control flows one of two ways: #1 (if true) → #1.1 → #1.2 → #3; or #1 (if false) → #2 (else) → #2.1 → #3.

The instructions above can be translated into the code below:

if (not WinExist("ahk_class Notepad"))
{
    Run "Notepad"
    WinWait "ahk_class Notepad"
}
else
    WinActivate "ahk_class Notepad"
Send "Hello, world!"

In our written instructions, we used indentation and numbering to group the statements. Scripts work a little differently. Although indentation makes code easier to read, in AutoHotkey it does not affect the grouping of statements. Instead, statements are grouped by enclosing them in braces, as shown above. This is called a block.

For details about syntax - that is, how to write or recognise control flow statements in AutoHotkey - see Control Flow.

Details

String Encoding

Each character in the string is represented by a number, called its ordinal number, or character code. For example, the value "Abc" would be represented as follows:

Abc
659899

The encoding of a string is the way in which numbers are mapped to symbols. There are many different encodings, but as all of those supported by AutoHotkey include ASCII as a subset, character codes 0 to 127 always have the same meaning. For example, 'A' always has the character code 65.

Although AutoHotkey provides ways to work with text in various encodings, the built-in functions--and to some degree the language itself--all assume string values to be in one particular encoding. This is referred to as the native encoding. The native encoding depends on the version of AutoHotkey:

Note: There is currently no ANSI version of AutoHotkey v2.

Generally, other parts of this documentation use the term "character" to mean a string's smallest unit; bytes for ANSI strings and 16-bit code units for Unicode strings. For practical reasons, the length of a string and positions within a string are measured by counting these fixed-size units, even though they may not be complete Unicode characters.

FileRead, FileAppend, FileOpen and the File object provide ways of reading and writing text in files with a specific encoding.

The functions StrGet and StrPut can be used to convert strings between the native encoding and some other specified encoding. However, these are usually only useful in combination with data structures and the DllCall function. Strings which are passed directly to or from DllCall can be converted to ANSI or UTF-16 by using the AStr or WStr parameter types.

Techniques for dealing with the differences between ANSI and Unicode versions of AutoHotkey can be found under Unicode vs ANSI.

Pure Numbers

A pure or binary number is one which is stored in memory in a format that the computer's CPU can directly work with, such as to perform math. In most cases, AutoHotkey automatically converts between numeric strings and pure numbers as needed, and rarely differentiates between the two types. AutoHotkey primarily uses two data types for pure numbers:

In other words, scripts are affected by the following limitations:

Note: There are some decimal fractions which the binary floating-point format cannot precisely represent, so a number is rounded to the closest representable number. This may lead to unexpected results. For example:

MsgBox 0.1 + 0           ; 0.10000000000000001
MsgBox 0.1 + 0.2         ; 0.30000000000000004
MsgBox 0.3 + 0           ; 0.29999999999999999
MsgBox 0.1 + 0.2 = 0.3   ; 0 (not equal)

One strategy for dealing with this is to avoid direct comparison, instead comparing the difference. For example:

MsgBox Abs((0.1 + 0.2) - (0.3)) < 0.0000000000000001

Another strategy is to explicitly apply rounding before comparison, such as by converting to a string. There are generally two ways to do this while specifying the precision, and both are shown below:

MsgBox Round(0.1 + 0.2, 15) = Format("{:.15f}", 0.3)

Names

AutoHotkey uses the same set of rules for naming various things, including variables, functions, window groups, classes, properties and methods. The rules are as follows.

Case sensitivity: None for ASCII characters. For example, CurrentDate is the same as currentdate. However, uppercase non-ASCII characters such as 'Ä' are not considered equal to their lowercase counterparts, regardless of the current user's locale. This helps the script to behave consistently across multiple locales.

Maximum length: 253 characters.

Allowed characters: Letters, digits, underscore and non-ASCII characters; however, the first character cannot be a digit.

Reserved words: and, contains, in, is, new, not and or. These words are reserved for use as operators and therefore cannot be used as variable names when written literally in an expression.

Names of control flow statements are also reserved, primarily to detect mistakes. This includes: Break, Catch, Continue, Else, Finally, For, Gosub, Goto, If, Loop, Return, Throw, Try, Until, While

Variable References vs Values

Variables have certain attributes that blur the line between a variable and its value, but it is important to make the distinction. In particular, consider objects and ByRef parameters.

Although we may say the variable myArray contains an array (which is a type of object), what the variable contains isn't the array itself but rather a reference or pointer to the array. Any number of variables can contain a reference to the same object. It may be helpful to think of a variable as just a name in that case. For instance, giving a person a nickname doesn't cause a clone of that person to come into existence.

By default, variables are passed to user-defined functions by value. In other words, the value contained by the variable is copied into the variable which corresponds to the function's parameter. ByRef parameters allow you to pass a variable by reference, or in other words, to make one parameter of the function an alias for your variable, allowing the function to assign a new value to your variable.

Because a variable only ever contains a reference to an object and not the object itself, when you pass such a variable to a non-ByRef parameter, what the function receives is a reference to the same object. This allows the function to modify the object, but it does not allow the function to modify the variable which the function's caller used, because the function only has a reference to the object, not the variable.

References to Objects

Scripts interact with an object only indirectly, through a reference to the object. When you create an object, the object is created at some location you don't control, and you're given a reference. Passing this reference to a function or storing it in a variable or another object creates a new reference to the same object. You release a reference by simply using an assignment to replace it with any other value. An object is deleted only after all references have been released; you cannot delete an object explicitly, and should not try.

ref1 := Object()  ; Create an object and store first reference
ref2 := ref1      ; Create a new reference to the same object
ref1 := ""        ; Release the first reference
ref2 := ""        ; Release the second reference; object is deleted

If that's difficult to understand, try thinking of an object as a rental unit. When you rent a unit, you're given a key which you can use to access the unit. You can get more keys and use them to access the same unit, but when you're finished with the unit, you must hand all keys back to the rental agent. Usually a unit wouldn't be deleted, but maybe the agent will have any junk you left behind removed; just as any values you stored in an object are freed when the object is deleted.