变量和表达式

优质
小牛编辑
140浏览
2023-12-01

变量

变量的类型: AutoHotkey 中没有明确的变量类型. 然而, 只包含数字 (可以含有小数点) 的变量进行数学运算或比较时, 会被自动转换为数值. (为了提高性能, 在内部会对数字进行缓存以避免与字符串之间的转换.)

变量的作用域和声明: 除了函数中的 局部变量, 其他所有变量都是全局的; 即可以在脚本的任意位置读取或修改它们的内容. 除了在函数页面注明的情况,变量都是不需要声明的;使用它们的时候它们就产生了(每个变量初始为空)。

变量的名称: 变量名不区分大小写 (例如, CurrentDate 等同于 currentdate). 变量名可以含有多达 253 个字符, 并且可以由字母, 数字以及后面的标点组成: # _ @ $

考虑到命名的惯例, 通常在命名变量时最好仅使用字母, 数字和下划线 (例如: CursorPosition, Total_Itemsentry_is_valid). 这样的风格可以让熟悉其他计算机语言的人更容易理解您的脚本. 而且, 如果您在 AutoHotkey 和其他语言中使用相同的风格, 您会发现能更容易重新读懂自己的脚本.

尽管变量名可以完全由数字组成, 但通常这样的名称仅用于 传入的命令行参数. 这样数值名称的变量不能用在 表达式 中, 因为它们会被看成是数字而不是变量.

因为单词 AND, ORNOT 作为表达式的 运算符 使用, 所以通常不应该把它们用作变量名称. 在表达式中使用这样的名称会无法正确计算.

给变量赋值: 要把字符串或数字保存到变量中, 有两种方法: 传统方法和表达式方法. 传统方法使用 等号运算符 (=) 来指定 没有加引号的 原义字符串或包围在百分号中的变量. 例如:

MyNumber = 123
MyString = This is a literal string.
CopyOfVar = %Var%  ; 和 = 运算符一起使用时, 需要使用百分号来获取变量的内容.

与之相比, 表达式方法使用 冒号等号运算符 (:=) 来保存数字, 加引号的 字符串和其他类型的 表达式. 下面的例子在功能上与前面的例子相同:

MyNumber := 123
MyString := "This is a literal string."
CopyOfVar := Var  ; 和前面段落中与其作用相同的语句不同, 百分号不和 := 运算符一起使用.

后一种方法由于其更清晰并且与其他许多语言几乎一致的 表达式语法 成为大多数人的首选方法.

从上面的例子中您可能已经想到了有两种方法来清除变量的内容 (即让变量为空):

MyVar =
MyVar := ""

上面的这对空引号只能和 := 运算符一起使用, 因为和 = 运算符一起使用时, 则会在变量中保存两个原义的引号字符.

获取变量的内容: 如同赋值有两种方法, 获取变量的内容也有两种方法: 传统方法和表达式方法. 传统方法需要将变量名包围在百分号中来获取变量的内容. 例如:

MsgBox The value in the variable named Var is %Var%.
CopyOfVar = %Var%

与之相比, 表达式方法省去了变量名两边的百分号, 但原义的字符串必须包围在双引号中. 所以, 下面的表达式作用等同于上面的例子:

MsgBox % "The value in the variable named Var is " . Var . "."  ; 使用句点连接两个字符串.
CopyOfVar := Var

在上面的 MsgBox 这行, 通过使用百分号和空格把参数从传统模式改变为表达式模式. 因为所有的命令默认情况下使用传统模式 (除了另外注明的那些), 所以这是必须的. 不过, 某些命令的特定参数已注明接受表达式, 此时前导的百分号可以省略. 例如, 下面的所有语句都是等效的, 因为 Sleep 的首个参数可以是表达式:

Sleep MillisecondsToWait
Sleep %MillisecondsToWait%
Sleep % MillisecondsToWait

变量的比较: 请阅读下面表达式部分中关于不同类型变量比较的重要提示, 尤其是关于何时使用小括号的内容.

表达式

表达式用来对一系列变量, 原义字符串和/或原义数字执行一个或多个操作.

表达式中的变量名称不用包围在百分号中(伪数组和其他的双重引用除外)。所以, 为了与变量区别, 原义的字符串必须用双引号包围. 例如:

if (CurrentSetting > 100 or FoundColor <> "Blue")
    MsgBox The setting is too high or the wrong color is present.

在上面的例子中, 因为 "Blue" 是原义字符串, 所以包围在双引号中. 要在原义字符串中包含真实的引号字符,请指定两个连续的引号,如同此例中的两次演示:"She said, ""An apple a day."""

重要说明:含有表达式的 if 语句与传统的 if 语句(例如 If FoundColor <> Blue),可以通过单词“if”后是否有开括号来区分。尽管通常把整个表达式包围在括号中,不过也可以写成这样:if (x > 0) and (y > 0)。此外, 如果单词 "if" 后的第一项为 函数调用 或类似 "not" 或 "!" 这样的运算符时, 开括号可以完全省略.

空字符串: 要在表达式中使用空字符串, 请指定一对空引号. 例如,当 MyVar 非空时语句 if (MyVar <> "") 的结果为真。然而, 在 传统 if 语句 中, 一对空引号会被视为原义的字符串. 例如,当 MyVar 仅包含一对真实的引号时语句 if MyVar = "" 结果为真。因此,要使用传统的 if 语句判断变量是否为空,则需要让 = 或 <> 的右侧为空,例如:if Var =

相关提示,任何无效的表达式例如 (x +* 3) 会产生空字符串。

保存表达式的结果: 要把结果赋值给变量, 请使用 := 运算符. 例如:

NetPrice := Price * (1 - Discount/100)

布尔值: 要计算表达式结果为真还是假时 (例如 IF 语句), 表达式结果为空或零被视为假, 而其他所有结果都视为真. 例如,仅当 ItemCount 为空或 0 时 if ItemCount 的结果才为假。类似地,表达式 if not ItemCount 将产生相反的结果。

