Scripting Language

Um script do AutoHotkey é basicamente um grupo de instruções para o programa seguir escrito em uma linguagem personalizada exclusiva para o AutoHotkey. Essa linguagem tem semelhanças com várias outras linguagens de script, mas também possui seus pontos fortes e armadilhas. Este documento descreve a linguagem e também tenta apontar armadilhas comuns .

Veja a página Conceitos e Convenções para mais explicações gerais de vários conceitos usados pelo AutoHotkey.

Há dois estilos distintos de sintaxe usados no AutoHotkey: sintaxe legado e expressões.

Tabela de Conteúdos

Convenções gerais

Nomes: Nomes de variáveis e funções não são case sensitive (por exemplo, CurrentDate é o mesmo que currentdate). Para detalhes como o comprimento máximo e caracteres utilizáveis, veja Nomes.

Variáveis não tipadas: Variáveis não possuem um tipo definido explicitamente; por causa disso, um valor de qualquer tipo pode ser armazenado em qualquer variável (exceto as variáveis embutidas). Números podem ser convertidos automaticamnete em strings (texto) ou vice-versa, dependendo da situação.

Declarações são opcionais: Com exceção de onde está anotado na página da função, variáveis não precisam ser declaradas; elas passam a existir pelo simples fato de serem usadas (e cada variável começa vazia/em branco).

Espaços são majoritariamente ignorados: A indentação é importante para tornar o código legível, mas não é necessário para o programa e normalmente é ignorado. Espaços e tabs geralmente são ignorados no final de uma linha, dentro de uma expressão (exceto quando cercado por aspas) e antes e depois de parâmetros de comandos. No entanto, espaços são significantes em alguns casos, inlcuindo:

Quebras de linhas são relevantes: Quebras de linha normalmente agem como um separador de declaração, terminando o comando ou expressão anterior. (Uma declaração nada mais é que o menor elemento independente da linguagem que expressa alguma ação a ser realizada). A exceção para isso é a continuação de linha (veja abaixo).

Continuação de linha: Linhas longas podem ser divididas em uma coleção de outras menores para melhorar a legibilidade e manutenção. Isso é realizado pelo pré-processamento, então não é parte da linguagem como tal. Há dois métodos:

Comentários

Comentários são porções de texto dentro do script que são ignorados pelo programa. Eles são tipicamente usados para adicionar explicação ou desativar partes do código.

Scripts podem ser comentados através do uso de um ponto-e-vírgula no começ ode uma linha. Por exemplo:

; Esta linha inteira é um comentário.

Comentários também podem ser adicionados no final de uma linha, mas nesse caso o ponto-e-vírgula precisa ter pelo menos um espaço ou tab antes dele. Por exemplo:

Run Notepad  ; Isto é um comentário na mesma linha que um comando.

Além disso, os símbolos /* e */ podem ser usados para comentar uma seção inteira, mas apenas se os símbolos aparecerem no começo de uma linha (excluindo espaços em branco), como nesse exemplo:

/*
MsgBox, Essa linha está comentada (desativada).
MsgBox, Common mistake: */ isto não encerra o comentário.
MsgBox, Esta linha está comentada 
*/

Visto que os comentários são ignorados quando um script é iniciado, eles não impactam a performance ou o uso de memória.

O caractere de comentário padrão (ponto-e-vírgula) pode ser alterado para algum outro caractere ou string através da diretiva #CommentFlag.

Expressões

Expressões são combinações de um ou mais valores, variáveis, operadores e chamadas de funções. Por exemplo, 10, 1+1 e MinhaVar são expressões válidas. Normalmente, uma expressão toma um ou mais valores como entrada, realiza uma ou mais operações e produz um valor como resultado. O processo de descobrir o valor de uma expressão é chamado de avaliação. Por exemplo, a expressão 1+1 resulta no número 2.

Comandos são projetados para pegar uma lista de parâmetros e realizar uma única ação por linha, enquanto que expressões simples podem ser postas juntas para formar expressões cada vez mais complexas. Por exemplo, se Discount/100 converte uma porcentagem de desconto em uma fração, 1 - Discount/100 calcula uma fração que representa a quantidade restante e Price * (1 - Discount/100)aplica isso para produzir o próximo preço.

