# 变量和表达式

## 目录

- 变量介绍
- 表达式
- 表达式中的运算符
- 内置变量
- 环境变量对普通变量
- 变量的容量和内存

## 变量介绍

变量类型：AutoHotkey 没有明确定义变量类型；所有的变量都是以字符串的形式存储。不过，当一个只包含数字(可以还有小数点)的变量进行数学运算或比较时，它将被自动地转换为数值(译注：整型数或浮点型数等)。反过来，当数学运算的结果需要存储在一个变量里时，它将被转换回字符串。

变量的范围和声明：除了函数中的局部变量，其他所有变量都是全局的；也就是说，它们的内容可以在脚本的任何位置被读取或改变。此外，变量是无需声明的；只要在使用它们的时候它们就产生了(每个变量初始为空/空白)。

变量名：变量名不区分大小写(例如，CurrentDate 等同于 currentdate)。变量名最长可以有 254 个字符并且可以由字母、数字和下列标点符号: # _ @ $ ? [ ] 组成。

由于格式上的惯例，一般来说最好仅使用字母、数字和下划线来命名你的变量(例如: CursorPosition、Total_Items 和 entry_is_valid)。这种命名风格使熟悉其他计算机语言的人能够更容易地理解你的脚本。而且，如果你在 AutoHotkey 中使用的命名风格与你在其他语言中使用的风格一致，你会发现能更容易地重读自己的脚本。

虽然一个变量名可以完全由数字组成，但是通常仅给传入的命令行参数使用。这种数字名称不能在表达式中使用，因为它们会被视为数字而不是变量。

因为单词 AND 、OR 、NOT 在表达式中被当作运算符使用，所以通常它们不应该作为变量名使用。在表达式中使用这样的名称将阻碍正确的计算。

给变量赋值：要在一个变量里储存字符串或数值，有两种方法：传统方法和表达式方法。传统方法使用等号运算符(=)来指定未引用的原义字符串或者围在百分号里的变量。例如:

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

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

    MyNumber := 123
    MyString := "This is a literal string."
    CopyOfVar := Var ;和上面的部分里与它相似的那个不同，百分号不和 := 运算符一起使用。

第二种方法由于其更清晰以及与其他语言几乎一致的表达式语法而被大多数人所喜爱。

从上面的例子来看，你可能已经猜到了有两种方法来清除一个变量的内容(就是说，使变量为空):

    MyVar =
    MyVar := ""

上面这对空双引号只能和 := 运算符一起使用，因为假如它与 = 运算符一起用，它将在变量里储存两个原义的引号字符。

获取变量的内容：类似于赋值的两种方法，获取变量的值也有两种方法：传统方法和表达式方法。传统方法要将每个变量名围在百分号里以取得它的内容。例如:

    CopyOfVar = %Var%
    MsgBox 变量 Var 的值为 %Var%。

相比之下，表达式方法不用在变量名两边加上百分号，但要将原义的字符串括入双引号。所以，下列表达式方法是与上面的例子相等的:

    CopyOfVar := Var
    MsgBox % "变量 Var 的值为" . Var . "。"

在上面 MsgBox 这行，一个百分号一个空格用来将参数由传统方法变为表达式方法(译注：后面的一个点两边一个空格表示连接，具体请看下面的表达式中的运算符那段)。因为所有命令默认使用传统方法(除了那些另外说明的)，所以这是必须的。不过，一些命令的特定参数已说明过接受表达式，在这种情况下，带头的百分号允许使用但不是必须的。例如，下面所有命令实际上是一样的，因为 Sleep 的首个参数可以是表达式:

    Sleep MillisecondsToWait
    Sleep %MillisecondsToWait%
    Sleep % MillisecondsToWait

比较变量：请读下面的表达式这节中关于各种比较的注意事项，特别是关于何时使用圆括号的部分。

## 表达式

表达式被用来在一系列变量、原义的字符串和/或原义的数字上执行一个或者多个操作。

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

    if (CurrentSetting > 100 or FoundColor <> "Blue")
     MsgBox 设置太高或者呈现了错误的颜色。

在上面的例子里，"Blue"出现在双引号内，因为它是一个原义的字符串。要在一个原义的字符串内包含一个真的引号字符，请指定两个连续的引号，如在这个例子中出现了两回: "She said, ""An apple a day."""