像 NOT/AND/OR/>/=/< 这些运算符的运算会自动产生真值或假值的结果: 真值时结果为 1 而假值时为 0. 例如, 在下面的表达式中, 如果有一个条件为真则变量 Done 被赋值为 1:

Done := A_Index > 5 or FoundIt

如上面提示的那样, 简单地置空变量或为其赋值为 0 可以让它假值. 利用这种特性,可以使用简写语句 if Done 来检查变量 Done 是真还是假。

单词 truefalse 是值分别为 1 和 0 的内置变量. 使用它们可以增加脚本的可读性, 例如:

CaseSensitive := false
ContinueSearch := true

整数和浮点数: 在表达式中, 含有小数点的数字被视为浮点数; 否则视为整数. 对于大多数运算符(例如加法和乘法),只要其中的一个输入是浮点数,那么结果也将是浮点数。

不论在表达式中还是在表达式外的其他地方, 整数都可以表示成十六进制或十进制. 十六进制数必须以前缀 0x 开头. 例如,Sleep 0xFF 等同于 Sleep 255。在 v1.0.46.11+,可以识别用科学计数法表示的浮点数;但只有在它们含有小数点时才行(例如 1.0e4-2.1E-4)。

强制使用表达式: 通过在表达式前加上百分号和空格或 tab, 能把表达式用在不直接支持表达式的参数中 (除了像 StringLen 的 OutputVar 和 InputVar 的那些参数). 这种技巧常用来访问 数组. 例如:

FileAppend, % MyArray%i%, My File.txt
MsgBox % "The variable MyVar contains " . MyVar . "."
Loop % Iterations + 1
WinSet, Transparent, % X + 100
Control, Choose, % CurrentSelection - 1

表达式中的运算符

优先级相同的运算符例如乘 (*) 和除 (/) 按从左到右的顺序计算, 下面另行注明的除外. 与之相比, 低优先级的运算符例如加 (+) 在更高优先级的运算符例如 (*) 之后 计算. 例如, 3 + 2 * 2 等价于 3 + (2 * 2). 使用括号可以改变优先级, 例如: (3 + 2) * 2

除了下面注明的情况, 其他时候在数学运算中包含的任何空值 (空字符串) 都 不会 被假定为零. 作为替代, 它会被视为错误, 这将导致那部分表达式的计算结果为空字符串. 例如, 如果变量 X 为空, 那么表达式 X+1 会产生空值而不是 1.

表达式运算符 (按优先级降序排列)

%Var%

如果表达式中的变量包围在百分号中 (例如 %Var%), 不管此变量 包含 什么内容都会被假定为另一个变量 (如果不存在这样的变量, 那么 %Var% 会被解析为空字符串) 的名称或部分名称. 这种方法常用来引用 伪数组 元素, 例如:

Var := MyArray%A_Index% + 100

为了向后兼容, 注明了 "可以使用表达式" 的命令参数把百分号中的孤立名称 (例如 %Var%, 但不是 Array%i%) 当作其两边的百分号不存在一样. 通过把引号包围在括号中可以避免这种情况;例如 Sleep (%Var%)

[AHK_L 52+]: 除了普通变量, %Var% 还可以解析为 环境变量, 剪贴板或任何的 保留/只读的变量. 在修订号 52 之前, 在这些情况中 %Var% 会被当成空字符串.

x.y[AHK_L 31+]: 对象访问. 从对象 x 中取值或为其存入值或调用其方法, 此处 y 是个原义值. 请参阅 对象语法.
new[v1.1.00+]:基于其他对象创建新对象。例如,x := new y 通常等价于 x := {base: y}new 后应该跟着变量或 GlobalClass.NestedClass 形式的简单类名,还可以像 x := new y(z) 那样加上可选参数(其中 y 是变量而非函数名)。更多细节请参阅自定义对象
++
--
前置和后置的自增/自减. 从变量中增加或减去 1 (但在 1.0.46 之前的版本中, 只有把它们放在一行中才能用; 此行中不能使用其他运算符). 运算符可以放在变量名的前面或后面. 如果放在变量名的 前面, 会立即执行运算并把结果用于后面的运算. 例如,Var := ++X 让 X 自增后才把它的值赋给 Var。相反地, 如果运算符放在变量名的 后面, 在后面的运算使用了变量 之后 才对其进行自增运算. 例如,Var := X++ 把 X 的当前值赋给 Var 后才进行自增。由于向后兼容性,仅当空变量在单独一行时运算符 ++ 和 -- 才把它们视为零;例如 y:=1, ++xMsgBox % ++x 当 x 为空时结果都为空。
**. 底数和指数都可以为小数. 如果指数为负数, 即使底数和指数都为整数, 结果也会被格式化为浮点数. 因为 ** 的优先级高于一元负号,所以 -2**2 的计算过程和 -(2**2) 一样且得到结果 -4。因此,要让负号的优先级高于幂运算,需要把它们包围在括号中,例如 (-2)**2。注意:不支持底数为负数且指数为分数的情况,例如 (-2)**0.5;它会产生空字符串。但 (-2)**2(-2)**2.0 都是支持的。
-
!
~
& *

一元负号(-):尽管它和减运算符使用相同的符号,但一元负号仅应用于单项或子表达式,如此例中的两次演示:-(3 / -x)。相关提示, 表达式中的任何一元正号 (+) 都会被忽略.

逻辑非(!): 如果运算数为空或 0, 那么逻辑非的结果为 1, 这表示 "真". 否则, 结果为 0 (假). 例如:!x or !(y and z)。注意: 单词 NOT 和 ! 含义相同, 但 ! 优先级更高. 在 v1.0.46+,允许使用连续的一元运算符,例如 !!Var,因为它们是按从右到左的顺序计算。