Valores são números, objetos ou strings. Um valor literal é um valor que é escrito fisicamente no script; um que você pode ver quando você olha para o código.

Texto / Strings

Para uma explicação mais ampla sobre strings, veja Strings.

Uma string ou string de caracteres é apenas um valor de texto. Em uma expressão, textos literais precisam ser cercados em aspas para diferenciá-los de um nome de variável ou alguma outra expressão. Isso é frequentemente chamado de quoted literal string, ou simplesmente quoted string. Por exemplo, "Isto é uma quoted string"..

Para incluir o caractere atual de aspas dentro de uma string cercada por aspas, especifique duas aspas consecutivas duas vezes, como mostrado neste exemplo: "Ela disse ""Uma maçã por dia."".

Strings cercadas por aspas podem conter sequências de escape como 't (tab), 'n (linefeed) e 'r (carriage return). Ao contrário de textos não cercados, não é necessário escapar vírgulas ou sinais de porcentagem, visto que strings cercadas não podem conter variáveis. O uso da sequência de escape '" para produzir um caractere de aspas literal não é suportado atualmente; em vez disso, use duas aspas consecutivas como mostrado acima.

Variáveis

Para uma explicação e detalhes gerais sobre variáveis, veja Variáveis.

Variáveis podem ser usadas em uma expressão através da simples ação de escrever o nome da variável. Por exemplo. AScreenWidth/2. No entanto, variáveis não podem ser usadas dentro de uma string cercada. Em vez disso, variáveis e outros valores podem ser combinados com o texto através de um processo chamado de concatenação. Existem duas manerias de concatenar valores em uma expressão:

A concatenação implícita também é conhecida como auto-concat. Em ambos os casos, os espaços que precedem a variável e o ponto são obrigatórios.

A função Format também pode ser usada para este propósito. Por exemplo:

MsgBox % Format("You are using AutoHotkey v{1} {2}-bit.", A_AhkVersion, A_PtrSize*8)

Para atribuir um valor para uma variável, use o operador de atribuição :=, como em MinhaVar := "Algum texto".

Sinais de porcentagem dentro de uma expressão são usados para criar referências dinâmicas de variáveis e chamadas dinâmicas de função. Essas estruturas não são necessárias na maioria das vezes, então, no geral, nomes de variáveis não devem ser cercados em sinais de porcentagem dentro de uma expressão.

Operadores

Operadores assumem a forma de um símbolo ou grupo de símbolos, como em +, := ou uma das palavras and, or, not ou new. Eles pegam um, dois ou três valores como entrada e retornam um valor como resultado. Um valor ou sub-expressão usado como entrada para um operador é chamado de um operando.

Alguns operadores unários e binários compartilham os mesmos símbolos, neste caso o significado do operador depende se ele está escrito antes, depois ou entre dois valores. Por exemplo, x-y faz uma subtração enquanto que -x inverte o sinal de x (produzindo um valor positivo a partir de um valor negativo e vice-versa).

Operadores de precedência igual como multiplicação (*) e divisão (/) são avaliados na ordem da esquerda para a direita a menos que esteja especificado de outra maneira na tabela de operadores. Em contraste, um operador de precedência menor como a adição (+) é avaliado depois de um maior como a multiplicação (*). Por exemplo, 3 + 2 * 2 é avaliado como 3 + (2 * 2). Parênteses podem ser usados para sobrepor a precedência como mostrado neste exemplo: (3 + 2) * 2

Chamadas de função

Para uma explicação geral sobre funções e terminogias relacionadas, veja Comandos/Funções.

Funções fazem uso de um número variável de entradas, realizam alguam ação ou cálculo e então retornam um resultado. As entradas de uma função são chamadas de parâmetros ou argumentos. Uma função é chamada pela simples ação de se escrever seu nome seguido de seus parâmetros envoltos por parênteses. Por exemplo, GetKeyState("Shift") retorna (resulta em) 1 se a tecla Shift estiver sendo pressionada ou 0 caso contrário.

OBS: Não deve haver nenhum espaço entre o nome da função e os parênteses.