重要的：一个包含有表达式的 if-语句与传统的 if-语句例如 If FoundColor <> Blue 可以通过 "if" 后面是否有左括号来区分。虽然一般将整个表达式放在括号里，但也可以像这样写 if (x > 0) and (y > 0) 。此外，如果 "if" 后面的第一项是一个函数调用或者一个像 "not" 或 "!" 这样的运算符，括号也可以完全地省略。

空字符串：要在表达式中指定一个空字符串，可以使用一对空引号。例如，语句 if (MyVar <> "") 中如果 MyVar 不为空，那么将返回 true 。不过，在传统的-if 中，一对空引号将被当作原义的字符串。例如，语句 if MyVar = "" 只在 MyVar 包含一对真的引号时才为 true 。因此，要检查在一个传统的-if 语句中变量是否为空，可以像这个例子一样让 = 或 <> 右侧为空: if Var =

作个相关提示，任何无效的表达式例如 (x +* 3) 都将产生一个空字符串。

存储表达式的结果：要指定一个表达式的结果给变量，可以使用 := 运算符。例如:

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

因为上面的例子产生了一个浮点型数(由于有除法)，那么存在变量 NetPrice 中的小数位数就由 SetFormat 决定。SetFormat 还可以改变表达式的结果的其他特性。相比之下，AutoTrim 不会对表达式的结果产生影响。

布尔值：当一个表达式需要计算出是 true 还是 false 时(例如一个 IF-语句)，表达式结果为空或为零将视为 false，而其他所有结果视为 true。例如，语句 "if ItemCount" 只在 ItemCount 为空或为零时才是 false。类似地，语句 "if not ItemCount" 将得出相反的结果。

运算符例如 NOT/AND/OR/>/=/< 将自动生成一个 true 或 false 的值: 它们是 true 得出 1，而 false 得出 0。例如，在下面的表达式中，如果任何一个条件为 true，变量 Done 会指定为 1 :

    Done := A_Index > 5 or FoundIt

如上面提示的那样，一个变量可以简单地通过留空或指定为 0 使其一直是 false 值。利用这个，速写的语句 "if Done" 可以用来检查变量 Done 是 true 还是 false。

单词 true 和 false 是包含 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 % "变量 MyVar 包含" MyVar "。"
    Loop % Iterations + 1
    WinSet, Transparent, % X + 100
    Control, Choose, % CurrentSelection - 1

## 表达式中的运算符

除非在下面另有规定外，优先级相同的运算符例如乘(*)和除(/)按从左到右的顺序计算。相比之下，优先级低的运算符在优先级高的之后执行，比如加(+)在乘(*)后执行。例如，3 + 2 * 2 等价于 3 + (2 * 2)。括号在这个例子里可以用来超越优先级: (3 + 2) * 2

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