按位非 (~): 此运算符对运算数按位取反. 如果运算数为浮点数, 则在计算前把它截取成整数. 如果运算数介于 0 和 4294967295 (0xffffffff) 之间, 那么它会被视为 无符号的 32 位值. 否则, 它被视为 有符号的 64 位值. 例如,~0xf0f 计算结果为 0xfffff0f0(4294963440)。

取址(&)&MyVar 获取 MyVar 的内容的内存地址,此地址一般和 DllCall 结构一起使用。同时 &MyVar 也禁用了此变量中的二进制数的缓存,如果它经常用于数学或数值比较,那么这会拖慢其性能。每当变量的地址改变时会重新启用它的缓存 (例如使用 VarSetCapacity()).

解除引用(*)*Expression 假定 Expression 解析为数值的内存地址;它会获取在一个介于 0 和 255 之间的数字表示的内存地址中一个字节的内容(地址为 0 时获取的结果也总是 0;但应该避免使用其他任何无效地址,因为它可能会让脚本崩溃)。然而, 使用 NumGet() 获取二进制数通常会更好.

*
/
//

乘 (*): 如果两个输入都为整数, 则结果为整数; 否则结果为浮点数.

真除 (/): 与 EnvDiv 不同, 即使两个输入都是整数, 真除的结果也为浮点数. 例如,3/2 结果为 1.5 而不是 1,而 4/2 结果为 2.0 而不是 2。

向下舍除 (//): 如果两个输入都是整数, 那么双斜线运算符使用高效的整数除法. 例如,5//3 结果为 1 而 5//-3 结果为 -1。如果任何一个输入为浮点数, 则执行浮点除法并把结果往下取整到最近的整数. 例如,5//3.0 结果为 1.0 而 5.0//-3 结果为 -2.0。尽管浮点除法的结果为整数, 但它被保存为浮点格式, 以便其他使用者能使用浮点格式. 关于求模运算,请参阅 mod()

*=/= 运算符是用变量的值乘以或除以另一个值的一种简写形式. 例如,Var*=2Var:=Var*2 会得到相同的结果(不过前者执行的更好)。

除数为零时结果为空 (空字符串).

+
-

加 (+)减 (-). 相关提示, +=-= 运算符是从变量中增加或减少值的一种简写形式. 例如,Var+=2Var:=Var+2 会得到相同的结果(不过前者执行的更好)。同样地,使用 Var++、Var--、++Var 或 --Var 可以让变量增加或减小 1。

<<
>>
按位左移 (<<)右移 (>>). 用法示例:Value1 << Value2。任何浮点数在计算前会被截取成整数. 左移 (<<) 相当于把 Value1 乘以 "2 的 Value2 次幂". 右移(>>)相当于把 Value1 除以“2 的 Value2 次幂”并把结果往下取整到最近的整数;例如,-3>>1 结果为 -2。
&
^
|
按位与 (&), 按位异或 (^)按位或 (|). 这三个运算符中, & 优先级最高而 | 优先级最低. 任何浮点数在计算前会被截取成整数.
.

连接. 句点运算符用于把两个项目组合成单个字符串 (在句点的两边至少必须有一个空格). 省略句点也可以达到相同的目的(除非表达式中有不明确的关系,例如 x -y,或在右边的项目含有前导的 ++ 或 -- 运算符)。省略句点时, 合并的两个项目间应该至少有一个空格.
示例(表达式方法):Var := "The color is " . FoundColor
示例(传统方法):Var = The color is %FoundColor%

还可以用来连接子表达式. 例如:Var := "The net price is " . Price * (1 - Discount/100)

以句点 (或其他任何运算符) 开始的行会自动 附加到 前一行的末尾.

~=[AHK_L 31+]: RegExMatch 的简写形式. 例如,"abc123" ~= "\d" 会设置 ErrorLevel 为 0 并得到结果 4(首个数字的位置)。在 v1.1.03 之前, 此运算符和 等号 (=) 运算符优先级相同, 却完全没有说明.
>   <
>= <=
大于(>)小于(<)大于或等于(>=)小于或等于(<=)。如果某个输入不是数字, 则按字母顺序比较 (加了引号的原义字符串例如 "55" 在这种情况中总是被当成是非数值的). 仅当 StringCaseSense 打开时, 比较才区分大小写. 另请参阅: Sort
=
==
<> !=
等号(=)区分大小写等于(==)不等于(<> 或 !=)。运算符 !=<> 功能完全相同。当两个输入都是数字时,运算符 === 是一样的,当某个输入不是数字时,== 总是区分大小写,而 = 总是不区分大小写(不区分大小写的方法由 StringCaseSense 决定)。与之相比,<>!= 都遵循 StringCaseSense。注意: 加了引号的字符串例如 "55" 在这种情况下总是被当成非数值的.
NOT逻辑非. 除了优先级较低外, 其他的与 ! 运算符相同. 例如,not (x = 3 or y = 3) 等同于 !(x = 3 or y = 3)
AND
&&
这两个运算符都是 逻辑与. 例如:x > 3 and x < 10。要提高性能, 则要应用 求值优化. 此外, 以 AND/OR/&&/|| (或其他任何运算符) 开始的行会自动 附加到 前一行的末尾.
OR
||
这两个运算符都是 逻辑或. 例如:x <= 3 or x >= 10。要提高性能, 则要应用 求值优化.
?:三元运算符 [v1.0.46+]. 此运算符是 if-else 语句 的简写形式. 它计算左侧的条件来决定两个分支中哪个作为最终结果. 例如,var := x>y ? 2 : 3,当 x 大于 y 时保存 2 到 Var;否则保存 3。为了提高性能,只计算决定性的分支(请参阅求值优化)。
:=
+=
-=
*=
/=
//=
.=
|=
&=
^=
>>=
<<=

赋值. 对变量的内容进行运算, 然后把结果保存到同一个变量中 (但在 1.0.46 之前的版本中, 这些运算符只能在一行中最左边使用, 且仅支持前五个运算符). 最简单的赋值运算符为 冒号等号 (:=), 它把表达式的结果保存到变量中. 关于其他运算符的功能说明, 请参阅这个表格中它们的相关条目. 例如,Var //= 2 执行向下舍除,把 Var 除以 2,然后把结果保存回 Var。同样地,Var .= "abc"Var := Var . "abc" 的一种简写形式。

与其他大多数运算符不同, 赋值运算是从右往左执行的. 因此,Var1 := Var2 := 0 这个语句中首先把 0 赋值给 Var2,然后把 Var2 赋值给 Var1

如果使用赋值运算的结果作为其他某些运算符的输出, 那么输入的值是变量自身. 例如,如果变量 Var 新增值后大于 50,那么表达式 (Var+=2) > 50 结果为真。这样还允许赋值被作为 ByRef 传递或获取它的地址,例如:&(x:="abc")

需要避免语法错误或提供更直观的操作时, 会自动提升赋值运算符的优先级. 例如:not x:=y 等价于 not (x:=y)。同样地,++Var := X 等价于 ++(Var := X);而 Z>0 ? X:=2 : Y:=2 等价于 Z>0 ? (X:=2) : (Y:=2)

由向后兼容引起的已知限制(可能会在未来的版本中解决):1) 当 /= 为表达式中最左边的运算符并且它不是多语句表达式的一部分时,而且输入都不是浮点数时,它会执行向下舍除(在其他所有情况中,/= 会执行真除);2) 仅当 +=-= 为一行中最左边的运算符时,它们才支持日期/时间的计算;3) 运算符 +=, -= 和 *= 仅在空变量在单独一行时才把它们视为零;例如,y:=1, x+=1MsgBox % x-=3 当 x 为空时都得到空的结果。