Quando comparada a um comando, a exigência de parênteses pode parecer enigmática a primeira vista, mas são eles que permitem que uma chamada de função seja combinada com outras operações. Por exemplo, a expressão GetKeyState("Shift", "P") e GetKeyState("Ctrl", "P") retorna 1 apenas se ambas as teclas estiverem fisicamente pressionadas.

Os nomes de funções sempre são globais, e são separadas de nomes de variáveis. Por exemplo, Round pode ser tanto um nome de variável quanto de uma função e Round := 1 não afetará Round(n) em nada.

Operadores para Objetos

Existem outros símbolos usados em expressões que não se encaixam em nenhuma das categorias definidas acima ou que afetam o significado de outras partes da expressão, como descrito abaixo: Todos esses se relacionam com objetos de alguma maneira. Fornecer uma explicação completa sobre o que cada estrutura faz exigiria a introdução de mais conceitos que não são abrangidos por esta seção.

Alpha.Beta é frequentemente chamado de member access. Alpha é uma variável ordinária e pode ser substituida com uma chamada de função ou alguma outra sub-expressão que retorna um objeto. Quando avaliado, o objeto envia uma solicitação "me dê o valor da propriedade Beta", "armazene este valor na propriedade Beta" ou "chame o método nomeado como Beta". Em outras palavras, Beta é um nome que possui significado para o objeto; isso não é uma variável local ou global.

Alpha.Beta() é um método de chamada, como descrito acima.

Alpha.Beta[Param] é uma forma especializada do acesso de member acess que inclui parâmetros adicionais na solicitação. Enquanto que Beta é apenas um nome, Param é uma variável ordinária ou sub-expressão, ou uma lista de sub-expressões separadas por vírgulas (o mesmo que em uma lista de parâmetros de função).

Alpha[Index] possui uma função similar a Alpha.Beta, mas cada parte é interpretada de uma maneira mais padrão. Isto é, ambos Alpha e Index são variáveis neste caso e podem ser substituídos virtualmente por qualquer sub-expressão. Esta sintaxe normalmente é usada para recuperar um elemento de um array ou array associativo.

new ClassName() é usada para iniciar uma classe ou criar um objeto derivado de outro objeto. Embora isso se pareça com uma chamada de função, ClassName na verdade é uma variável ordinária. De forma parecida, new Alpha.Beta() criaria um objeto derivado do objeto retornado por Alpha.Beta; Beta não é nem uma função e nem um método. Se os parênteses opcionais estiverem presentes, eles podem conter parâmetros para o método __New do objeto.

[A, B, C] cria um array com os conteúdos iniciais A, B e C (todas as variáveis neste caso), onde o elemento A é 1.

{Key1: Value1, Key2: Value2} cria um array associativo a partir de uma lista de pares de chave-valor. Um valor pode ser recuperado posteriormente por sua chave associada. Escrever uma palavra simples (consistindo de caracteres alfanuméricos, underscore e caracteres non-ASCII) à esquerda de : é equivalente a cercar aquela palavra em aspas. Por exemplo, {A: B} é equivalente à {"A": B}. Entretanto, {(A): B} usa o conteúdo da variável A como chave.

MyFunc(Params*) é uma chamada de função variádica. O asterisco deve preceder imediatamente o parêntese de fechamento no final da lista de parâmetros da função. Params deve ser uma variável ou sub-expressão que retorna um objeto array. Embora isso não valide usar Params* em qualquer lugar, ele pode ser usado em um array literal ([A, B, C, ArrayToAppend*]) or indexer (Alpha[Params*]).

Declarações de Expressão

Nem todas as expressões podem ser usadas sozinhas em uma linha. Por exemplo, uma linha consistindo apenas de 21*2 ou "Algum texto" não faria nenhum sentido. Uma declaração de expressão é uma expressão usada por si própria, tipicamente por seus efeitos secundários. Muitas expressões com efeitos secundários podem ser usadas desta forma, então não é necessário memorisar os detalhes desta seção.

Os seguintes tipos de expressões podem ser usados como declarações:

Atribuições, como em x := y, atribuições compostas como em x += y e operadores de incrementação/decrementação como ++x e x--. Contudo, no AutoHotkey v1, ++, --, +=, -=, *= e /= possuem um comportamento ligeiramente diferente quando usados sozinhos em uma linha, já que eles são equivalentes à EnvAdd, EnvSub, EnvMult ou EnvDiv. Para detalhes, veja "Limitações conhecidas" dentro de Atribuir na tabela de operadores.

Chamadas de função como MyFunc(Params). Porém, uma chamada de função autônoma não pode ser seguida por uma chave de abertura { (no final da linha ou na próxima linha) porque isso seria confundido com uma declaração de função.

Chamadas de métodos como MyObj.MyMethod().

Acesso de membro usando colchetes, como MyObj[Index], que possui efeitos secundários como uma chamada de função.

Expressões começadas com o operador new, como em new ClassName, porque às vezes uma classe pode ser inicializada só por seus efeitos secundários

Expressões ternárias, como x ? CallIfTrue() : CallIfFalse(). Porém, é mais seguro utilizar a regra abaixo; isto é, sempre cercar a expressão (ou apenas a condição) em parênteses.

OBS: Nomes de comandos têm precedência sobre ternários no AutoHotkey v1. Por exemplo, MsgBox ? 1 : 0 mostra uma caixa de diálogo.

OBS: A condição não pode começar com ! ou qualquer outro operador de expressão, já que seria interpretado como uma linha de continuação.

Expressões iniciadas com(. Contudo, deve haver um ) correspondente na mesma linha, caso contrário a linha seria interpretada como o início de uma seção de continuação.

Para simplificar: Expressões iniciadas com qualquer um dos descritos acima (mas não os que são descritos abaixo) também são permtidos. Por exemplo, MyFunc()+1 é permitido atualmente, mesmo que +1 não possua efeito e seu resultado seja descartado. Tais expressões podem se tornar inválidas futuramente por motivos de melhorias na verificação de erros.

Acesso de membro usando um ponto (uma vez ou em uma série), como ExcelApp.Quit oux.y.z. No entanto, ao contrário do uso de parênteses (como em uma chamada de método), isso não pode ser o prefixo de uma expressão grande. Por exemplo, ExcelApp.Quit, xxx é proibido devido a aparência semelhante à sintaxe dos comandos.

Sintaxe legado

A sintaxe Legado ou a sintaxe de comando geralmente permitem apenas uma ação por linha, mas usam alguns caracteres para realizar simples tarefas como enviar o pressionamento de teclas ou executar um programa. A sintaxe consiste de comandos e nomes de variáveis, textos não cercados e vários símbolos como ,, = and %.

Texto não cercado nada mais é do que apenas textos que não são cercados por aspas. Desde que o texto não tenha marcas de início e fim explícitas, ele terminará no final da linha ou no final do parâmetro. Espaços e tabs no começo e no final da linha são ignorados. Dentro de textos não cercados, os seguintes caracteres possuem significado especial:

Commands accept a mixture of unquoted text, variable names and numeric expressions.

Send, The time is %A_Hour% o'clock.

Legacy assignment assigns unquoted text to a variable.

Clipboard = This text is copied to the clipboard.

If statements perform an action only if the specified condition is met.

If Var = Text value

There are also several other control flow statements (such as loops) which use legacy syntax similar to commands.

Comandos

A command is an instruction to carry out a specific predefined action. "Command" may also refer to a specific predefined action, such as MsgBox. The set of available commands is predefined and cannot be changed by the script.

A command is called simply by writing its name at the beginning of a line, optionally followed by parameters. Por exemplo:

MsgBox, The time is %A_Hour% o'clock.

The comma separating the command name from its parameters is optional, except in the following cases:

Each parameter of a command may accept different syntax, depending on the command. There are four types of parameters:

In most cases the percent prefix can be used to pass an expression.

Parâmetros de Entrada e Saída

OutputVar and InputVar parameters require a variable name or dynamic variable reference. Por exemplo:

; Replace all spaces with pluses:
StringReplace, NewStr, OldStr, %A_Space%, +, All

This command reads the value from OldStr (the InputVar) and stores the result in NewStr (the OutputVar).

Note: Only a plain variable can be used as an OutputVar. Array elements, properties and other expressions are not supported.

InputVar parameters can accept an expression only when the percent prefix is used. However, the prefix is not supported in the Var parameters of legacy If commands, so If (expression) should be used instead.

Parâmetros de texto

Text parameters accept unquoted text. Por exemplo:

MsgBox, The time is %A_Hour% o'clock.

Since commas and percent signs have special meaning, use the escape sequence `, to specify a literal comma and `% to specify a literal percent sign. For clarity, it is best to always escape any comma which is intended to be literal, but escaping comma is optional in the following cases:

To include a leading or trailing space or tab, use the built-in variables %A_Space% and %A_Tab% or a forced expression such as % " x ". [v1.1.06+]: Whitespace can also be preserved by preceding the space or tab with an escape character, except for whitespace at the end of a line.

Text parameters can also accept a forced expression.

Parâmetros numéricos

Numeric parameters accept a literal number or an expression, and can be identified by phrasing like "This parameter can be an expression."

For historical reasons, simple variable references alone or combined with digits are not interpreted as expressions. Por exemplo:

Sleep %n%000  ; Sleep for n seconds.
Sleep %m%     ; Sleep for m milliseconds.

To perform a double-deref in such cases, enclose the expression in parentheses: Sleep (%m%)

Note that mixed-type parameters such as SetTimer's second parameter, which sometimes accepts a number and sometimes accepts a string such as On or Off, are actually Text parameters, and as such, they do not accept expressions unless the percent prefix is used.

Numeric parameters allow and ignore the percent prefix.

% Expressão

Although purely numeric parameters accept an expression by default, all other parameters of commands do not. Specify a percent sign followed by a space or tab to force a parameter to accept an expression. For example, all of the following are effectively identical because Sleep's first parameter is expression-capable:

Sleep MillisecondsToWait
Sleep %MillisecondsToWait%
Sleep % MillisecondsToWait

Note: Using the percent-space prefix in a numeric parameter does not necessarily force it to be an expression.

All parameters support the percent-space prefix except for:

Some users may find it easier to always force an expression, keeping to one consistent syntax (expression syntax) as much as possible.

Convenções da documentação

At the top of each page which documents a command, there is usually a block showing syntax, like this:

StringLower, OutputVar, InputVar , T

The square brackets denote optional parameters; the brackets themselves must be omitted from the actual code.

Sometimes the value a parameter accepts is written directly in the syntax block. For example, the third parameter of StringLower shown above accepts the letter T as text. The exact usage of a parameter is described in the Parameters section, and varies between commands.

Parâmetros Opcionais

Optional parameters can simply be left blank. The comma preceding an optional parameter can also be omitted if all subsequent parameters are omitted. For example, the Run command can accept between one and four parameters. All of the following are valid:

Run, notepad.exe, C:\
Run, notepad.exe,, Min
Run notepad.exe, , , notepadPID

Expressões vs Sintaxe Legado

Many command parameters do not accept expressions by default. Use the percent-space prefix at the beginning of a parameter to evaluate that parameter as an expression. In the following examples, the expression is shown on the first line (beginning after the percent sign), with pure legacy syntax shown on the second line.

MsgBox % 1+1  ; Shows "2"
MsgBox   1+1  ; Shows "1+1"

Literal text in an expression is always enclosed in quote marks. These are called quoted strings.

MsgBox % "This is text."
MsgBox    This is text.

Variables in an expression are never enclosed in percent signs, except to create a double reference.

MsgBox %  A_AhkVersion
MsgBox   %A_AhkVersion%

Variables cannot be used inside a quoted string.

MsgBox % "Hello %A_UserName%."  ; Shows "%A_UserName%"
MsgBox    Hello %A_UserName%.   ; Shows your username.

Instead, values are concatenated by writing them in sequence, separated by a space or tab, or a dot surrounded by spaces.

MsgBox % "Hello " . A_UserName . "."  ; Shows your username.

One alternative is to use the Format function, which can also format the parameter value in various ways.

MsgBox % Format("Hello {1}.", A_UserName)  ; {} also works in place of {1}.

A value is assigned to a variable with := instead of =:

MyVar := "This is text."
MyVar = This is text.

Comparisons are performed using the same symbols as legacy If: =, <> or !=, >, >=, < and <=.

if (Var1 = Var2)
if Var1 = %Var2%

In an expression, both values can be simple values or complex sub-expressions. A comparison can also be combined with other conditions using operators such as and and or (which are equivalent to && and ||).

if (Var1 >= Low and Var1 <= High)
if Var1 between %Low% and %High%  

Iguais Diferentes

One common mistake is to write = where := is needed. Por exemplo:

Total = A + B   ; Assigns the literal text "A + B"

This can be difficult to avoid (at least until such time as the legacy assignment syntax is removed), but it may help to always use := where an assignment is intended.

The equal sign (when not used with another symbol, such as <=) has the following meanings:

The first two cases can be avoided by always using the := assignment operator and if (expression).

For the last three cases, := should have been used instead of =.

Comandos vs Funções

In AutoHotkey v1, it is currently not possible to call a command from an expression, or to call a function using the command syntax. However, several commands have a function replacement.

CommandReplacement
FileAppendFileOpen and File.Write
FileGetAttribFileExist
FileReadFileOpen and File.Read
GetKeyStateGetKeyState (the function returns 0 or 1, not "U" or "D")
IfExistFileExist
IfInStringInStr
IfWinActiveWinActive
IfWinExistWinExist
StringGetPosInStr
StringLenStrLen
StringReplaceStrReplace
StringSplitStrSplit
StringLower
StringUpper
Format("{:L}", input), Format("{:U}", input) or Format("{:T}", input)
StringLeft
StringMid
StringRight
StringTrimLeft
StringTrimRight
SubStr

Declarações de Controle de Fluxo

For a general explanation of control flow, see Control Flow.

Statements are grouped together into a block by enclosing them in braces {}, as in C, JavaScript and similar languages, but usually the braces must appear at the start of a line. Control flow statements can be applied to an entire block or just a single statement.

The body of a control flow statement is always a single group of statements. A block counts as a single group of statements, as does a control flow statement and its body. The following related statements are also grouped with each other, along with their bodies: If with Else; Loop/For with Until; Try with Catch and/or Finally. In other words, when a group of these statements is used as a whole, it does not always need to be enclosed in braces (however, some coding styles always include the braces, for clarity).

Control flow statements which have a body and therefore must always be followed by a related statement or group of statements: If, Else, Loop, While, For, Try, Catch and Finally.

The following control flow statements exist:

Controle de Fluxo vs Comandos

Control flow statements have syntax resembling commands, and are often referred to as such, but some differ from commands:

Declaração If

If (expression) evaluates an expression and executes the following statement only if the result is true.

Common cause of confusion: There are several other types of If statements, some of which look very similar to If (expression). These should be avoided in new scripts. If in doubt, it is best to always begin the expression with an open-parenthesis. The "legacy" If statements are as follows:

Any If statement which does not match one of the usages shown above is interpreted as If (expression).

These are some common points of confusion related to legacy If statements:

The following "legacy" named If statements also exist:

With the exception of IfMsgBox, these are all obsolete and generally should be avoided in new scripts.

Named If statements allow a command to be written on the same line, but mispelled command names are treated as literal text. Such errors may be difficult to detect.

Declaração Loop

There are several types of loop statements:

Break exits (terminates) a loop, effectively jumping to the next line after the loop's body.

Continue skips the rest of the current loop iteration and begins a new one.

Until causes a loop to terminate when an expression evaluates to true. The expression is evaluated after each iteration.

A label can be used to "name" a loop for Continue and Break. This allows the script to easily continue or break out of any number of nested loops without using Goto.

The built-in variable A_Index contains the number of the current loop iteration. It contains 1 the first time the loop's body is executed. For the second time, it contains 2; and so on. If an inner loop is enclosed by an outer loop, the inner loop takes precedence. A_Index works inside all types of loops, but contains 0 outside of a loop.

For some loop types, other built-in variables return information about the current loop item (registry key/value, file, substring or line of text). These variables have names beginning with A_Loop, such as A_LoopFileName and A_LoopReadLine. Their values always correspond to the most recently started (but not yet stopped) loop of the appropriate type. For example, A_LoopField returns the current substring in the innermost parsing loop, even if it is used inside a file or registry loop.

t := "column 1`tcolumn 2`nvalue 1`tvalue 2"
Loop Parse, t, `n
{
    rowtext := A_LoopField
    rownum := A_Index  ; Save this for use in the second loop, below.
    Loop Parse, rowtext, `t
    {
        MsgBox %rownum%:%A_Index% = %A_LoopField%
    }
}