%Var% | 在表达式中如果一个变量被百分号围住(例如 %Var%)，不管此变量包含什么都将被当作另一个变量的名称或者部分名称(如果不存在此变量，%Var% 就解析为一个空字符串)。常用来像下例这样引用数组元素: Var := MyArray%A_Index% + 100 被引用的元素不应该是环境变量、剪切板或任何保留的/只读的变量。如果是，它将被当做一个空字符串。
++ -- | 前置和后置递增/递减。将变量增加或减少 1(不过在 v1.0.46 之前的版本里，只有将它们放在一行才能用；不能有其他的运算符出现)。此运算符可以放在变量名称的前面或后面。如果出现在变量的前面，此运算马上执行并且它的结果可以给之后的运算使用。例如 Var := ++X 马上递增 X 然后将其值传给 Var。相反地，如果运算符出现在变量的后面，变量被之后的运算使用过后才执行此运算。例如 Var := X++ 仅在把当前 X 的值给 Var 之后才递增 X。
** | 幂。底和指数都可以包含小数点。如果指数是负数，即使底和指数都为整数，结果也将格式为浮点数。因为 ** 的优先级比负号更高，-2**2 计算成 -(2**2) 求得 -4。因此，要让负数能够做幂运算的底，可以将这个负数用小括号括住，比如 (-2)**2。注意：一个负底数配上一个分数指数是不被支持的，例如: (-2)**0.5 它将得出一个空字符串。不过像 (-2)**2 和 (-2)**2.0 这样都是支持的。
- ! ~ & * | 负号(-):虽然它和减运算符使用一样的符号，不过负号仅适用于单个元素或子表达式，就像这个例子里出现的两种情况一样: -(3 / -x)。顺便说一下，表达式中任何正号(+)都被忽略。 逻辑-非(!):如果运算对象为空或 0，逻辑非的结果将是 1，也就是 "true"。否则，结果将为 0 (false)。例如: !x or !(y and z)。注意: 运算符 NOT 除了没有 ! 的优先级高外，含义与 ! 相同。在 v1.0.46 及之后版本，连续的一元运算符，例如 !!Var 是被允许的，因为它们运算的顺序是从右到左。 按位-非(~):此运算符反转其运算对象的每一位。如果运算对象是一个浮点数，在运算前将被截成整数。如果运算对象是 0 到 4294967295 (0xffffffff) 之间的数，它将被视为一个无符号的 32 位数值；否则，它将被视为一个有符号的 64 位数值，例如 ~0xf0f 得出 0xfffff0f0 (4294963440)。 地址(&)和 Dereference(解引用) (*): &MyVar 返回变量 MyVar 的内容在内存里的地址。相反地，*Expression 假设 Expression 已解析为一个数字的内存地址；它将取得数字 0 到 255 之间的地址里的字节(如果地址为 0，值将始终为 0；但必须避免是其它任何非法的地址，因为它可能使脚本崩溃；此外，NumGet() 获取数字通常会更快一些)。这些很少使用的运算符可以帮助我们使用 DllCall 结构体以及处理含有二进制零的字符串。
* / // | 乘(*):如果输入的都是整数的话，结果也是整数；反之，结果为浮点数。 True divide(真除) (/):与 EnvDiv 不同，即使输入的都是整数，真除运算也将得出浮点数的结果。例如，3/2 得出 1.5 而不是 1，4/2 得出 2.0 而不是 2。 Floor divide(向下舍除) (//):如果输入的两个都是整数，双斜线运算符将使用高效的整数除法。例如，5//3 得出 1 ，5//-3 得出 -1。如果输入的任何一个是浮点数，将执行浮点型除法并且截取数轴向左最接近整数的结果。例如，5//3.0 得出 1.0 而 5.0//-3 得出 -2.0。虽然浮点型除法的结果是一个整数，但它以浮点数的格式存储，以便其它使用者能使用浮点格式。计算模数，请看 mod()。 *= 和 /= 运算符是用变量的值乘或除另一个值的一种简写方式。例如，Var*=2 产生的结果同 Var:=Var*2 一样(不过前者执行得更好)。 除以 0 将得到一个空结果(空字符串)。
+ - | 加(+)和减(-)。注意:在表达式中，任何在数学运算中出现的空值(空字符串)不假设为零，而被当作是错误，其导致那部分的表达式得出一个空字符串。例如，如果变量 X 为空，则表达式 X+1 得到一个空值而不是 1。 += 和 -= 运算符是递增或递减一个变量的简写方式。例如，Var+=2 产生的结果同 Var:=Var+2 一样(不过前者执行得更好)。类似地，一个变量想要增加或减少 1 的话还可以使用 Var++, Var--, ++Var 或 --Var。
<< >> | 左移位(<<)和右移位(>>)。使用范例: Value1 << Value2。任何浮点数先被截为整数再参加计算。左位移(<<) 等价于 Value1 * (2 ** Value2)。右位移(>>) 等价于 Value1 / (2 ** Value2) 并且取数轴向左最接近整数的结果；例如，-3>>1 结果为 -2。
& ^ | | 位与(&), bitwise-exclusive-or(位异或) (^)和位或(|)。三个中，& 的优先级最高而 | 优先级最低。任何浮点数在运算前都要先转换成整数。
. | 连接。点运算符用于将两个元素连接成一个字符串(应确保点的两边至少有一个空格)。你也可以忽略句点，得到同样的结果(除非那有不明确的例如 x -y 或当右边的元素以 ++ 或 -- 开头时)。当忽略句点时，合并的两个元素之间应该至少有一个空格。 示例(表达式方法): Var := "The color is " . FoundColor 示例(传统方法): Var = The color is %FoundColor% 子表达式同样可以被连接。例如: Var := "The net price is " . Price * (1 - Discount/100) 以句点(或其他任何运算符)开头的行，自动添加到上一行。
> < >= <= | 大于(>),小于(<),大于等于(>=)和小于等于(<=)。如果输入的任何一个都不是数字，两边将按字母的顺序比较(一个由双引号括住的字符串例如 "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，将在 var 里存储 2；反之，其存储 3。要提高性能，可以只计算胜出的分支(请看最少运算)。注意:由于兼容性的原因，问号两边都至少要有一个空格才能被认出来(此问题可能会在未来的版本解决)。
:= += -= *= /= //= .= |= &= ^= >>= <<= | 赋值。对变量的内容进行操作再把结果存回同个变量(不过在 1.0.46 之前的版本，这些只能用在一行最左边的运算符并且是前 5 个运算符才被支持)。最简单的赋值运算符就是冒号-等号 (:=)，用于将一个表达式的结果存在一个变量里。例如，Var //= 2 执行向下舍除，Var 除以 2，接着将结果存回到 Var。类似地，Var .= "abc" 是 Var := Var . "abc" 的简写。 不像大多数运算符，赋值是从右到左开始运算的。所以，像这样的一行: Var1 := Var2 := 0 首先将 0 赋值给 Var2 再将 Var2 赋值给 Var1。 如果一个赋值运算被用作其它运算符的输入部分，输入部分的值就是变量本身的值。例如，表达式 (Var+=2) > 50 如果 Var 新增加了值后大于 50，那么表达式为 true。而且也允许赋值操作被传递给 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)当运算符 +=, -= 和 *= 不是多语句表达式的一部分时才会把空白值当作零(否则，这样的运算产生的结果还是空白)。
, | 逗号(多语句)[v1.0.46+]。逗号被用来在一行中写入多个子表达式。它最常用来将多个赋值语句或函数调用放在一起。例如: x:=1, y+=2, ++index, func() [不过请看逗号的性能]。这些语句以从左到右的顺序执行。注意:以逗号(或任何其他运算符)开头的行将被自动添加到上一行。 在 v1.0.46.01 及之后版本，当逗号紧跟着一个变量和一个等号，那个等号将被自动作为赋值 (:=)。例如，下列所有的都是赋值: x:=1, y=2, a=b=c
mod() round() abs() | 这几个以及其它的内置数学函数在这里有阐述。

性能: 表达式赋值运算符 (:=) 已被优化，以便在执行像下面这样简单的赋值时能和非表达式运算符(=)一样快:

    x := y ; 和 x = %y% 的性能一样
    x := 5 ; 和 x = 5 的性能一样
    x := "literal string" ; 和 x = literal string 的性能一样

逗号运算符(,)强行将简单的赋值语句当作表达式来运算而不是在速度上进行优化。例如，下列各自放一行的话，速度将至少提高 20% (这个性能上的差异可能在未来的版本中被减少): Var++, Var-=Var2, Var:=55, Var:="literal string", Var:=Var2。相反地，如果表达式含有的是非平凡的比如函数调用，逗号通常能提高性能(虽然一般不到 5%)，因为组合的表达式可以被一次全部运算而不是分开运算。

## 内置变量

下列变量都内置在程序中，并且可以被任何脚本引用。除了 Clipboard, ErrorLevel 和命令行参数，这些变量都是只读的；也就是说，它们的内容不能被脚本直接改变。

### 目录

- 特殊字符: A_Space, A_Tab
- 脚本属性: command line parameters, 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 | 当前脚本所在目录的完全路径。为了向后兼容 AutoIt v2，只为 .aut 脚本包含路径未尾的反斜线(甚至根分区也一样)。一个对 .aut 脚本的例子: C:\My Documents\
A_ScriptName | 当前脚本的文件名称，不带路径，例如: MyScript.ahk。
A_ScriptFullPath | 结合了上面两个变量的脚本的完全路径，例如: C:\My Documents\My Script.ahk
A_LineNumber | 当前脚本中正在执行的那一行的行号(或是它的某个 #Include 文件)。这个行号同 ListLines 显示的一致；它对错误报告会比较有用，比如这个例子: MsgBox 不能写入记录文件(行号 %A_LineNumber%)。 由于已编译的脚本将它所有的 #Include 文件合 并进一个大脚本，它的行号可能和它以非编译模式运行时不一样。
A_LineFile | A_LineNumber 所属的文件名称及其完全路径，除非当前行属于未编译脚本的某个 #Include 文件，否则它会和 A_ScriptFullPath 一样。
A_ThisFunc [v1.0.46.16+] | 当前正在执行的自定义的函数名称(如果没有就是空白)；例如: MyFunction
A_ThisLabel [v1.0.46.16+] | 当前正在执行的标签(子程序)的名称(如果没有就是空白)；例如: MyLabel。当脚本执行 Gosub/Return 或 Goto 时它的值会更新。此变量也会被像 timers, GUI threads, menu items, hotkeys, hotstrings, OnClipboardChange 和 OnExit 那样自动调用标签的命令更新。不过，在执行过程中从上面的语句“掉落”到一个标签时，A_ThisLabel 不会更新，还是保留之前的值。同时请看: A_ThisHotkey
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_IsCompiled | 如果脚本作为一个已编译的 EXE 运行，它就包含 1，如果不是，则为空。
A_ExitReason | 最近一次脚本被要求退出的原因。除非脚本有个 OnExit 子程序并且这个子程序正在运行或已被一个退出的尝试调用过至少一次，否则此变量为空。详见 OnExit。

### 日期和时间

A_YYYY | 当前 4 位数的年份(例如 2004)。与 A_Year 同义。注意：要取得一个适用于你的区域和语言设置的格式化的时间或日期，可以使用 "FormatTime, OutputVar" (时间和长日期格式) 或者 "FormatTime, OutputVar,, LongDate" (获取长日期格式)。
A_MM | 当前 2 位数的月份(01-12)。与 A_Mon 同义。
A_DD | 当前月份的 2 位数的日期(01-31)。与 A_MDay 同义。
A_MMMM | 在当前的用户语言里当前月份的全称，例如 July
A_MMM | 在当前的用户语言里当前月份的缩写，例如 Jul
A_DDDD | 在当前的用户语言里当前星期几的全称，例如 Sunday
A_DDD | 在当前的用户语言里当前星期几的 3 个字母的缩写，例如 Sun
A_WDay | 当前星期几的 1 位数(1-7)。1 表示星期天。
A_YDay | 当前年份的天数(1-366)。变量的值是没有填充零的，例如取得 9，而不是 009。要取得一个用零填充的值，可使用: FormatTime, OutputVar, , YDay0
A_YWeek | 当前的年份和星期数(例如 200453)按照 ISO 8601。要将年份和星期数分离开来，可以使用语句 StringLeft, Year, A_YWeek, 4 和 StringRight, Week, A_YWeek, 2。A_YWeek 的精确定义：如果 Week 包含了新年的一月一日并有四天或更多在内，那么它被称为第一个星期。否则，它是前一年的最后一周，而且下一周才是新年的第一周。
A_Hour | 当前 24 小时制中的 2 位小时数(00-23) (例如，17 表示 5pm)。要获得 12 小时制以及 AM/PM 指示，参此例: FormatTime, OutputVar, , h:mm:ss tt
A_Min | 当前的 2 位分钟数(00-59)。
A_Sec | 当前的 2 位秒数(00-59)。
A_MSec | 当前的 3 位毫秒数(000-999)。要移除前置的零，参此例: Milliseconds := A_MSec + 0
A_Now | YYYYMMDDHH24MISS 格式的当前本地时间。注意：时间和日期的算术可以用 EnvAdd 和 EnvSub 来完成。此外， FormatTime 可以按照你的区域设置或首选项来格式化日期和/或时间。
A_NowUTC | YYYYMMDDHH24MISS 格式的当前世界协调时间(UTC)。UTC 本质上和格林尼治标准时间(GMT)是一样的。
A_TickCount | 计算机重启后经过的毫秒数。通过将 A_TickCount 存到一个变量里，然后把最新的 A_TickCount 的值减去那个变量，就能测得消逝的时间。例如:
    StartTime := A_TickCount
    Sleep, 1000
    ElapsedTime := A_TickCount - StartTime
    MsgBox,已经消逝了 %ElapsedTime% 毫秒。
如果你需要比 A_TickCount 的 10ms 更高的精确度，请用 QueryPerformanceCounter()。

### 脚本设置

A_IsSuspended | 如果脚本挂起则包含 1；否则为 0。
A_BatchLines | (与 A_NumBatchLines 同义)由 SetBatchLines 来设置当前的值。例如: 200 或 10ms (根据格式)。
A_TitleMatchMode | 由 SetTitleMatchMode 设置当前的模式：1, 2, 3 或 RegEx。
A_TitleMatchModeSpeed | 由 SetTitleMatchMode 设置当前的匹配速度(fast 或 slow)。
A_DetectHiddenWindows | 由 DetectHiddenWindows 设置当前的模式(On 或 Off)。
A_DetectHiddenText | 由 DetectHiddenText 设置当前的模式(On 或 Off)。
A_AutoTrim | 由 AutoTrim 设置当前的模式(On 或 Off)。
A_StringCaseSense | 由 StringCaseSense 设置当前的模式(On, Off 或 Locale)。
A_FormatInteger | 由 SetFormat 设置当前的整数格式(H 或 D)。
A_FormatFloat | 由 SetFormat 设置当前的浮点数格式。
A_KeyDelay | 由 SetKeyDelay 设置当前的延迟(总是十进制数，不是十六进制)。此延迟是针对传统的 SendEvent 模式，不是 SendPlay。
A_WinDelay | 由 SetWinDelay 设置当前的延迟(总是十进制数，不是十六进制)。
A_ControlDelay | 由 SetControlDelay 设置当前的延迟(总是十进制数，不是十六进制)。
A_MouseDelay | 由 SetMouseDelay 设置当前的延迟(总是十进制数，不是十六进制)。此延迟是针对传统的 SendEvent 模式，不是 SendPlay。
A_DefaultMouseSpeed | 由 SetDefaultMouseSpeed 设置当前的速度(总是十进制数，不是十六进制)。
A_IconHidden | 如果托盘图标当前被隐藏则为 1；否则为 0。可以用 #NoTrayIcon 或 Menu 命令来隐藏图标。
A_IconTip | 除非用 Menu, Tray, Tip 已经为托盘图标指定了自定义提示--这种情况下它就是此提示的文本；否则为空。
A_IconFile | 除非用 Menu, tray, icon 已经指定了自定义托盘图标--这种情况下它就是此图标文件的完全路径和名称；否则为空。
A_IconNumber | 如果 A_IconFile 为空，则它也为空。否则，它是 A_IconFile 里的图标编号(一般是 1)。

### 用户闲置时间

A_TimeIdle | 从系统最后一次接收键盘、鼠标或其它输入后所消逝的毫秒数。这用来判断用户是否离开是很有用的。除了操作系统是 Windows 2000, XP 或之后的版本外，此变量将为空。用户物理的输入和由任何程序或脚本(例如 Send 或 MouseMove 命令)产生的模拟输入都将重置此变量为零。由于这个值倾向于以 10 的增量增加，所以判断它是否等于另一个值便毫无意义了。取而代之，可以检查它是否大于或小于另一个值。例如: IfGreater, A_TimeIdle, 600000, MsgBox, 上一次键盘或鼠标的活动至少是 10 分钟前的事了。
A_TimeIdlePhysical | 和上面的一样，不过在安装了相应的钩子(keyboard 或 mouse) 时会忽略模拟的键击和/或鼠标点击。如果没有安装任何钩子，此变量就等于 A_TimeIdle。如果只有一个钩子，那么将只忽略它模拟的输入。在判断用户是否真的出现方面，A_TimeIdlePhysical 可能比 A_TimeIdle 更有用。

### GUI 窗口和菜单栏

A_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 窗口的宽和高。它们适用于窗口的客户端区域，此区域包括标题栏、菜单栏和边框。
A_GuiX A_GuiY | 这些变量包含了 GuiContextMenu 和 GuiDropFiles 事件的 X 和 Y 坐标。坐标是相对于窗口的左上角的。
A_GuiEvent 或 A_GuiControlEvent | 启动了当前线程的事件类型。如果线程不是通过 GUI 动作启动的，此变量为空。反之，它会包含以下字符串之一: Normal: 通过一个鼠标左键单击或者通过键击(箭头按键、TAB 键、空格、带下划线的快捷键，等等)触发的事件。 这个变量的值也可以给菜单栏项目和像 GuiClose 和 GuiEscape 这样的特殊事件来使用。 DoubleClick: 此事件可由双击来触发。注意：双击中的首次点击仍会引起 Normal 事件先被获取。换句话说，子程序被启动了两次：一次是首次点击，然后是第二次。 RightClick: 仅发生在 GuiContextMenu, ListViews 和 TreeViews。 Context-sensitive values: 详见 GuiContextMenu, GuiDropFiles, Slider, MonthCal, ListView 和 TreeView。
A_EventInfo | 包含下列事件的额外信息: OnClipboardChange 标签 鼠标滚轮热键 (上滚/下滚) RegisterCallback() GUI 事件，也就是 GuiContextMenu, GuiDropFiles, ListBox, ListView, TreeView 和 StatusBar。如果没有事件的额外信息，A_EventInfo 包含 0。

注意：与变量比如 A_ThisHotkey 不同，每个 thread 为 A_Gui, A_GuiControl, A_GuiX/Y, A_GuiEvent 和 A_EventInfo 包含了它自己的值。因此，如果一个变量被另一个变量打断，在恢复时仍可以在那些变量里看到它原来/正确的值。

### 热键、热字符串和自定义菜单项

A_ThisMenuItem | 最近选择的自定义菜单项的名称(如果没有就为空)。
A_ThisMenu | A_ThisMenuItem 所在的菜单的名称。
A_ThisMenuItemPos | 指示 A_ThisMenu 中 A_ThisMenuItem 当前位置的编号。菜单的第一项就是 1，第二项则为 2，以此类推。菜单分隔符行也计算在内。如果 A_ThisMenuItem 为空或不再存在 A_ThisMenu 里，此变量为空。如果 A_ThisMenu 本身已不再存在，它也为空。
A_ThisHotkey | 最近执行的热键和热字符串的按键名称(如果没有则为空)，例如 #z。如果当前线程被其它热键中断，这个值将会改变，所以如果你之后需要在一个子程序中使用原来的值，确保马上将其复制到另一个变量。 当一个热键被第一次创建时--无论是通过脚本中的 Hotkey 命令还是双冒号标签--它的键名和修饰键符号的顺序成为那个热键的固定名称。同时请看: A_ThisLabel
A_PriorHotkey | 除了存放的是前一个热键的键名外，其它的同上。如果没有它将为空。
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\用户名\LOCALS~1\Temp)。它从下列的几个地方获得(按顺序): 1) 环境变量 TMP, TEMP 或 USERPROFILE；2) Windows 目录。在 Windows 9x 上，如果没有 TMP 和 TEMP 的存在，将使用 A_WorkingDir 的值。
A_OSType | 正在运行的操作系统的类型。值为 WIN32_WINDOWS (即 Windows 95/98/ME)或 WIN32_NT (即 Windows NT4/2000/XP/2003/Vista)。
A_OSVersion | 下列字符串之一: WIN_VISTA [需要 v1.0.44.13+], WIN_2003, WIN_XP, WIN_2000, WIN_NT4, WIN_95, WIN_98, WIN_ME。例如:
    if A_OSVersion in WIN_NT4,WIN_95,WIN_98,WIN_ME ;注意：逗号周围没空格。
    {
    MsgBox 此脚本需要 Windows 2000/XP 及之后版本。
    ExitApp
    }