,

逗号 (多语句) [v1.0.46+]. 逗号可以用来在单行中书写多个子表达式. 最常用于把多个赋值或函数调用聚集在一起. 例如:x:=1, y+=2, ++index, func()。这样的语句按从左到右的顺序执行. 注意: 以逗号 (或其他任何运算符) 开始的行会自动 附加到 前一行的末尾. 另请参阅: 逗号的性能.

在 v1.0.46.01+, 当逗号后紧跟着变量和等号时, 则这个等号会被自动当成赋值 赋值 (:=). 例如,后面所有的都是赋值:x:=1, y=2, a=b=c

mod()
round()
abs()

这些和其他内置数学函数在 这里 阐述.
func.()

[AHK_L 48+]: 试图调用对象 func 的命名的空方法. 按照约定, 这是对象的 "默认" 方法. 如果 func 不是对象, 则调用 默认基对象.

[v1.0.95+]: 如果 func 为函数名, 则调用这个命名的函数.

F(p*)[AHK_L 60+]: 请参阅 可变参数函数.
x[y][AHK_L 31+]: 对象访问. 从对象 x 中取值或为其存入值或调用其方法, 这里的 y 是参数列表或计算方法名. 请参阅 数组语法对象语法.

性能:在 v1.0.48+,使用逗号运算符常常比分开写单独的表达式速度更快,尤其是把一个变量的值赋给另一个变量时(例如 x:=y, a:=b)。当越多的表达式联合成单个表达式时, 性能会持续得到提升; 例如, 把五个或十个简单的表达式联合成单个表达式速度可能提升 35%.

内置变量

下列变量内置于程序中, 可以在任何脚本中引用. 除了 Clipboard, ErrorLevel 和 命令行参数, 其他变量都是只读的; 即它们的内容无法在脚本中直接修改.

目录

  • 特殊字符: A_Space, A_Tab
  • 脚本属性: 命令行参数, A_WorkingDir, A_ScriptDir, A_ScriptName, (...更多...)
  • 日期和时间: A_YYYY, A_MM, A_DD, A_Hour, A_Min, A_Sec, (...更多...)
  • 脚本设置: A_IsSuspended, A_BatchLines, A_TitleMatchMode, (...更多...)
  • 用户空闲时间: A_TimeIdle, A_TimeIdlePhysical
  • GUI 窗口和菜单栏: A_Gui, A_GuiControl, A_GuiEvent, A_EventInfo
  • 热键, 热字串和自定义菜单项: A_ThisHotkey, A_EndChar, A_ThisMenuItem, (...更多...)
  • 操作系统和用户信息: A_OSVersion, A_ScreenWidth, A_ScreenHeight, (...更多...)
  • 杂项: A_Cursor, A_CaretX, A_CaretY, Clipboard, ClipboardAll, ErrorLevel
  • 循环: A_Index, (...更多...)

特殊字符

A_Space此变量包含单个空格字符. 请参阅 AutoTrim 了解详情.
A_Tab此变量包含单个 tab 字符. 请参阅 AutoTrim 了解详情.

脚本属性

1, 2, 3 等每当启动带命令行参数的脚本时, 会自动创建这些变量. 可以像普通变量一样修改和引用它们 (例如: %1%). 变量 %0% 包含了命令行参数的数目 (如果没有则为 0). 需了解详情请参阅 命令行参数.
A_WorkingDir脚本当前工作目录, 这是脚本访问文件的默认路径. 除非是根目录, 否则路径末尾不包含反斜线. 两个示例: C:\ 和 C:\My Documents. 使用 SetWorkingDir 可以改变当前工作目录.
A_ScriptDir当前脚本所在目录的绝对路径. 不包含最后的反斜线(根目录同样如此)。
A_ScriptName当前脚本的文件名称, 不含路径, 例如 MyScript.ahk.
A_ScriptFullPath上面两个变量的组合, 包含了当前脚本的完整路径和名称, 例如 C:\My Documents\My Script.ahk
A_ScriptHwnd
[v1.1.01+]
脚本隐藏主窗口的唯一 ID (HWND/句柄).
A_LineNumber