Loop variables can also be used outside the body of a loop, such as in a function or subroutine which is called from within a loop.

Sem Controle de Fluxo

As directives, labels (including hotkeys and hotstrings), and declarations without assignments are processed when the script is loaded from file, they are not subject to control flow. In other words, they take effect unconditionally, before the script ever executes any control flow statements. Similarly, the #If directives such as #IfWinActive cannot affect control flow; they merely set the criteria for any hotkey labels and hotstrings specified in the code. A hotkey's criteria is evaluated each time it is pressed, not when the #If directive is encountered in the code.

Estrutura de um Script

Seção de auto-execução

After the script has been loaded, it begins executing at the top line, continuing until a Return, Exit, the script's first hotkey/hotstring label, or the physical end of the script is encountered (whichever comes first). This top portion of the script is referred to as the auto-execute section, but it is really just a subroutine which is called after program startup.

Note: While the script's first hotkey/hotstring label has the same effect as return, other hotkeys and labels do not.

The auto-execute section is often used to configure settings which apply to every newly launched thread. For details, see The Top of the Script.

Sub-rotinas

A subroutine (or sub) is a reusable block of code which can be called to perform some task.

Scripts use subroutines to define what should happen when a particular hotkey is pressed or some other event occurs. Scripts can also call subroutines directly, by using Gosub.

