Este documento cobre alguns conceitos gerais e convenções usadas pelo AutoHotkey, num artigo focado mais na explicação do que no código. Não se assume que o leitor tenha qualquer conhecimento prévio de confecção de scripts ou programação, mas deve estar preparado para aprender novas terminologias.
Para detalhes mais específicos sobre a sintaxe, veja Linguagem de Confecção de Scripts.
Um valor é simplesmente um pedaço de informação dentro de um programa. Por exemplo, o nome de uma tecla a ser enviada ou um programa a executar, o número de vezes que uma hotkey foi pressionada, o título de uma janela a ser ativada, ou qualquer que seja a coisa que tenha algum significado dentro do programa ou script.
O AutoHotkey suporta estes tipos de valores:
Alguns outros conceitos relacionados:
Uma string é simplesmente texto. Cada string é na verdade uma sequência ou cadeia de caracteres, mas pode ser tratada como uma entidade única. O comprimento de uma string é o número de caracteres na sequência, enquanto a posição de um caractere na string é meramente o número sequencial daquele caractere. No AutoHotkey, por convenção, o primeiro caractere está na posição 1.
Strings numéricas: uma string de dígitos (ou qualquer outro formato de número suportado) é automaticamente interpretado como um número quando uma operação matemática ou comparação o requer. Na versão 1 do AutoHotkey, comparações são feitas numericamente se ambos os valores são números mesmo que ambos sejam strings. Entretanto, uma string entre aspas (ou o resultado de da concatenação com uma string entre aspas) nunca é considerada numérica quando usada diretamente numa expressão.
A forma com que texto literal deve ser escrito dentro do script depende do contexto. Para detalhes, veja Sintaxe Legada e Strings (em expressões).
Para uma explicação mais detalhada de como strings funcionam, veja Codificação de Strings.
O AutoHotkey suporta estes formatos de números:
123
, 00123
ou -1
.0x78
, 0x007B
ou -0x1
.3.14159
.Números hexadecimais devem usar o prefixo 0x
ou 0X
, exceto onde estiver especificado na documentação. Esse prefixo deve ser escrito depois do sinal de +
ou -
, se presente, e antes de quaisquer zeros à esquerda. Por exemplo, 0x001
é válido, mas 000x1
não é.
Números escritos com uma casa decimal são sempre considerados como ponto flutuante, mesmo quando a parte fracionária é zero. Por exemplo, 42
e 42.0
são geralmente equivalentes, mas nem sempre. Notação científica também é reconhecida, mas somente se uma casa decimal estiver presente (exemplo: 1.0e4
e -2.1E-4
).
O separador de casas decimais é sempre um ponto, mesmo se as configurações regionais do usuário especificarem a vírgula.
Quando um número é convertido em uma string, ele é formatado de acordo com o formato de inteiro ou decimal atual. Apesar de o comando SetFormat poder ser usado para alterar o formato atual, costuma ser melhor usar a função Format para formatar uma string. Números de ponto flutuante também podem ser formatados usando-se a função Round.
Para detalhes sobre o intervalo e a precisão de valores numéricos, veja Números Puros.
Um valor booleano pode ou ser verdadeiro ou falso. Valores booleanos são usados para representar qualquer coisa que tenha exatamente dois estados possíveis, como a verdade de uma expressão. Por exemplo, a expressão (x <= y)
é verdadeira quando x tem valor igual ou menor que y. Um valor booleano também pode representar sim ou não, ligado ou desligado, pressionada ou solta (nas situações em que o estado de uma tecla é verificado, tal como ocorre quando se usa o comando GetKeyState), entre outros.
O AutoHotkey não tem um tipo específico de valor booleano, então ele usa o valor inteiro 0
para representar falso e 1
para representar verdadeiro. Quando se exige que um valor seja verdadeiro ou falso, um valor em branco ou igual a zero é considerado falso e todos os demais valores são considerados verdadeiros. (Objetos sempre são considerados verdadeiros.)
As palavras true
e false
são variáveis nativas contendo 1 e 0. Elas podem ser usadas para tornar um script mais legível.
O AutoHotkey não possui um valor próprio para representar nothing, null, nil ou undefined, como visto em outras linguagens. Em vez disso, uma string vazia (uma string com comprimento zero) é o que costuma fazer esse papel no AHK.
Se uma variável ou parâmetro é dito “vazio” ou “em branco”, isso geralmente é o mesmo que uma string vazia (uma string de comprimento zero).
Há normalmente duas maneiras de visualizar objetos:
O uso correto de objetos (e, em particular, classes) pode resultar em código modular e reusável. Código modular é geralmente mais fácil de testar, entender e manter. Por exemplo, alguém pode melhorar ou modificar uma seção de código sem precisar saber os detalhes de outra seção, e sem ter que realizar as modificações necessárias a tais seções. Código reusável poupa tempo, dispensando a necessidade de escrever e testar código para a mesma tarefa ou tarefas similares a cada vez.
Quando você atribui um objeto a uma variável, como no exemplo meuObjeto := {}
, o que você armazena não é o objeto em si, mas uma referência a ele. Copiar aquela variável, como em seuObjeto := meuObjeto
, cria uma nova referência ao mesmo objeto. Uma alteração como meuObjeto.resposta := 42
seria refletida tanto em meuObjeto.resposta
e seuObjeto.resposta
, uma vez que ambos se referem ao mesmo objeto. Contudo, meuObjeto := Object()
só afetará a variável meuObjeto, não a variável seuObjeto, a qual ainda se refere ao objeto original.
Esta seção se baseia nos conceitos seguintes, que são cobertos em seções posteriores: variáveis, funções
Objetos funcionam de acordo com o princípio da troca de mensagens. Você não sabe onde um código ou variáveis de um objeto efetivamente ficam, então você deve passar uma mensagem ao objeto, como “dê-me foo” ou “vá fazer bar”, e esperar que o objeto responda a essa mensagem. Objetos no AutoHotkey suportam as mensagens básicas a seguir:
:=
.()
.Cada mensagem pode opcionalmente possuir um ou mais parâmetros, (e, para o caso de Set, o valor). Normalmente existe pelo menos um parâmetro, e ele é interpretado como o nome de uma propriedade ou método, uma chave ou índice de vetor, dependendo do objeto e como você está usando-o. Os parâmetros de uma mensagem são especificados usando-se três diferentes padrões: .Name
, [Parâmetros]
e (Parâmetros)
, onde Name é um nome ou identificador literal, e Parâmetros é uma lista de parâmetros (na forma de sub-expressões), a qual pode ser vazia/em branco ([]
ou ()
).
Para Get e Set, .Name
e [Parâmetros]
podem ser usados indistintamente, ou em conjunto:
meuObjeto[arg1, arg2, ..., argN] meuObjeto.name meuObjeto.name[arg2, ..., argN]
Para Call, .Name
e [Parâmetro]
podem ser usados indistintamente, e devem sempre ser seguidos de (Parâmetros)
:
meuObjeto.name(arg2, ..., argN) meuObjeto[arg1](arg2, ..., argN)
Note que se name
estiver presente, ele se torna o primeiro parâmetro. meuObjeto.name
é equivalente a meuObjeto["name"]
, enquanto meuObjeto.123
é equivalente a meuObjeto[123]
. Isso é verdade para todo tipo de objeto, então é sempre possível computar o nome de uma propriedade ou método em tempo de execução, em vez de codificá-lo no script.
Apesar de name ou arg1 serem considerados como o primeiro parâmetro, lembre-se que esses são somente mensagens, e o objeto está livre para manipulá-los de qualquer maneira. mas não sempNuma chamada de método como as mostradas acima, normalmente o objeto usa name ou arg1 para identificar qual método deve ser chamado, e então arg2 e seguintes são passados ao método. Com efeito, arg2 torna-se o primeiro parâmetro aparente do método.
Geralmente, Set tem o mesmo significado de uma atribuição de valor, então usa o mesmo operador:
meuObjeto[arg1, arg2, ..., argN] := valor meuObjeto.name := valor meuObjeto.name[arg2, ..., argN] := valor
Também existe uma sintaxe “híbrida” permitida para a instrução Set, mas é melhor não a usar:
meuObjeto.name(arg2, ..., argN) := valor
Tecnicamente, o valor
é passado como último parâmetro da mensagem Set, entretanto, esse detalhe quase nunca é relevante para autores de scripts. Geralmente alguém pode simplesmente pensar nele como “o valor que está sendo atribuído”.
Uma variável permite que você use um nome como um marcador de posição de um valor. Já qual valor é esse é algo que pode mudar repetidamente durante o tempo em que seu script estiver rodando. Por exemplo, uma hotkey pode usar uma variável contagem_pressionamentos
para contar o número de vezes que ela foi pressionada, e enviar o pressionamento de uma tecla diferente toda vez que contagem_pressionamentos
for um múltiplo de 3 (a cada três pressionamentos). Mesmo uma variável à qual somente uma vez é atribuído um valor pode ser útil. Por exemplo, uma variável TituloDoNavegadorWeb
pode ser usada para fazer seu código mais fácil de atualizar quando você resolver mudar seu browser preferido, ou se o título ou classe de janela muda devido a uma atualização de software.
No AutoHotkey, as variáveis são criadas no momento em que são simplesmente usadas. Cada variável não é permanentemente restrita a um tipo de dados, mas pode ter um valor de qualquer tipo: string, número ou objeto. Cada variável começa vazia/em branco; em outras palavras, cada variável nova contém uma string vazia até que a ela seja atribuído um outro valor.
Uma variável tem três aspectos principais:
Algumas restrições se aplicam a nomes - vide Nomes para detalhes. Em resumo, é melhor manter nomes que consistam somente em letras ASCII (as quais não diferenciam maiúsculas e minúsculas), algarismos e underscores, e evitar usar nomes que comecem com um algarismo.
Uma variável tem um escopo, o qual define onde no código aquele nome pode ser usado para se referir àquela variável em particular; em outras palavras, onde a variável está visível. Se uma variável não está visível dentro de determinado escopo, o mesmo nome pode ser referir a uma outra variável. Ambas as variáveis podem existir ao mesmo tempo, mas somente uma estará visível a cada parte do script. Variáveis globais são visíveis no “escopo global” (isto é, fora de funções), mas devem normalmente ser declaradas para ficarem visíveis dentro de uma função. Variáveis locais são visíveis somente dentro da função que as criou.
Uma variável pode ser entendida como um contêiner ou local de armazenamento para um valor, então você muitas vezes vai ver que a documentação se refere ao valor da variável como o conteúdo da variável. Para uma variável x := 42
, nós também podemos dizer que a variável x tem o número 42 como seu valor, ou que o valor de x é 42.
É importante notar que a variável e seu valor não são a mesma coisa. Exemplificativamente, nós poderíamos dizer “meuVetor
é um vetor”, mas o que realmente queremos dizer é que meuVetor é uma variável contendo uma referência a um vetor. O que estamos fazendo é tomar um atalho ao usar o nome da variável para se referir ao seu valor, mas “meuVetor” é na verdade apenas o nome da variável; o objeto vetor não sabe que ele tem um nome, e poderia ser referenciado por várias variáveis diferentes (portanto, vários diferentes nomes).
Inicializar uma variável é atribuir a ela um valor inicial. Apesar de o programa automaticamente inicializar todas as variáveis (uma string vazia sendo o valor padrão), é uma boa prática que o script sempre inicialize as variáveis antes do uso. Dessa forma, qualquer pessoa lendo o script pode ver quais variáveis o script usará e quais valores iniciais espera-se que elas tenham.
Costuma ser necessário que o script inicialize qualquer variável cujo valor que se espera que ela armazene seja um número. Por exemplo, x := x + 1
não irá funcionar se à variável x nunca tiver sido atribuído um valor antes, já que a string vazia é considerada não numérica. O script deveria ter atribuído um valor inicial, como x := 0
. Há alguns casos em que valores vazios são considerados iguais a 0, mas é melhor não pressupor isso.
IsSet can be used to determine whether a variable has been initialized, such as to initialize a global or static variable on first use.
Autores de scripts podem usar a diretiva #Warn para ajudar a encontrar instâncias em que uma variável é usada sem ter sido inicializada pelo script.
Há várias variáveis úteis que são nativas ao programa e que podem ser referenciadas por qualquer script. Com a exceção de Clipboard, ErrorLevel e parâmetros da linha de comando, essas variáveis são somente leitura; isto é, seus conteúdos não podem ser diretamente alterados por um script. Por convenção, a maioria dessas variáveis inicia com o prefixo A_
, então é melhor evitar usar esse prefixo nas variáveis que você criar.
Algumas variáveis como A_KeyDelay e A_TitleMatchMode representam configurações que controlam o comportamento do script, e retêm valores separados para cada fio de execução. Isso permite que sub-rotinas sejam executadas por novos fios de execução (como hotkeys, menus, timers e afins) para alterar configurações sem afetar outros fios de execução.
Há também algumas variáveis especiais que não são atualizadas periodicamente; em vez disso, seus valores são obtidos ou calculados toda vez que o script referencia essa variável. Por exemplo, Clipboard obtém o valor do conteúdo atual da área de transferência como texto, e A_TimeSinceThisHotkey calcula o número de milissegundos que se passaram desde que a hotkey foi pressionada.
Assuntos relacionados: lista de variáveis nativas.
Variáveis de ambiente são mantidas pelo sistema operacional. Você pode ver uma lista delas no prompt de comando digitando SET e depois Enter.
Um script pode criar uma variável de ambiente ou alterar o conteúdo de uma com EnvSet. Tais adições e alterações não são vistas pelo resto do sistema. Todavia, quaisquer programas ou scripts que o script vier a executar por meio do comando Run ou RunWait normalmente herdam uma cópia das variáveis de ambiente do script pai.
Recomenda-se que todos os novos scripts obtenham as variáveis de ambiente, como Path, via EnvGet.
EnvGet, OutputVar, Path ; Para explicações, veja #NoEnv.
Se um script não possui a diretiva #NoEnv, ler uma variável vazia vai, em vez disso, retornar o valor da variável de ambiente com aquele nome, se houver uma. Isso pode causar confusão, então recomenda-se que todos os novos scripts usem #NoEnv.
Apesar de que tipicamente imagina-se uma variável armazenando um único valor, e também cada variável seja de um tipo distinto (string, número e objeto), o AutoHotkey automaticamente converte entre números e strings em casos como minhaString + 1
e MsgBox %meuNumero%
. Já que essas conversões podem ocorrer muito frequentemente, toda vez que uma variável é convertida, o resultado é armazenado no cache da variável.
Como efeito, a variável pode obter tanto uma string quanto um número simultaneamente. Normalmente isso apenas melhora o desempenho do script sem reveses, mas se uma variável contiver tanto um número quanto uma string, então ela é um número, ou é uma string? Essa ambiguidade causa comportamentos inesperados em pelo menos dois casos:
O modo lento do SetFormat força a atribuição de um número puro para imediatamente converter aquele número em uma string. Para inteiros, o número também é armazenado, então isso não tem efeitos adversos para além da performance. Para pontos flutuantes, o número não é armazenado, já que o comando SetFormat afeta a precisão do valor, possivelmente truncando todas as casas decimais. Em outras palavras, o modo lento do SetFormat impede que pontos flutuantes puros sejam armazenados em variáveis.
Tomar o endereço de uma variável efetivamente converte o valor da variável em uma string, desabilitando o cache até que o endereço da variável mude (isso acontece quando sua capacidade muda). Isso é tanto para retrocompatibilidade e também porque o script poderia mudar o valor indiretamente por meio do endereço da variável a qualquer momento, tornando o cache impreciso.
Uma função ou comando é o meio primordial pelo qual um script faz algo.
Essencialmente, funções e comandos são a mesma coisa, então os conceitos aqui se aplicam a ambos. Entretanto, a longa história do AutoHotkey v1 e a ênfase em retrocompatibilidade têm resultado em uma divisão entre comandos, os quais requerem sintaxe legada, e funções, que requerem a sintaxe de expressão.
Comandos e funções podem ter propósitos diferentes. Algumas funções fazem não mais que realizar um simples cálculo, enquanto outras têm efeitos imediatamente visíveis, como mover uma janela. Uma das vantagens do AutoHotkey é a facilidade com que os scripts podem automatizar outros programas e realizar várias outras tarefas comuns simplesmente chamando algumas funções. Veja a lista de comandos e funções para exemplos.
Ao longo desta documentação, algumas palavras comuns são usadas de maneiras que podem não ser óbvias para alguém sem experiência prévia. Abaixo há várias palavras/expressões que são usadas frequentemente em relação a funções e comandos:
Chamar uma função ou comando faz com que o programa invoque, execute ou calcule-o(a). Em outras palavras, uma chamada de função transfere temporariamente o controle do script para a função. Quando a função completar seu propósito, ela retorna o controle ao script. Ou seja, qualquer código que vier depois da chamada de função não executará até que a função complete.
Contudo, algumas vezes a função ou comando completa antes que seus efeitos possam ser vistos pelo usuário. Por exemplo, o comando Send envia pressionamentos de teclas, mas podem retornar antes que as teclas pressionadas cheguem ao seu destino e gerem seu efeito pretendido.
Geralmente um comando ou função aceita parâmetros que podem dizer ao comando ou função como operar ou em que operar. Cada parâmetro é um valor, como uma string ou um número. Por exemplo, WinMove move uma janela, então seus parâmetros irão dizer qual janela mover e para onde movê-la. Parâmetros também podem ser chamados de argumentos. Abreviaturas comuns são param e arg.
Parâmetros são passados para uma função ou comando, o que significa que um valor é especificado para cada parâmetro da função ou comando quando ele(a) é chamado. Por exemplo, alguém pode passar o nome de uma tecla para GetKeyState() para determinar se aquela tecla está sendo mantida pressionada.
Funções retornam um valor, então o resultado da função é frequentemente chamado de valor de retorno. Por exemplo, StrLen() retorna o número de caracteres em uma string. Comandos não retornam um valor diretamente; em vez disso, eles armazenam o resultado em uma variável. Funções também podem fazer isso, como quando há mais de um resultado.
Funções e comandos normalmente aguardam que parâmetros sejam escritos em uma ordem específica, então o significado de cada parâmetro depende de sua posição na lista de parâmetros, que é separada por vírgulas. Alguns parâmetros podem ser omitidos, caso em que o parâmetro deve ser deixado em branco, mas a vírgula seguinte só pode ser omitida se todos os parâmetros que vierem depois também forem omitidos. Por exemplo, a sintaxe para ControlSend é:
ControlSend , Controle, Teclas, TituloDaJanela, TextoDaJanela, ExcluirTitulo, ExcluirTexto
A presença de colchetes nos parâmetros significa que eles são parâmetros opcionais (os colchetes em si não devem aparecer no código). No entanto, ControlSend não tem utilidade a não ser que Teclas sejam especificadas, e geralmente também é necessário especificar a janela alvo. Por exemplo:
ControlSend, Edit1, ^{Home}, A ; Correto. O controle foi especificado. ControlSend, ^{Home}, A ; Incorreto: os parâmetros não combinam. ControlSend,, ^{Home}, A ; Correto. O controle foi omitido.
Métodos são funções que operam em um objeto em particular. Embora só possa existir uma função denominada Send
(por exemplo), pode haver tantos métodos denominados Send
quanto for o número de objetos, já que cada objeto (ou classe de objetos) pode responder de uma maneira diferente. Por essa razão, o objeto alvo (que pode ser uma variável ou sub-expressão) é especificado à esquerda do nome do método em vez de dentro da lista de parâmetros. Para detalhes, vide Protocolo dos Objetos.
Fluxo de controle é a ordem na qual instruções individuais são executadas. Normalmente as instruções são executadas sequencialmente de cima para baixo, mas uma instrução de controle de fluxo pode ignorar essa ordem (tomar precedência), tal como quando se especifica que as instruções devem ser executadas repetidamente, ou somente se determinada condição for atingida.
Uma instrução é simplesmente o menor elemento da linguagem que expressa uma ação a ser executada. No AutoHotkey, instruções incluem comandos, atribuições de valor, chamadas de funções e outras expressões. Porém, diretivas, rótulos (incluindo hotkeys e hotstrings) e declarações sem atribuições de valor não são instruções; eles são processados assim que o programa inicia, antes de o script executar.
Fazer, executar, exercer, calcular, avaliar, pôr em efeito, etc. Executar tem basicamente o mesmo significado que tem fora do jargão da programação.
O corpo de uma instrução de fluxo de controle é a instrução ou grupo de instruções às quais aquele se aplica. Por exemplo, o corpo de uma instrução com if é executado somente se uma condição específica é atingida.
Considere, como exemplo, este pequeno conjunto de instruções:
Damos um passo de cada vez, e quando esse passo é concluído, passamos para o próximo. Da mesma forma, o controle em um programa ou script normalmente segue de uma instrução para a próxima. Mas e se quisermos digitar sobre uma janela já existente do Bloco de Notas? Considere este conjunto revisado de instruções:
Então ou abrimos o Bloco de Notas ou ativamos sua janela dependendo de ele já estar ou não em execução. #1 é uma instrução condicional, também conhecida como uma instrução com if; isto é, nós executamos seu corpo (#1.1 - #1.2) somente se uma condição específica é atingida. #2 é uma instrução com else; nós executamos seu corpo (#2.1) somente se a condição de uma instrução com if anterior não tiver sido atingida. Dependendo da condição, o controle flui de uma dessas duas maneiras: #1 (se verdadeiro) → #1.1 → #1.2 → #3; ou #1 (se falso) → #2 (senão) → #2.1 → #3.
As instruções acima podem ser traduzidas no código abaixo:
if (not WinExist("ahk_class Notepad")) { Run Notepad WinWait ahk_class Notepad } else WinActivate ahk_class Notepad Send Hello`, world{!}
Em nossas instruções escritas, nós usamos indentação e numeração para agrupar as instruções. Scripts funcionam de um jeito um pouco diferente. Conquanto a indentação deixa o código mais fácil de ler, no AutoHotkey ela não afeta o agrupamento de instruções. Em vez de indentação, as instruções são agrupadas envolvendo-se-as em chaves, como mostrado acima. Isso é chamado de bloco.
Para detalhes sobre a sintaxe - isto é, como escrever ou reconhecer instruções de fluxo de controle no AutoHotkey - veja Fluxo de Controle.
Cada caractere na string é representado por um número, chamado de número ordinal do caractere, ou código do caractere. Por exemplo, o valor “Abc” seria representado assim:
A | b | c | |
65 | 98 | 99 | 0 |
Codificação: a codificação de uma string define como os símbolos são mapeados para números ordinais, e números ordinais para bytes. Há várias diferentes codificações, mas todas as que são suportadas pelo AutoHotkey incluem a ASCII como um subconjunto; caracteres de códigos 0 a 127 sempre têm o mesmo significado. Por exemplo, “A” sempre terá o código de caractere 65.
Terminação nula: cada string é finalizada com um “caractere nulo”, ou, em outras palavras, um caractere com valor binário zero marca o fim da string. O comprimento de uma string não precisa ser armazenado uma vez que ele pode ser inferido pela posição do caractere finalizador. Com vistas no desempenho, o AutoHotkey às vezes armazena o comprimento, como na ocasião em que uma string é armazenada numa variável.
Observação: devido à dependência na terminação no caractere nulo, o AutoHotkey v1 em geral não suporta strings com caracteres nulos incorporados. Tais strings podem ser criadas com VarSetCapacity() e NumPut() ou DllCall(), mas podem gerar efeitos inconsistentes.
Codificação nativa: apesar de o AutoHotkey proporcionar meios de trabalhar com texto em várias codificações, os comandos e funções nativos — e até certo ponto a linguagem em si — assumem, todos eles, que os valores de strings estão em uma codificação em particular. Isso é chamado aqui de codificação nativa. A codificação nativa depende da versão do AutoHotkey.
As versões Unicode do AutoHotkey usam UTF-16. O menor elemento em uma string em UTF-16 possui dois bytes (16 bits). Caracteres Unicode no intervalo 0 a 65535 (U+FFFF) são representados por uma única unidade de código 16 bits do mesmo valor, enquanto os caracteres no intervalo 65536 (U+10000) a 1114111 (U+10FFFF) são representados por um par substituto; isto é, exatamente duas unidades de código 16-bits entre 0xD800 e 0xDFFF. (Para explicações mais detalhadas dos pares substitutos e seus métodos de codificação e decodificação, pesquise na Internet.)
Versões ANSI do AutoHotkey usam a página de código padrão ANSI, que depende da região do sistema ou a configuração “idioma para programas não Unicode” do sistema. O menor elemento de uma string ANSI é um byte. Entretanto, algumas páginas de código contêm caracteres que são representados por sequências de múltiplos bytes (estas são sempre caracteres não ASCII).
Caractere: geralmente, outras partes desta documentação usam o termo “caractere” para se referir à menor unidade de uma string; usa-se aqui também “bytes” para strings ANSI e “unidades de código 16 bits” para strings Unicode (UTF-16). Por razões de praticidade, o comprimento de uma string e posições no interior de uma string são medidas contando-se essas unidades de tamanho fixo, mesmo que elas possam não ser caracteres Unicode completos.
Os comandos FileRead, FileAppend, a função FileOpen() e o Objeto arquivo fornecem meios de ler e escrever texto com uma codificação específica em arquivos.
As funções StrGet e StrPut podem ser usadas para converter strings entre a codificação nativa e alguma outra codificação especificada. Entretanto, essas funções só são úteis em combinação com estruturas de dados e com a função DllCall. Strings que são passadas diretamente de ou para DllCall() podem ser convertidas para ANSI ou UTF-16 usando-se os tipos de parâmetros AStr
ou WStr
.
Técnicas para lidar com as diferenças entre as versões ANSI e Unicode do AutoHotkey podem ser encontradas na página Unicode x ANSI.
Um número puro ou binário é aquele que é armazenado na método em um formato com que o processador do computador pode trabalhar diretamente, como para realizar operações matemáticas. Na maioria dos casos, AutoHotkey converte automaticamente entre strings numéricas e números puros conforme necessário, e raramente diferencia entre os dois tipos. O AutoHotkey primariamente usa dois tipos de dados para números puros:
Em outras palavras, scripts são afetados pelas limitações seguintes:
Inteiros devem estar no intervalo 9223372036854775808 (-0x8000000000000000, ou -263) a 9223372036854775807 (0x7FFFFFFFFFFFFFFF, ou 263-1). Apesar de valores maiores poderem ser contidos numa string, qualquer tentativa de converter a string em um número (como pelo uso da string numa operação matemática) pode gerar resultados inconsistentes.
Números de ponto flutuante geralmente suportam 15 dígitos de precisão. Porém, converter um número de ponto flutuante em uma string faz com que o número seja arredondado de acordo com o formato de ponto flutuante atual, que, por padrão, tem 6 casas decimais. Se o modo “lento” do comando SetFormat está presente em qualquer lugar do script, números são sempre convertidos em strings quando atribuídos a uma variável.
Observação: há algumas frações decimais cujo formato de ponto flutuante não pode representar precisamente, então um número é arredondado para o número representável mais próximo. Isso pode levar a resultados inesperados. Por exemplo:
SetFormat FloatFast, 0.17 ; Mostrar precisão "além do máximo" 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)
Uma estratégia para lidar com isso é evitar a comparação direta, e fazer a comparação da diferença no lugar. Por exemplo:
MsgBox % Abs((0.1 + 0.2) - (0.3)) < 0.0000000000000001
Outra estratégia é sempre converter para string (logo, aplicando o arredondamento) antes da comparação. Há geralmente dois modos de fazer isso enquanto se especifica a precisão, e ambos são mostrados abaixo:
MsgBox % Round(0.1 + 0.2, 15) = Format("{:.15f}", 0.3)
AutoHotkey usa o mesmo conjunto de regras para denominar várias coisas, inclusive variáveis, funções, grupos de janelas, GUIs, classes e métodos:
CurrentDate
é o mesmo que currentdate
. Todavia, caracteres não ASCII maiúsculos, como “Ä”, não são consideradas iguais aos seus correspondentes minúsculos, independentemente da configuração de região do usuário. Isso ajuda o script a se comportar de maneira consistente entre múltiplas configurações regionais.Devido a convenções de estilo, é geralmente melhor nomear suas variáveis usando somente letras, números e o caractere _ (por exemplo:) PosicaoCursor, Total_itens e entrada_eh_valida). Esse estilo permite que pessoas familiarizadas com outras linguagens entendam seus scripts mais facilmente.
Embora uma variável possa consistir totalmente de algarismos, fazer isso geralmente só é usado para parâmetros de entrada da linha de comando. Esses nomes numéricos não podem ser usados em expressões porque eles seriam vistos como números e não como variáveis. É melhor evitar iniciar um nome de variável com um algarismo, já que esses nomes levam a confusões e serão considerados inválidos no AutoHotkey v2.
E, dado que os caracteres a seguir poderão estar reservados para outros fins na versão 2 do AutoHotkey, recomenda-se evitá-los: # @ $
Nomes de propriedades em classes têm as mesmas regras e restrições dos nomes de variáveis, exceto que os três caracteres listados acima (# @ $) não são permitidos. Apesar de poderem ser usados na definição de um método, chamar um método desse exigirá o uso de colchetes. Por exemplo, meuObjeto.@home()
não é válido, mas meuObjeto["@home"]()
é aceitável.
Variáveis têm certos atributos que turvam a linha que diferencia uma variável de seu valor, mas é importante fazer a distinção. Em particular, considere objetos e parâmetros ByRef.
Não obstante possamos dizer que a variável meuVetor
contém um vetor (o que é um tipo de objeto), o que a variável contém não é o vetor em si mas uma referência ou ponteiro para o vetor. Qualquer número de variáveis pode conter uma referência para o mesmo objeto. Pode ser útil pensar numa variável como simplesmente um nome, nesse caso. Exemplificativamente, dar a uma pessoa um apelido não faz com que surja um clone daquela pessoa.
Por padrão, variáveis são passadas para funções definidas pelo usuário por valor. Ou seja, o valor contido na variável é copiado para a variável que corresponde ao parâmetro da função. Parâmetros ByRef permitem que você passe uma variável por referência, ou, em outras palavras, tornar um parâmetro da função um codinome para sua variável, permitindo que a função atribua um novo valor para sua variável.
Como uma variável somente contém, a qualquer momento, uma referência para um objeto e não o objeto em si, quando você passar uma variável dessa para um parâmetro que não seja ByRef, o que a função recebe é uma referência ao mesmo objeto. Isso permite que a função modifique o objeto, mas não permite que a função modifique a variável que o chamador da função empregou, pois a função apenas tem uma referência ao objeto, não à variável.
Scripts interagem com um objeto só indiretamente, através de uma referência ao objeto. Quando você cria um objeto, o objeto é criado em certo local que você não controla, e a você é dada uma referência. Passar essa referência a uma função ou armazená-la numa variável ou outro objeto cria uma nova referência ao mesmo objeto. Você libera uma referência ao simplesmente usar uma atribuição para substituí-la por qualquer outro valor. Um objeto só é excluído depois que todas as referências a ele são liberadas; você não pode excluir um objeto explicitamente, e não deve tentar fazê-lo.
ref1 := Object() ; Criar um objeto e armazenar sua primeira referência ref2 := ref1 ; Criar uma nova referência para o mesmo objeto ref1 := "" ; Libera a primeira referência ref2 := "" ; Libera a segunda referência; o objeto é excluído
Se está difícil entender, tente pensar nos objetos como uma casa que você aluga. Quando você aluga uma unidade residencial, você recebe uma chave que você pode usar para acessá-la. Você pode obter mais chaves e usá-las para acessar a mesma casa, mas quando você tiver terminado seu período locatício, você deverá devolver todas as chaves ao responsável pela locação. Geralmente uma unidade residencial não seria deletada, mas talvez o representante da imobiliária providenciará a remoção de toda tralha que você tiver deixado para trás; da mesma forma que quaisquer valores armazenados num objeto são liberados quando o objeto é excluído.