当前脚本中正在执行的行所在的行号 (或其 "ListLines.htm">ListLines 显示的一致;它可以用在报告错误的时候,例如:MsgBox Could not write to log file (line number %A_LineNumber%)

由于 已编译脚本 已经把它所有的 #Include 文件 合并成一个大脚本, 所以它的行号可能与它在未编译模式运行时不一样.

A_LineFileA_LineNumber 所属文件的完整路径和名称, 除非当前行属于未编译脚本的某个 "">A_ScriptFullPath 相同.
A_ThisFunc
[v1.0.46.16+]
当前正在执行的 自定义函数 的名称 (没有则为空); 例如: MyFunction. 另请参阅: IsFunc()
A_ThisLabel
[v1.0.46.16+]
当前正在执行的 标签 (子程序) 的名称 (没有则为空); 例如: MyLabel. 每当脚本执行 Gosub/ReturnGoto 时会更新此变量的值. 执行自动调用的标签时也会更新此变量的值,例如计时器GUI 线程菜单项热键热字串OnClipboardChangeOnExit。不过,当执行从前面的语句“进入”一个标签时不会更新 A_ThisLabel 的值,即此时它还是保持原来的值。另请参阅: A_ThisHotkey 和 IsLabel()
A_AhkVersion在 1.0.22 之前的版本, 此变量为空. 否则, 它包含了运行当前脚本的 AutoHotkey 主程序的版本号, 例如 1.0.22. 在 已编译脚本 中, 它包含了原来编译时使用的主程序的版本号. 格式化的版本号使得脚本可以使用 > 或 >= 来检查 A_AhkVersion 是否大于某个最小的版本号,例如:if A_AhkVersion >= 1.0.25.07
A_AhkPath

对于未编译脚本: 实际运行当前脚本的 EXE 文件的完整路径和名称. 例如: C:\Program Files\AutoHotkey\AutoHotkey.exe

对于 已编译脚本: 除了通过注册表条目 HKEY_LOCAL_MACHINE\SOFTWARE\AutoHotkey\InstallDir 获取 AutoHotkey 目录外, 其他的和上面相同. 如果找不到这个注册表条目, 则 A_AhkPath 为空.

A_IsUnicode当字符串为 Unicode (16 位) 时值为 1, 字符串为 ANSI (8 位) 时为空字符串 (这会被视为 false). 字符串的格式取决于用来运行当前脚本的 AutoHotkey.exe, 如果为已编译脚本, 则取决于用来编译它的主程序.
A_IsCompiled如果当前运行的脚本为 已编译 EXE 时此变量值为 1, 否则为空字符串 (这会被视为 false).
A_ExitReason最近一次要求脚本终止的原因. 除非脚本含有 OnExit 子程序并且此子程序当前正在运行或被退出尝试至少调用过一次, 否则此变量为空. 请参阅 OnExit 了解详情.

日期和时间

A_YYYY4 位数表示的当前年份 (例如 2004). 与 A_Year 含义相同. 注意:要获取符合您区域设置和语言的格式化时间或日期,请使用 FormatTime, OutputVar(时间和长日期)或 FormatTime, OutputVar,, LongDate(获取长格式日期)。
A_MM2 位数表示的当前月份 (01-12). 与 A_Mon 含义相同.
A_DD2 位数表示的当前月份的日期 (01-31). 与 A_MDay 含义相同.
A_MMMM使用当前用户语言表示的当前月份的全称, 例如 July
A_MMM使用当前用户语言表示的当前月份的简称, 例如 Jul
A_DDDD使用当前用户语言表示的当前星期几的全称, 例如 Sunday
A_DDD使用当前用户语言表示的当前星期几的 3 个字母的简称, 例如 Sun
A_WDay1 位数表示的当前星期经过的天数 (1-7). 在所有区域设置中 1 都表示星期天.
A_YDay当前年份中经过的天数 (1-366). 不会使用零对变量的值进行填充, 例如会获取到 9, 而不是 009. 要对变量的值进行零填充,请使用:FormatTime, OutputVar, , YDay0
A_YWeek符合 ISO 8601 标准的当前的年份和周数 (例如 200453). 要分离年份和周数,请使用 StringLeft, Year, A_YWeek, 4StringRight, Week, A_YWeek, 2。A_YWeek 的准确定义为: 如果含有 1 月 1 日的星期有四天以上在新年里, 则它被认为是新年的第一个星期. 否则, 它为前一年的最后一个星期, 而下一星期为新年的第一星期.
A_Hour在 24 小时制 (例如, 17 表示 5pm) 中 2 位数表示的当前小时数 (00-23). 要获取带 AM/PM 提示的 12 小时制的时间,请参照此例:FormatTime, OutputVar, , h:mm:ss tt
A_Min

2 位数表示的当前分钟数 (00-59).

A_Sec2 位数表示的当前秒数 (00-59).
A_MSec3 位数表示的当前毫秒数 (000-999). 要移除前导零,请参照此例:Milliseconds := A_MSec + 0
A_NowYYYYMMDDHH24MISS 格式的当前本地时间. 注意: 使用 EnvAddEnvSub 可以对日期和时间进行计算. 此外, 使用 FormatTime 可以根据您的区域设置或选项来格式化日期和/或时间.
A_NowUTCYYYYMMDDHH24MISS 格式的当前的协调世界时 (UTC). UTC 本质上和格林威治标准时间 (GMT) 一致.
A_TickCount

计算机重启后经过的毫秒数. 通过把 A_TickCount 保存到变量中, 经过一段时间后从最近的 A_TickCount 值中减去那个变量, 可以计算出所经过的时间. 例如:

StartTime := A_TickCount
Sleep, 1000
ElapsedTime := A_TickCount - StartTime
MsgBox,  %ElapsedTime% milliseconds have elapsed.

如果您需要比 A_TickCount 的10ms 更高的精确度, 请使用 QueryPerformanceCounter().

脚本设置

A_IsSuspended当脚本 挂起时 值为 1, 否则为 0.
A_IsPaused
[v1.0.48+]
当紧随当前线程的 线程暂停 时值为 1. 否则为 0.
A_IsCritical
[v1.0.48+]
当前线程Critical 设置关闭时值为 0. 否则它包含大于零的整数, 即 Critical 使用的 消息检查频率. 因为 Critical 0 关闭了当前线程的关键性,所以 Critical 的当前状态可以这样来保存和恢复:Old_IsCritical := A_IsCritical,后来执行 Critical %Old_IsCritical%
A_BatchLines(同义于 A_NumBatchLines) 由 SetBatchLines 设置的当前值. 例如: 200 或 10ms (取决于格式).
A_TitleMatchModeSetTitleMatchMode 设置的当前模式: 1, 2, 3 或 RegEx.
A_TitleMatchModeSpeedSetTitleMatchMode 设置的当前匹配速度 (fast 或 slow).
A_DetectHiddenWindowsDetectHiddenWindows 设置的当前模式 (On 或 Off).
A_DetectHiddenTextDetectHiddenText 设置的当前模式 (On 或 Off).
A_AutoTrimAutoTrim 设置的当前模式 (On 或 Off).
A_StringCaseSenseStringCaseSense 设置的当前模式 (On, Off 或 Locale).
A_FileEncoding[AHK_L 46+] 包含了多个命令使用的默认编码; 请参阅 FileEncoding.
A_FormatIntegerSetFormat 设置的当前整数格式 (H 或 D). [AHK_L 42+]: 此变量还可能为小写字母 h.
A_FormatFloatSetFormat 设置的当前浮点数格式.
A_KeyDelaySetKeyDelay 设置的当前延迟 (总是十进制数, 不是十六进制). 此延迟适用于传统的 SendEvent 模式, 不适用于 SendPlay.
A_WinDelaySetWinDelay 设置的当前延迟 (总是十进制数, 不是十六进制).
A_ControlDelaySetControlDelay 设置的当前延迟 (总是十进制数, 不是十六进制).
A_MouseDelaySetMouseDelay 设置的当前延迟 (总是十进制数, 不是十六进制). 此延迟适用于传统的 SendEvent 模式, 不适用于 SendPlay.
A_DefaultMouseSpeedSetDefaultMouseSpeed 设置的当前速度 (总是十进制数, 不是十六进制).
A_RegView[v1.1.08+]:由 SetRegView 设置的当前注册表视图。
A_IconHidden托盘图标当前隐藏时值为 1, 否则为 0. 此图标可以使用 https://www.xnip.cn/shouce/1165/74667.html 命令进行隐藏.
A_IconTip如果使用 Menu, Tray, Tip 为托盘图标指定了自定义的工具提示时,变量的值为这个提示的文本,否则为空。
A_IconFile如果使用 Menu, tray, icon 指定了自定义的托盘图标时,变量的值为图标文件的完整路径和名称,否则为空。已知限制:如果脚本原来传递相对路径给系统的 DLL,那么此变量中的路径可能不正确;例如 Menu, Tray, Icon, user32.dll, 2
A_IconNumber当 A_IconFile 为空时此变量为空. 否则, 它的值为 A_IconFile 中的图标编号 (通常为 1).

用户空闲时间

A_TimeIdle从系统最后一次接收到键盘, 鼠标或其他输入后所经过的毫秒数. 这可以用来判断用户是否离开. 用户的物理输入和由 任何 程序或脚本生成的模拟输入 (例如 SendMouseMove 命令) 会让此变量重置为零. 由于此变量的值趋向于以 10 的增量增加, 所以不应该判断它是否等于另一个值. 相反, 应该检查此变量是否大于或小于另一个值. 例如:IfGreater, A_TimeIdle, 600000, MsgBox, The last keyboard or mouse activity was at least 10 minutes ago
A_TimeIdlePhysical

与上面类似, 但在安装了相应的钩子 (键盘鼠标) 后会忽略模拟的键击和/或鼠标点击; 即此变量仅反应物理事件. (这样避免了由于模拟键击和鼠标点击而误以为用户存在.) 如果两种钩子都没有安装, 则此变量等同于 A_TimeIdle. 如果仅安装了一种钩子, 那么仅此类型的物理输入才会对 A_TimeIdlePhysical 起作用 (另一种/未安装钩子的输入, 包括物理的和模拟的, 都会被忽略).

GUI 窗口和菜单栏

A_Gui启动了 当前线程GUI 的名称或编号. 除非当前线程是由 Gui 控件, 菜单项或 Gui 事件 (例如 GuiClose/GuiEscape) 启动的, 否则此变量为空.
A_GuiControl启动 当前线程 的 GUI 控件的关联变量名. 如果那个控件没有 关联变量, 则 A_GuiControl 包含此控件的文本/标题中前 63 个字符 (这常用来避免给每个按钮分配变量名). 出现后面这些情况时 A_GuiControl 为空: 1) A_Gui 为空; 2) GUI 菜单项或事件 (例如 GuiClose/GuiEscape) 启动了当前线程; 3) 那个控件没有关联变量, 也没有标题; 或 4) 最初启动当前线程的控件已经不存在 (可能由于 Gui Destroy 的原因).
A_GuiWidth
A_GuiHeight
GuiSize 子程序 中引用时, 它们分别包含了 GUI 窗口的宽度和高度. 它们对应于窗口的工作区, 这是窗口中不包括标题栏, 菜单栏和边框的区域. [v1.1.11+]:这些值会受 DPI 缩放的影响。
A_GuiX
A_GuiY
它们包含了 GuiContextMenuGuiDropFiles 事件中的 X 和 Y 坐标. 这里的坐标相对于窗口的左上角. [v1.1.11+]:这些值会受 DPI 缩放的影响。
A_GuiEvent
或 A_GuiControlEvent