Any label can be used as the starting point of a subroutine. A subroutine has no explicitly marked ending point, but instead ends if and when control is returned to the subroutine's caller by Return or when the thread is exited. Por exemplo:

gosub Label1

Label1:
MsgBox %A_ThisLabel%
return

Note that as labels have no effect when reached during normal execution, in this example a MsgBox would be shown twice: once while the subroutine is running and again after it returns. One important consequence is that you cannot define one subroutine inside another subroutine, because the "body" of the inner subroutine would execute automatically and then return, effectively terminating the outer subroutine.

Subroutines should typically be defined separately to any other block of code, but can also be defined inside a function, allowing the subroutine access to that function's static variables (and local variables, but only while the function is running).

Note: Subroutines defined inside a function have certain limitations regarding the use of local variables and dynamic variable references, including Gui control variables. For details, see Using Subroutines Within a Function.

Funções Definidas Pelo Usuário

Generally speaking, a function is a kind of subroutine. However, within the AutoHotkey documentation, "subroutine" typically refers to the kind of subroutine defined by a label (described above).

User-defined functions differ from subroutines in that they can accept parameters and return a value, and they can have local variables. They can be called either by a function call within the script or by the program itself, such as if a function was passed to the Hotkey or SetTimer commands.

Functions are defined using syntax resembling a function call followed by a block of code enclosed in braces:

MyFunction(FirstParameter, Second, ByRef Third, Fourth:="")
{
    ...
    return "a value"
}

As with function calls, there must be no space between the function name and open-parenthesis.

The line break between the close-parenthesis and open-brace is optional. There can be any amount of whitespace or comments between the two.

ByRef indicates that the parameter accepts a variable reference, making that parameter an alias for whichever variable the caller passes. If the caller does not pass a variable, the parameter acts as a normal local variable. ByRef parameters can also be optional.

Optional parameters are specified by following the parameter name with := or = and a default value, which must be a literal quoted string, a number, true or false. The operators := and = are interchangeable for historical reasons, but it is best to use := for consistency with assignment in expressions.

The function can return a value. If it does not, the default return value is an empty string.

A function cannot be defined inside another function. Otherwise, the position of a function definition does not matter; any function defined within the script can be called from anywhere else.

See Functions for much more detail.

#Include

The #Include directive causes the script to behave as though the specified file's contents are present at this exact position. This is often used to organise code into separate files, or to make use of script libraries written by other users.

Note: The following paragraphs detail some common points of confusion.

When using #Include, it is important to consider what effect the file's contents would have if placed at that position, since #Include will have the same effect. For instance:

#Include can be safely used within the auto-execute section to include files which contain only function definitions, since function definitions (but not function calls) are skipped over during execution. If a file contains other code, one can avoid breaking the auto-execute section by skipping over the file's contents with Goto.