A_Language | 系统的默认语言，值为这些 4 位数字代码中的一个。
A_ComputerName | 网络上可查看到的计算机名称。
A_UserName | 当前用户的登录名称。
A_WinDir | Windows 目录。例如: 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 | 当前用户开始菜单中 Programs 文件夹的完全路径和名称。
A_ProgramsCommon | 所有用户开始菜单中 Programs 文件夹的完全路径和名称。
A_Startup | 当前用户开始菜单中启动文件夹的完全路径和名称。
A_StartupCommon | 所有用户开始菜单中启动文件夹的完全路径和名称。
A_MyDocuments | 当前用户“我的文档”文件夹的完全路径和名称。与大多数变量不同，如果此文件夹是一个驱动器的根目录，末尾处不包括反斜线。例如，它包含 M: 而不是 M:\
A_IsAdmin | 如果当前用户有管理员权限，此变量值为 1。否则为 0。不过在 Windows 95/98/Me 下此变量始终为 1。 在 Windows Vista 下，一些脚本可能需要管理员权限才能正常的运行(比如一个会影响进程或窗口的脚本需要管理员权限来运行)。要实现此目的，请在脚本的顶部添加下列语句(对已编译的脚本需要一些调整，也许还需要传递参数):
    if not A_IsAdmin
    {
     DllCall("shell32\ShellExecuteA", uint, 0, str, "RunAs", str, A_AhkPath
     , str, """" . A_ScriptFullPath . """", str, A_WorkingDir, int, 1)
     ExitApp
    }
A_ScreenWidth A_ScreenHeight | 主显示器的宽度和高度，以像素为单位(例如 1024 和 768)。 要得到多显示器系统中其他显示器的尺寸，请用 SysGet。 要得到整个桌面(即使它跨越了多个显示器)的宽和高，可用下面的例子 (不过在 Windows 95/NT 下，下面的两个变量都将被设置为 0): SysGet, VirtualWidth, 78 SysGet, VirtualHeight, 79 此外，可用 SysGet 来获得显示器工作区域，它会比显示器的整个区域要小，因为没有包括任务栏和其他注册的桌面工具栏。
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 类型里。 在 Windows 95 中的已知限制：如果此变量的内容被高频率(即每 500 ms 或更快)反复读取，就会干扰使用者双击鼠标的能力。没有已知的解决方案。
A_CaretX A_CaretY | 当前文本插入符的 X 和 Y 坐标。除非使用了 CoordMode 让坐标相对于整个显示器，否则它们相对于激活的窗口。如果没有激活的窗口或者无法确定插入符的位置，这两个变量将为空。 下面这个脚本允许你四处移动插入符时通过自动更新的提示来显示它当前的位置。注意某些窗口(例如某些版本的 MicroSoft Word)将报告同个插入符位置而不管它真正的位置。 #Persistent SetTimer, WatchCaret, 100 return WatchCaret: ToolTip, X%A_CaretX% Y%A_CaretY%, A_CaretX, A_CaretY - 20 return 如果这些变量的内容被高频率(即每 500 ms 或更快)反复读取，就会干扰使用者双击鼠标的能力。没有已知的解决方案。
Clipboard | 操作系统的剪贴板内容，它能被读取或者写入。请看 Clipboard 章节。
ClipboardAll | 整个剪贴板的内容(例如格式设置和文本)。请看 ClipboardAll。
ErrorLevel | 请看 ErrorLevel。
A_LastError | 操作系统的函数 GetLastError() 返回的结果。详见 DllCall() 和 Run/RunWait。

### 循环

A_Index | 当前循环重复的次数(64 位的整型数)。例如，脚本第一次执行循环体时，此变量的值为 1。详见 Loop。
A_LoopFileName 等 | 此变量和其它相关的变量仅在文件-循环中有效。
A_LoopRegName 等 | 此变量和其它相关的变量仅在注册表-循环中有效。
A_LoopReadLine | 请看文件-读取循环。
A_LoopField | 请看分解循环。

## 环境变量对“普通”变量

环境变量由操作系统维护。在命令提示符中输入 SET 并回车，你就可以看到一个它们的列表。

一个脚本可以用 EnvSet 创建一个新的环境变量或者改变一个已存在的环境变量的值。然而，这些添加和改变都是私有的；它们不会被系统其它的部分看到。不过还有一个例外，当一个脚本使用 Run 或 RunWait 来运行一个程序(甚至另一个脚本)：这个程序将继承一个复制自父脚本的环境变量，包括那些私有的环境变量。

在 v1.0.43.08 及之后版本，推荐在所有新脚本中通过下面的方式获得像 Path 这样的环境变量:

    EnvGet, OutputVar, Path ;解释请看 #NoEnv。

## 变量的容量和内存

- 每个变量可以包含多达 64 MB 的文本(这个限制可以通过 #MaxMem 来增加)。
- 当给变量赋的新值比当前的更长时，将自动分配额外的系统内存。
- 占据巨大内存空间的变量可将其设置为空来释放内存，例如: var := ""
- 没有对一个脚本可以创建的变量个数做限制。程序被设计来支持至少几百万变量而不会出现一个性能上的巨大落差。
- 命令、函数和表达式通常能够接受 15 位精度的浮点数值；64 位带正负号的整数值，范围从-9223372036854775808 (-0x8000000000000000) 到 9223372036854775807 (0x7FFFFFFFFFFFFFFF)。任何在范围之外的整数常量不被支持并可能产生不一致的结果。相反，整数的算术运算却可能产生溢出(例如: 0x7FFFFFFFFFFFFFFF + 1 = -0x8000000000000000)。

翻译: 第八单元 8thunit@gmail.com 修正：天堂之门 menk33@163.com 2008年9月27日