启动当前线程的事件类型。如果当前线程不是由 GUI 动作 启动的,则此变量为空。否则, 它为下列字符串的其中一个:

Normal: 此事件是由左键单击和键击 (方向键, TAB 键, 空格键, 带下划线的快捷键等) 触发的. 此变量的值还可以用于菜单项和特殊的 Gui 事件, 例如 GuiClose 和 GuiEscape.

DoubleClick: 此事件是由双击触发的. 注意: 双击中的首次点击仍会引起 Normal 事件首先被接收到. 换句话说, 双击时子程序会运行两次: 一次在首次点击时, 再次是在第二次点击时.

RightClick: 仅出现在 GuiContextMenu, ListViewsTreeViews.

上下文相关值:要了解详情请参阅 GuiContextMenuGuiDropFilesSliderMonthCalListViewTreeView

A_EventInfo

包含下列事件的额外信息:

注意: 与类似 A_ThisHotkey 这样的变量不同, 每个 线程 会为 A_Gui, A_GuiControl, A_GuiX/Y, A_GuiEvent 和 A_EventInfo 保存它自己本身的值. 因此, 如果一个线程被另一个中断, 在这个线程恢复时它仍将看到这些变量的原来/正确的值.

热键, 热字串和自定义菜单项

A_ThisMenuItem最近选择的 自定义菜单项 的名称 (没有则为空).
A_ThisMenuA_ThisMenuItem 所在菜单的名称.
A_ThisMenuItemPos表示 A_ThisMenuItem 在 A_ThisMenu 当前 位置的编号. 菜单中首个项目为 1, 第二项为 2, 依此类推. 菜单分隔线也计算在内. 如果 A_ThisMenuItem 为空或已不存在于 A_ThisMenu 中, 则此变量为空. 如果 A_ThisMenu 已不存在, 则此变量也为空.
A_ThisHotkey