Unlike in C/C++, #Include does nothing if the file has already been included by a previous directive. To include the contents of the same file multiple times, use #IncludeAgain.

Script files containing functions can be automatically included without having to use #Include, if they are saved in a standard location and named appropriately. The effect is similar to using #Include at the end of the main script file. For details, see Libraries of Functions.

Variedades

Variáveis Dinâmicas

A dynamic variable reference takes a text value and interprets it as the name of a variable.

The most common form of dynamic variable reference is called a double reference or double-deref. Before performing a double reference, the name of the target variable is stored in a second variable. This second variable can then be used to assign a value to the target variable indirectly, using a double reference. Por exemplo:

target := 42
second := "target"
MsgBox   %second%  ; Normal (single) variable reference in text => target
MsgBox %  second   ; Normal (single) variable reference in an expression => target
MsgBox % %second%  ; Double-deref in an expression => 42

At first, it would appear that percent signs have a different meaning depending on whether they are used in text or in an expression. However, it may make more sense to think of %second% as being replaced with the contents of the variable second in both cases:

Currently, second must always contain a variable name in the second case; arbitrary expressions are not supported.

A dynamic variable reference can also take one or more pieces of literal text and the content of one or more variables, and join them together to form a single variable name. This is done simply by writing the pieces of the name and percent-enclosed variables in sequence, without any spaces. For example, MyArray%A_Index% or MyGrid%X%_%Y%. This is used to access pseudo-arrays, described below.

For a description of how dynamic variable references inside functions are resolved, see Functions: More about locals and globals.

Pseudo-arrays

A pseudo-array is actually just a bunch of discrete variables, but with a naming pattern which allows them to be used like elements of an array. Por exemplo:

MyArray1 = A
MyArray2 = B
MyArray3 = C
Loop 3
    MsgBox % MyArray%A_Index%  ; Shows A, then B, then C.

As the individual elements are just normal variables, one can assign or retrieve a value, but cannot remove or insert elements. Because the pseudo-array itself doesn't really exist, it can't be passed to or returned from a function, or copied as a whole. For these reasons, it is generally recommended to use normal arrays instead, where possible.

Pseudo-arrays associativos

The "index" used to form the final variable name does not have to be numeric; it could instead be a letter or keyword, making the pseudo-array similar to an associative array or an object. The following example creates a pseudo-array with elements "Left", "Top", "Right" and "Bottom":

SysGet, WA, MonitorWorkArea
MsgBox, Left: %WALeft% -- Top: %WATop% -- Right: %WARight% -- Bottom: %WABottom%.

Comandos que criam pseudo-arrays

There are several commands which create associative pseudo-arrays:

Caution: These commands do not follow the same rules as dynamic variable references. If used within a function, the resulting pseudo-array is either entirely global or entirely local, depending only on the first element (or base name) of the array. Some of the variables in the pseudo-array may be inaccessible if they are not individually declared. For details, see Functions: More about locals and globals.

AutoHotkey also creates one global pseudo-array to contain any command line parameters that were passed to the script.

Labels

A label identifies a line of code, and can be used as a Goto target or to form a subroutine. There are three kinds of label: normal named labels, hotkey labels and hotstring labels.

Normal labels consist of a name followed by a colon.

this_is_a_label:

Hotkey labels consist of a hotkey followed by double-colon.

^a::

Hotstring labels consist of a colon, zero or more options, another colon, an abbreviation and double-colon.

:*:btw::

Generally, aside from whitespace and comments, no other code can be written on the same line as a label. However:

For more details, see Labels.