最近执行的 热键非自动替换热字串 的按键名称 (如果没有则为空), 例如 "https://www.xnip.cn/doc/AutoHotkey-Threads">当前线程 被其他热键中断, 那么此变量的值会变化, 所以如果之后需要在子程序中使用原来的值, 则必须马上把它复制到另一个变量中.

首次创建热键时 (通过 Hotkey 命令双冒号标签 ), 其键名以及修饰符的顺序成为此热键的固定名称. 另请参阅: A_ThisLabel

A_PriorHotkey除了保存前一次热键的名称外, 其他的与上面相同. 如果没有它会为空.
A_PriorKey[v1.1.01+]: 在最近按键按下或按键释放前最后按下的按键名称, 如果在按键历史中没有适用的按键按下则为空. 不包括由 AutoHotkey 脚本生成的所有输入. 要使用此变量, 首先必须安装 键盘鼠标钩子 同时启用 按键历史.
A_TimeSinceThisHotkey从 A_ThisHotkey 按下后到现在经过的毫秒数. 如果 A_ThisHotkey 为空, 则此变量的值为 -1.
A_TimeSincePriorHotkey从 A_PriorHotkey 按下后到现在经过的毫秒数. 如果 A_PriorHotkey 为空, 则此变量的值为 -1.
A_EndChar用户最近按下的触发了 非自动替换热字串终止符. 如果不需要终止符 (由于使用了 * 选项), 那么此变量将为空.

操作系统和用户信息

ComSpec
[v1.0.43.08+]
此变量的值与系统环境变量 ComSpec 一样 (例如 C:\Windows\system32\cmd.exe). 常与 Run/RunWait 一起使用. 注意: 此变量不带 A_ 前缀.
A_Temp
[v1.0.43.09+]
存放临时文件的文件夹的完整路径和名称 (例如 C:\DOCUME~1\UserName\LOCALS~1\Temp). 它的值从下列的其中一个位置获取 (按顺序): 1) 环境变量 TMP, TEMP 或 USERPROFILE; 2) Windows 目录.
A_OSType正在运行的操作系统类型。由于 AutoHotkey 1.1 仅支持基于 NT 的操作系统,所以此变量总是为 WIN32_NT。旧版本的 AutoHotkey 运行在 Windows 95/98/ME 时会返回 WIN32_WINDOWS。
A_OSVersion

下列字符串的其中一个:WIN_7 [需要 v1.1+ 或 AHK_L]、WIN_8 [需要 v1.1.08+]、WIN_8.1 [需要 v1.1.15+]、WIN_VISTA、WIN_2003、WIN_XP、WIN_2000。

; 这个示例已过时了,里面的这些操作系统都不再受支持。
if A_OSVersion in WIN_NT4,WIN_95,WIN_98,WIN_ME  ; 注:逗号两边没有空格。
{
    MsgBox This script requires Windows 2000/XP or later.
    ExitApp
}
A_Is64bitOS[v1.1.08+]:当操作系统为 64 位则值为 1(真),为 32 位则为 0(假)。
A_PtrSize[AHK_L 42+]: 包含指针的大小值, 单位为字节. 值为 4(32 位)或 8(64位),取决于运行当前脚本的执行程序的类型。
A_Language当前系统的默认语言, 值为 这些 4- 位数字编码 的其中一个.
A_ComputerName在网络上看到的计算机名称.
A_UserName运行当前脚本的用户的登录名.
A_WinDirWindows 目录. 例如: C:\Windows
A_ProgramFiles
或 ProgramFiles
Program Files 目录 (例如 C:\Program Files). 在 v1.0.43.08+, 前缀 A_ 可以省略, 这样有助于自然过渡到 #NoEnv.
A_AppData
[v1.0.43.09+]
当前用户的应用程序数据文件夹的完整路径和名称. 例如: C:\Documents and Settings\Username\Application Data
A_AppDataCommon
[v1.0.43.09+]
所有用户的应用程序数据文件夹的完整路径和名称.
A_Desktop当前用户的桌面文件夹的完整路径和名称.
A_DesktopCommon所有用户的桌面文件夹的完整路径和名称.
A_StartMenu当前用户的开始菜单文件夹的完整路径和名称.
A_StartMenuCommon所有用户的开始菜单文件夹的完整路径和名称.
A_Programs当前用户的开始菜单中程序文件夹的完整路径和名称.
A_ProgramsCommon所有用户的开始菜单中程序文件夹的完整路径和名称.
A_Startup当前用户的开始菜单中启动文件夹的完整路径和名称.
A_StartupCommon所有用户的开始菜单中启动文件夹的完整路径和名称.
A_MyDocuments当前用户 "我的文档" 文件夹的完整路径和名称. 与大多数类似变量不同, 当此文件夹为驱动器的根目录时, 此变量的值不包含最后的反斜线. 例如, 它的值我 M: 而不是 M:\
A_IsAdmin

如果当前用户有管理员权限, 则此变量的值为 1. 否则为 0.

在 Windows Vista 或更高版本中, 一些脚本可能需要管理员权限才能正常运行 (例如与使用管理员权限执行的进程和窗口进行交互的脚本). 要做到这点,请把下列语句添加到脚本的顶部:

if not A_IsAdmin
{
   Run *RunAs "%A_ScriptFullPath%"  ; 需要 v1.0.92.01+
   ExitApp
}

A_ScreenWidth
A_ScreenHeight

主监视器的宽度和高度, 单位为像素 (例如 1024 和 768).

要获取多显示器系统中其他显示器的尺寸, 请使用 SysGet.

要获取整个桌面(即使它横跨多个显示器)的宽度和高度,请使用下面的例子:

SysGet, VirtualWidth, 78
SysGet, VirtualHeight, 79

此外, 使用 SysGet 可以获取显示器的工作区域, 它比显示器的整个区域小, 因为它不包括任务栏和其他注册的桌面工具栏.

A_ScreenDPI [v1.1.11+]在屏幕宽度上每逻辑寸的像素数。在多显示器的系统中,这个值对于所有的显示器都是一样的。在大多数系统中该值为 96;它取决于系统文本大小(DPI)设置。另请参阅 Gui -DPIScale
A_IPAddress1 到 4计算机中前 4 个网卡的 IP 地址.

杂项

A_Cursor

当前显示的鼠标光标类型. 其值为下列单词的其中一个: AppStarting, Arrow, Cross, Help, IBeam, Icon, No, Size, SizeAll, SizeNESW, SizeNS, SizeNWSE, SizeWE, UpArrow, Wait, Unknown. 与 size 指针类型一起的首字母表示方向, 例如 NESW = NorthEast+SouthWest. 手型指针 (点击和抓取) 属于 Unknown 类别.

A_CaretX
A_CaretY

当前光标 (文本插入点) 的 X 和 Y 坐标. 如果没有使用 CoordMode 使得坐标相对于整个屏幕, 默认坐标相对于活动窗口. 如果没有活动窗口或无法确定文本插入点的位置, 则这两个变量为空.

下面这个脚本可以让您在四处移动文本插入点时, 查看显示在自动更新工具提示上的当前位置. 注意在某些窗口 (例如某些版本的 MS Word) 会不管文本插入点的实际位置如何都报告同样的位置.

#Persistent
SetTimer, WatchCaret, 100
return
WatchCaret:
  ToolTip, X%A_CaretX% Y%A_CaretY%, A_CaretX, A_CaretY - 20
return

如果以很高的频率 (即每 500 ms 或更快) 重复获取这些变量的内容, 那么可能会干扰用户双击鼠标. 没有已知的解决方法.

Clipboard操作系统剪贴板的内容, 可以从中读取或写入内容. 请参阅 剪贴板 章节.
ClipboardAll剪贴板中的完整内容 (包含格式和文本). 请参阅 ClipboardAll.
ErrorLevel请参阅 ErrorLevel.
A_LastError操作系统 GetLastError() 函数或最近 COM 对象调用返回的结果. 要了解详情, 请参阅 DllCall()Run/RunWait.

循环

A_Index当前循环重复的次数 (64 位整数). 例如, 当脚本首次执行此循环体时, 此变量的值为 1. 要了解详情请参阅 LoopWhile 循环.
A_LoopFileName 等此变量和其他相关变量仅在 文件循环 中有效.
A_LoopRegName 等此变量和其他相关变量仅在 注册表循环 中有效.
A_LoopReadLine请参阅 文件读取循环.
A_LoopField请参阅 解析循环.

环境变量与 "普通" 变量

环境变量由操作系统维护. 在命令提示符中输入 SET 并回车后, 您可以看到环境变量列表.

脚本中可以使用 EnvSet 创建新的环境变量或改变现有环境变量的内容. 但是, 这样的添加和改变都是私有的; 它们不会被系统的其他部分看到. 一个例外是当脚本使用 RunRunWait 运行程序时 (甚至是另一个脚本): 这样的程序会继承其父脚本的环境变量的副本, 包括私有的那些.

在 v1.0.43.08+, 推荐在所有新脚本中使用以下方式获取环境变量, 例如 Path:

EnvGet, OutputVar, Path  ; 想了解含义, 请参阅 #NoEnv.

变量的容量和占用内存

  • 每个变量最多可以含有64MB的文本(使用#MaxMem可以突破这个限制)。
  • 当赋值给变量比当前更长的内容时, 会自动分配额外的系统内存给这个变量.
  • 通过赋值为空可以释放大变量占用的内存,例如 Var := ""
  • 脚本可以创建的变量数量没有限制. 程序设计用来支持至少几百万的变量而不会出现明显的性能下降.
  • 接受数值输入的命令, 函数和表达式通常可以支持 15 位的浮点数精度. 对于整数, 可以支持 64 位有符号整数, 其范围从 -9223372036854775808 (-0x8000000000000000) 到 9223372036854775807 (0x7FFFFFFFFFFFFFFF). 此范围外的任何整数不受支持, 并可能产生错误的结果. 与之相比, 整数的算数运算结果超出此范围时会产生溢出 (例如 0x7FFFFFFFFFFFFFFF + 1 = -0x8000000000000000).