AutoHotkey

版本 v1.1.00.00

www.autohotkey.com

www.autohotkey.net/~Lexikos/AutoHotkey_L

©2003-2010 Chris Mallett, 部分属于 ©AutoIt 团队 和 AHK 社区

软件许可: GNU 通用公共许可证

警告

由于 AutoHotkey 和 AutoHotkey_L 的一些基本差异 (尤其是 Unicode 和 x64 版本), 为 AutoHotkey 编写的脚本可能无法正常运行在 AutoHotkey_L 上. 关于已知的兼容性问题和解决方法的细节, 参见下面:

  • 脚本兼容性 - Unicode 和 ANSI 的比较, DllCall, NumPut/Get 以及其他变化
  • 脚本文件代码页 - 把您的文件保存为 UTF-8 编码!

AutoHotkey, AutoHotkey_L 和已编译脚本常常会引起反病毒软件的错误警告. 想了解更多细节, 参见 社区常见问题.

快速参考

基础:

  • 初学者向导
  • 带有 AutoHotkey 支持的文本编辑器
  • 常见问题
  • 脚本
    • 命令
    • 变量和表达式
    • 函数
    • 对象
    • 交互式调试

键盘和鼠标:

  • 热键 (鼠标, 游戏杆和键盘快捷键)
  • 热字串和自动替换
  • 重映射按键和鼠标按钮
  • 按键, 鼠标按钮和游戏控制杆列表

其他:

  • DllCall
  • 正则表达式快速参考
  • AutoHotkey_L 特性

致谢

特别感谢 Jonathan Bennett, 他于 1999 年把 AutoIt v2 作为自由软件慷慨地发布出来, 使其成为我以及世界上其他许多人节省时间的工具. 此外, AutoHotkey 中许多针对 AutoIt v2 命令集的增强功能以及 Window Spy 和脚本编译器都是直接改写自 AutoIt v3 源代码. 所以为此同样感谢 Jon 和 AutoIt 的其他开发人员.

最后, AutoHotkey 离开了 这些人 也不会有今天.

~ Chris Mallett


AutoHotkey Tutorial: Macro and Hotkey Creation

指南和概述

这个简短的介绍将帮助你马上开始编写你自己的宏和热键脚本。

指南目录

  • 创建一个脚本
  • 启动一个程序或文档
  • 发送键击和鼠标点击
  • 激活与操纵窗口
  • 从用户使用的 MsgBox, InputBox 等命令来获取输入的数据
  • 使用变量和剪贴板
  • 一遍遍地重复一系列动作
  • 操纵文件和文件夹
  • 其他功能的概述

创建一个脚本

每个脚本都是一个包含命令的要被程序(AutoHotkey.exe)执行的纯文本文件。一个脚本也可能包含热键和热字串，甚至于全部由它们组成。不过，在没有热键和热字串时，一个脚本从它被启动时起，将从头至尾顺序地执行它的命令。

要创建一个新脚本：

  1. 打开 Windows 资源管理器并进入一个你选择的文件夹。
  2. 拉下文件菜单并选择 新建 >> AutoHotkey Script (或 新建 >> 文本文档)。
  3. 给文件键入一个名称，确保它以 .ahk 结尾。例如：Test.ahk
  4. 鼠标右键点击此文件并选择 Edit Script。
  5. 在一个新的空行，键入下述内容：
    #space::Run www.google.com

符号 # 表示 Windows 键，因此 #space 意味着按住 Windows 键然后按下空格键来激活一个热键。符号 :: 意味着每次按下此热键时，随后的命令将会被执行，在此例中将转到 Google 网站。要试用此脚本，按下述内容继续操作：

  1. 保存并关闭此文件。
  2. 在 Windows 资源管理器中，鼠标双击来启动脚本。一个新的系统托盘图标出现。
  3. 按住 Windows 键并按下空格键。一个网页在默认浏览器中打开。
  4. 要退出或编辑此脚本，鼠标右键点击它的系统托盘图标。

注意：多个脚本能被同时运行，每个带有它自己的托盘图标。此外，每个脚本能拥有多个热键和热字串。

启动一个程序或文档

Run 命令用来启动一个程序、文档、URL(统一资源定位符) 或者快捷方式。这里有一些普通的例子：

Run Notepad
Run C:\My Documents\Address List.doc
Run C:\My Documents\My Shortcut.lnk
Run www.yahoo.com
Run mailto:someone@somedomain.com

一个热键通过包含一个热键标记能被分配给以上任何一个例子。在下面的第一个例子中，被分配的热键是 Win+N，而在第二个里是 Control+Alt+C：

#n::Run Notepad
^!c::Run calc.exe

上面的例子被称为单行热键，因为每个热键仅由单个命令组成。要通过一个热键执行多个命令，把首行放在热键定义的下面并让末行有一个 return。例如：

#n::
Run http://www.google.com
Run Notepad.exe
return

如果要运行的程序或文档没有与系统结合在一起，指定它的完整路径来使它启动：

Run %A_ProgramFiles%\Winamp\Winamp.exe

在上面的例子里，%A_ProgramFiles% 是一个内置变量。通过使用它而不是类似像 C:\Program Files，脚本将更便携，意味着它将很有可能在其他计算机上运行。注意：命令的名称和变量都不区分大小写。例如，"Run" 和 "run" 是一样的，而且 "A_ProgramFiles" 也和 "a_programfiles" 是一样的。

要让脚本在继续执行前等待程序或文档关闭，使用 RunWait 代替 Run。在下述例子中，MsgBox 命令将不会执行，直到用户关闭了记事本之后：

RunWait Notepad
MsgBox 用户已完成(记事本已被关闭)。

要学习更多关于启动程序的内容--像传递参数、指定工作目录和了解一个程序的退出代码--点击这里。

发送键击和鼠标点击

键击通过使用 Send 命令发送到活动的(最前面的)窗口。在下述例子中，Win+S 变为一个热键去键入一个签名(确保在按下 Win+S 前，像一个编辑器或起草电子邮件信息的窗口是活动的)：

#s::
Send Sincerely,{Enter}John Smith
return

在上面的例子里，所有的字符精确地发送，除了 {Enter}，其模拟按下了 Enter 键。下一个例子说明了其他一些常用的特殊字符：

Send ^c!{tab}pasted:^v

上面这行发送了一个 Control+C 紧跟一个 Alt+Tab 紧跟字串 "pasted:" 紧跟一个 Control+V。要得到一个完整的特殊字符和按键的列表，请见 Send 命令。

最后，键击也能对你键入的缩写做出反应而被发送，这称为热字串。例如，每当你键入 Btw 紧跟一个空格或逗号，下述这行会把它替换为 "By the way"：

::btw::by the way

鼠标点击：要对一个窗口发送一个鼠标点击，首先必须要定义将要点击的位置的 X 和 Y 坐标轴。这个能用 AutoScriptWriter 或 Window Spy 来完成，它们已包含在 AutoHotkey 中。下述步骤是适用于 Window Spy 的方法：

  1. 从脚本的托盘图标菜单或系统开始菜单启动 Window Spy。
  2. 通过鼠标点击感兴趣的窗口的标题栏、alt 标签栏或其他方法来激活窗口 (被设计好的 Window Spy 将处于 "置顶" )。
  3. 在目标窗口中移动鼠标指针到想要的位置并记下由 Window Spy 显示的鼠标坐标轴 (或按下 Shift-Alt-Tab 来激活 Window Spy 以便 "冻结的" 坐标轴能被复制和粘贴)。
  4. 在 Click 命令中使用上面发现的坐标轴。下述例子点击了鼠标左键：
    Click 112, 223

要移动鼠标而不是点击，请用 MouseMove。要拖选鼠标，请用 MouseClickDrag。

激活与操纵窗口

要激活一个窗口 (使它在最前面)，使用 WinActivate。要探测一个窗口是否存在，使用 IfWinExist 或 WinWait。下述的例子阐明了这些命令：

IfWinExist 无标题 - 记事本
{
    WinActivate
}
else
{
    Run Notepad
    WinWait 无标题 - 记事本
    WinActivate
}

上面的例子首先搜索标题以"无标题 - 记事本" (区分大小写) 开始的任何存在的窗口。如果这样的一个窗口被找到，它将被激活。否则，记事本被启动并且脚本等待无标题窗口出现，那时它将被激活。上面的例子也运用了最近找到的窗口来避免需要在每个 WinActivate 右边指定窗口的标题。

其他一些常用的窗口命令是：

  • IfWinActive: 检查指定的窗口当前是否激活。
  • WinWaitActive: 等待指定的窗口变为活动的窗口 (典型地使用在发送一个窗口激活键击之后，例如按下 Control-F 来“查找”)。
  • WinClose: 关闭指定的窗口。
  • WinMove: 移动及(或)调整指定窗口的大小。
  • WinMinimize, WinMaximize, WinRestore: 分别最小化、最大化或还原指定的窗口。

从用户使用的 MsgBox, InputBox 等命令来获取输入的数据

下述例子显示一个带两个按钮的对话框 (是 和 否)：

MsgBox, 4, , 你想继续吗？
IfMsgBox, No
    return
;否则，用户选择了是。
MsgBox 你按了是。

使用 InputBox 命令来提示用户键入一个字串。使用 FileSelectFile 或 FileSelectFolder 来让用户选择一个文件或文件夹。为了更高级的任务，使用 Gui 命令来创建自定义用户界面和数据输入表单。

提示：你也许已经从其他例子中注意到任何命令的第一个逗号可以被省略 (除了当第一个参数为空或者命令是单独在一个连续部分的顶端) 。例如：

MsgBox 这是可以的。
MsgBox, 这也是可以的 (它有一个明显的逗号)。

使用变量和剪贴板

一个变量是脚本储存文本或数字的一个内存区域。尽管所有变量将它们的内容存为字符串，一个仅包含数位的变量会在一个数学运算或比较需要时，自动地转换为一个数字。相反地，当一个数学运算的结果需要被存进一个变量时会被转换回一个字串。

除了在函数里的局部变量外，所有变量都是全局的；就是说，它们的内容可以在脚本的任意部分被读取或更改。另外，变量不需要声明；它们只在使用它们时存在 (并且每个变量都以空或空白开始) 。

要指定一个字串给一个变量，参照这些例子：

MyVar1 = 123
MyVar2 = 我的字串
要将一个变量的内容和一个数字或字串比较，参照这些例子：
if MyVar2 = 我的字串
{
    MsgBox MyVar2 包含字串"我的字串"。
}
if MyVar1 >= 100
{
    MsgBox MyVar1 包含 %MyVar1%，它是一个大于或等于 100 的数字。
}

在上面的 MsgBox 行， 注意那第二个出现的 MyVar1 被括在百分号内。它在那里显示了 MyVar1 的内容。相同的手法能用来复制一个变量的内容给另一个变量。例如：

MyVarConcatenated = %MyVar1% %MyVar2%

上面这行在变量 MyVarConcatenated 中储存了字串 "123 我的字串" (不含引号) 。

要比较一个变量和另一个变量的内容的用法，参考这个例子：

if (ItemCount > ItemLimit)
{
    MsgBox 在 ItemCount 里的值，是 %ItemCount%，比 %ItemLimit% 大。
}

注意上面例子的首行包含圆括号。圆括号表示那 if-语句包含一个表达式。没有它们的话，那行将被认作一个“非表达式的 if-语句”，并且因此它将需要让 ItemLimit 以百分号围住。这样的 IF 语句被限制为一个单独的比较运算符；也就是说，它们不能包含数学运算符或者像 "AND" 和 "OR" 这样的联合运算符。

数学: 要执行一个数学运算，使用冒号-等号运算符 (:=) 来指定一个表达式的结果给一个变量， 像下面的例子：

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

请见表达式来获得一个完整的数学运算符列表。

剪贴板: 名为 Clipboard 的变量是特殊变量，因为它包含了当前 Windows 剪贴板里的文本。即使如此，它也能像一个普通变量被使用。例如，下面这行将显示当前剪贴板的内容：

MsgBox %clipboard%

要改变剪贴板内容，参考下述例子，它用新的文本替换了当前剪贴板里的内容：

clipboard = 一行文本。`r`n第二行文本。`r`n

在上面这行，`r 和 `n (重音符紧跟着字母 "r" 或 "n") 被用来标明两个特殊的字符：回车和换行。这两个字符重新开始一个文本行就像用户按下了 Enter 键。

要追加文本到剪贴板(或任何其他变量)，参照这个例子：
clipboard = %clipboard% 这里是追加的文本。

详见剪贴板和变量章节。

一遍遍地重复一系列动作

要连续地不止一次执行某物，一个 loop 就是答案。下述 loop 显示了三次 MsgBox ：

Loop 3
{
    MsgBox 此窗口将被显示三次。
}

你也能在单词 Loop 后面指定一个变量，它在脚本内部的某处其循环的次数被定义时是有用的：

Loop %RunCount%
{
    Run C:\Check Server Status.exe
    Sleep 60000  ;暂停 60 秒。
}

在上面例子里，loop 将执行指定的次数，除非 RunCount 是 0，在这种情况下，loop 整个被跳过。

一个 loop 也可以终止它自己，当一个或多个条件改变时。下述例子重复地点击鼠标左键，当用户按住 F1 键时：

$F1::  ;让 F1 键成为一个热键 ( $ 符号有助于下面 GetKeyState 的 "P" 模式)。
Loop  ;由于没有指定数字给它，这是一个无限循环，除非在内部碰到 "break" 或 "return"。
{
    if not GetKeyState("F1", "P")  ;如果此状态为真，则用户已经物理地释放了 F1 键。
        break  ;打破循环。
    ;否则 (由于上面没有"打破")，保持点击鼠标左键。
    Click  ;在当前光标位置点击鼠标左键。
}
return

上面的例子和一个有时称为 "while...do" 的循环在功能上相同。短语 "while...do" 指的是当某个或某些条件仍然为真时，此循环重复地做某事的事实。在本例中，当 F1 键被按住的时候，此循环继续点击鼠标左键。当用户释放 F1 键时，此循环探测到此动作并通过 break 命令终止了它自己。Break 引起执行跳到循环的闭合大括号的下一行。

上面给出的例子是一般用途的循环。为了更具体的需要，可参考下述的某个循环：

文件读写循环: 在一个文本文件内一次检索一行。此命令能用来在一行行的基础上将一个文件转换成不同的格式。它也能被用来按你的标准逐行搜索。

文件和文件夹循环: 一次检索一个指定的文件或文件夹。它允许每个文件或文件夹执行一个满足你的标准的操作。

分解循环: 从一个字串里一次检索一个子字串。它允许一个像 "红、绿、蓝" 这样的字串被简单地打断成它的三个组成部分。

注册表循环: 一次检索一个指定的注册表子键的内容。

操纵文件和文件夹

要添加文本到一个文件的末尾 (或创建一个新文件)，使用在下述例子里出现的 FileAppend。注意它在后面使用 `n (换行) 来启用一个新的文本行：

FileAppend, 添加一行文本。`n, C:\My Documents\My Text File.txt

要覆盖一个存在的文件，在 FileAppend 之前使用 FileDelete。例如：

FileDelete, C:\My Documents\My Text File.txt

其他一些常用的文件和文件夹命令是：

  • FileRead: 读取一个文件的整个内容给一个变量。
  • 文件读取循环: 在一个文本文件里逐行检索。
  • IfExist: 根据一个文件或文件夹的是否存在而做出决定。
  • FileSelectFile 和 FileSelectFolder: 为用户选择一个文件或文件夹显示一个对话框。
  • FileDelete/FileRecycle: 删除或回收一个或多个文件。使用 FileRemoveDir 来删除一整个文件夹。
  • FileCopy/FileMove: 复制或移动一个或多个文件。使用 FileCopyDir/FileMoveDir 来复制或移动一整个文件夹。
  • 文件和文件夹循环: 一次检索一个被包含在一个文件夹下的文件和文件夹。
  • FileSetAttrib 和 FileSetTime: 改变一个或多个文件的属性或时间标记。
  • IniRead, IniWrite 和 IniDelete: 创建、访问和修改标准格式的 INI 文件。
  • RegRead, RegWrite, RegDelete 和 Registry Loop: 和 Windows 注册表一起工作。

其他功能的概述

获取每个命令的概述，请见命令列表。


AutoHotkey FAQ

常见问题 (FAQ)

语法

  • 何时才能在命令和它们的参数中使用引号？
  • 何时需要将变量名称装入百分号？
  • 何时才应该将百分号和逗号转义？

常见任务

  • 为什么我脚本中的某些行总是无法执行？
  • 为什么 Run 命令不能启动我的游戏或程序？
  • 怎样获取命令行操作的输出？
  • 怎样才能让一个脚本关闭、暂停或挂起其它的脚本？
  • 怎样才能不退出脚本却可以停止重复的动作？
  • 如何在玩游戏或平时 CPU 高负荷运行时改善性能？
  • 如何在任意编辑器中使用上下文相关的 AutoHotKey 命令帮助？
  • 如何探测一个网页何时加载完毕？
  • 怎样操作或比较日期和时间？
  • 为什么在某些游戏中，Hotstrings, Send 以及 MouseClick 不起作用？
  • 如何控制 Winamp，即使是在它未激活时？
  • 如何改变 MsgBox 的按钮名称？

热键、热字符串和重映射

  • 如何让我的热键和热字符串在 PC 启动时自动生效？
  • 我在把鼠标按键作为热键使用时遇到问题。有什么建议吗？
  • 如何将 Tab 和空格键定义为热键？
  • 如何将按键或鼠标按钮重映射成其他键？
  • 如何将热键或热字符串设置为在特定程序下专用？换句话说，我想让特定按键执行它原来的功能，在指定的窗口激活时除外。
  • 如何让前置按键执行它原有的功能，而不是什么也不做？
  • 如何修改或者禁用 Windows 内置的快捷键，比如 Win+U (辅助工具管理器) 和 Win+R (运行)？
  • 我的数字小键盘上有个特殊的 000 键，能否将其设为热键？

语法

何时才能在命令和它们的参数中使用引号？

双引号(")仅在表达式中有特殊的含义。在所有其它的地方，它们就像普通的字符一样被原义地对待。不过，当脚本启动一个程序或文档时，操作系统通常需要用引号把带空格的命令行参数括起来，比如此例：Run, Notepad.exe "C:\My Documents\Address List.txt"

何时需要将变量名称装入百分号？

除了以下用粗体表示的情况外，总是用百分号将变量名括起来的：

1) 在参数里的输入或输出变量：StringLen, OutputVar, InputVar
2) 在赋值表达式的左侧：Var = 123abc
3) 在传统的(非表达式) if 语句的左侧：If Var1 < %Var2%
4) 在表达式的任意位置。例如：
If (Var1 <> Var2)
Var1 := Var2 + 100

何时才应该将百分号和逗号转义？

原义的百分号必须通过在它们前面加重音符/反引号来转义。例如：MsgBox The current percentage is 25`%. 原义的逗号也必须转义 (`,)，除了用在 MsgBox 或任何命令的最后一个参数里时(这些情况下允许使用重音符，但不是必须的)。

当在表达式中，逗号或百分号被双引号括起时，允许使用重音符，但不是必须的。例如：Var := "15%"

常见任务

为什么我脚本中的某些行总是无法执行？

任何想在脚本启动时立即执行的行都应该出现在脚本的顶部，要在首个 hotkey, hotstring 或 Return 之前。详见自动执行部分。

而且，一个有多行要执行的热键，必须将它的首行列在热键的下面，而不是同一行。例如：

#space:: ; Win+空格
Run Notepad
WinWaitActive 无标题 - 记事本
WinMaximize
return

为什么 Run 命令不能启动我的游戏或程序？

有些程序需要在它们自己的目录下运行(如果不能确定时，通常最好这样做)。例如：
Run, %A_ProgramFiles%\Some Application\App.exe, %A_ProgramFiles%\Some Application

怎样获取命令行操作的输出？

测试显示，由于文件缓存的存在，对于较少量的输出，一个临时文件将生成得非常快。实际上，如果文件在使用后被立即删除，通常它并没有被真正地写到磁盘上。例如：

RunWait %comspec% /c dir > C:\My Temp File.txt
FileRead, VarToContainContents, C:\My Temp File.txt
FileDelete, C:\My Temp File.txt

要避免使用临时文件的话(特别是如果输出较大时)，可以考虑使用 CmdRet。或者，也可用一个免费的小工具 cb.zip (4 KB)，它可以从一个命令或程序获取多达 512KB 的输出。文本被抓取到剪贴板，一个脚本可以通过剪贴板变量来访问该文本。例如：

RunWait %comspec% /c dir | cb.exe
MsgBox %clipboard%

怎样才能让一个脚本关闭、暂停或者挂起其它的脚本？

首先，这有个关闭另一个脚本的例子：

DetectHiddenWindows On ;允许探测到一个隐藏的脚本主窗口。
SetTitleMatchMode 2 ;避免了需要给下面的文件指定完全路径。
WinClose Script's File Name.ahk - AutoHotkey ;按脚本的名称更新这里的标题(区分大小写)。

要挂起或者暂停另一个脚本，将上面脚本的最后一行替换为下列命令中的一个：

PostMessage, 0x111, 65305,,, Script's File Name.ahk - AutoHotkey ;挂起。
PostMessage, 0x111, 65306,,, Script's File Name.ahk - AutoHotkey ;暂停。

怎样才能不退出脚本却可以停止重复的动作？

要通过按键来暂停或恢复整个脚本，只要像下例那样给 Pause 命令指定一个热键：

^!p::Pause ;按 Ctrl+Alt+P 来暂停。再按一次则恢复。

要想停止循环内的动作，参考下例，这是一个可以启用和停止它自身重复动作的热键。换言之，按一次热键将启动循环，再按同个热键将停止循环。

#MaxThreadsPerHotkey 3
#z:: ; Win+Z 热键 (可根据你的设置修改这个热键)。
#MaxThreadsPerHotkey 1
if KeepWinZRunning ;这意味着一个潜在的线程正在下面的循环中运行。
{
   KeepWinZRunning := false ;向那个线程的循环发出停止的信号。
   return ;结束此线程，以便下面的线程恢复并得知上一行所做的更改。
}
;否则：
KeepWinZRunning := true
Loop
{
   ;以下四行是你要重复的动作(可根据你的设置修改它们)：
   ToolTip, 再按一次 Win-Z 将停止本提示闪动。
   Sleep 1000
   ToolTip
   Sleep 1000
  ;但是不要修改下面剩下的内容。
   if not KeepWinZRunning ;用户通过再次按下 Win-Z 来对循环发出停止信号。
      break ;跳出此循环。
}
KeepWinZRunning := false ;重置，为下一次按热键做准备。
return

如何在玩游戏或平时 CPU 高负荷运行时改善性能？

当 CPU 高负荷运行时，如果脚本里的 Hotkey, Click 或者 Send 命令明显比平时慢，那么提高脚本的进程优先级可能会有所帮助。要这样做的话，请在接近脚本的顶部包含下面这行命令：
Process, Priority, , High

如何在任意编辑器中使用上下文相关的 AutoHotKey 命令帮助？

这个脚本由 Rajat 创建。

如何探测一个网页何时加载完毕？

用 Internet Explorer 的话，或许最可靠的方法就是使用 DllCall 和 COM，如 www.autohotkey.com/forum/topic19256.html 所示。做一个相关提示，地址栏和状态栏的内容是可以被获取的，如 www.autohotkey.com/forum/topic19255.html 所示。

较早的，不太可靠的方法：下面例子中的技术对用微软的 Internet Explorer 浏览大多数的页面来说都会有效。相似的技术用在其它浏览器上也可能会奏效。

Run, http://ahkbbs.cn
MouseMove, 0, 0 ;防止状态栏显示鼠标悬停处的链接来代替“完成”。
WinWait,AutoHotKey中文论坛
WinActivate
StatusBarWait, Done, 30
if ErrorLevel
   MsgBox 等待超时或者窗口被关闭。
else
   MsgBox 页面加载完毕。

怎样操作或比较日期和时间？

EnvAdd 命令可以将 YYYYMMDDHH24MISS 格式的时间字符串加上或减去一些天数、小时、分钟或者秒数。下面的例子将指定的时间减去了 7 天：
EnvAdd, VarContainingTimestamp, -7, days

要计算两个日期或时间之间的间隔，请看 EnvSub，它给出了一个示例。此外，内置变量 A_Now 包含了当前本地的时间。最后，还有一些内置的日期/时间变量，以及 FormatTime 命令，它可用来创建自定义的日期/时间字符串。

为什么在某些游戏中，Hotstrings, Send 以及 Click 命令不起作用？

有些游戏专门使用 DirectInput。作为副作用，它们可能忽略所有模拟的键击和鼠标点击。要绕弯解决的话，尝试下列方法之一(或联合使用)：

  • 通过：1) SendPlay 命令；2) 使用 SendMode Play 和/或 3) 热字符串选项 SP 来使用 SendPlay。
  • 增加 SetKeyDelay。例如：
    SetKeyDelay, 0, 50
    SetKeyDelay, 0, 50, Play
  • 尝试用 ControlSend，在其它 Send 模式失效的地方，它可能会有用。

如何控制 Winamp，即使是在它未激活时？

请看 Automating Winamp。

如何改变 MsgBox 的按钮名称？

这里有个示例。

热键、热字符串和重映射

如何让我的热键和热字符串在 PC 启动时自动生效？

在开始菜单中有个文件夹叫做启动。如果你将脚本的快捷方式放入此文件夹，那么每次你启动 PC 的时候脚本将自动运行。要创建快捷方式的话：

  1. 在资源管理器中选中脚本文件并按下 Control-C。
  2. 右键点击开始按钮并选择“浏览所有用户”。
  3. 定位到程序文件夹中的启动文件夹。
  4. 从菜单栏选择编辑 > 粘贴快捷方式。脚本的快捷方式就会出现在启动文件夹中。

我在把鼠标按键作为热键使用时遇到问题。有什么建议吗？

注意鼠标热键当前在 Windows 95/98/Me 上不可用。在其它操作系统上，鼠标左键和右键应该可以正常地被指定(例如，"#LButton::" 是 Win+左键的热键)。相似地，鼠标中键以及鼠标滚轮的转动应该也可以正常地被指定，除非鼠标驱动直接控制那些按键。

第四个按键(XButton1)和第五个按键(XButton2)也可以被指定，如果你的鼠标驱动允许它们的点击被系统看见。如果它们不可见，或者你的鼠标除你用到的 5 个按键外还有更多的按键，你可以尝试配置鼠标附带的软件(有时在开始菜单或控制面板中)，每当你按下这些键后就使其发送一个键击。这样的键击随后可在脚本中被定义为热键。例如，假设你配置第四个按键来发送 Control+F1，随后在脚本里你可以通过使用 ^F1:: 来间接地将那个按键作为热键来配置。

如果你有一个五个键的鼠标，它的第四个和第五个按键不能被系统看见，那么你可以尝试把你的鼠标驱动改变为操作系统内含的默认驱动。这里假设你特别的鼠标会有可用的驱动并且你可以容忍不使用由鼠标自定义软件所提供的特性。

如何将 Tab 和空格键定义为热键？

使用按键的名称 (Tab 和 Space) 而不是它们的字符。例如，#Space 是 Win+空格，^!Tab 是 Control+Alt+Tab。

如何将按键或鼠标按钮重映射成其他键？

这被写在重映射页面。

如何将热键或热字符串设置为在特定程序下专用？换句话说，我想让特定按键执行它原来的功能，在指定的窗口激活时除外。

首选的方法是 #IfWinActive。例如：

#IfWinActive, ahk_class Notepad
^a::MsgBox 在记事本激活时你按下了 Control-A。

Windows 95/98/Me：虽然上述方法奏效了，但是在记事本以外的窗口中按下 Control-A 将没有任何作用(甚至没有它本来的功能)。要绕弯解决这种情况，请用：

$^a::Send ^a ; 在 Windows 9x 上，该热键必须首先列出。前缀 & 允许热键“发送它本身”。
#IfWinActive, ahk_class Notepad
^a::MsgBox 在记事本激活时你按下了 Control-A。

如何让前置按键执行它原有的功能，而不是什么也不做？

参考下面这个使用 Numpad0 作为前置按键的示例：

Numpad0 & Numpad1::MsgBox, 在按住 Numpad0 的同时你按下了 Numpad1。

现在，要让 Numpad0 在它没被用来触发上述热键的时候发送一个真正的 Numpad0 键击，可增加下面的热键：

 $Numpad0::Send, {Numpad0}

需要用前缀 $ 阻止产生一个关于无限循环的警告对话框(因为热键“发送了它自己”)。此外，上述动作在释放按键的时候发生。

如何修改或者禁用 Windows 内置的快捷键，比如 Win+U (辅助工具管理器) 和 Win+R (运行)？

这里有些示例。

我的数字小键盘上有个特殊的 000 键，能否将其设为热键？

可以，但仅适用于 Windows NT, 2000, XP 及以上版本。这个示例脚本将 000 键设为等号键。你可以用你选择的行替换 "Send, =" 这行来改变动作。


Hotkeys (Mouse, Joystick and Keyboard Shortcuts)

热键(鼠标、操纵杆和键盘快捷键)

内容列表

  • 介绍和简单的例子
  • 热键前缀符号(修饰键)
  • 上下文相关的热键
  • 自定义组合键和其他特性
  • 鼠标滚轮热键
  • 热键技巧和备注

介绍和简单的例子

热键有时也被称作快捷键，因为它们能轻易地触发一个动作(例如启动一个程序或键盘宏)。在下面的例子中，热键 Win+N 被设定为启动记事本。pound sign [#] 表示 Windows 键，其被称作修饰键：

#n::
Run Notepad
return

在上面的最后一行，"return" 用来结束热键。不过，如果一个热键仅仅需要执行一行，那么这行可以列在双冒号的右边。换句话说，return 可以省略：

#n::Run Notepad

要对一个热键使用多个修饰键，把它们连续地列出来(顺序没有关系)。下面的例子用 ^!s 来表示 Control+Alt+S:

^!s::
Send Sincerely,{enter}John Smith ;这行发送键击到激活的(最前面的)窗口。
return

你可以使用下列的修饰键符号来定义热键：

符号 描述
# Win (Windows 标识键)
! Alt
^ Control
+ Shift
& 一个连接符可以用在任何两个键或者鼠标按键的中间，从而将它们组合成一个自定义热键。详见下面 。这样的热键在 Windows 95/98/Me 上被忽略(未被激活)。
< 使用成对按键中左边的按键。例如 <!a 和 !a 一样，只是仅有左边的 Alt 键会触发它。这个符号在 Windows 95/98/ME 上被忽略。
> 使用成对按键中右边的按键。这个符号在 Windows 95/98/ME 上被忽略。
<^>!

AltGr (alternate graving)(译注：传说此键出现在大部分欧洲键盘上)。如果你的键盘布局中有一个代替右 Alt 键的 AltGr 键，这一系列的符号一般能用来表示 AltGr (需要 Windows NT/2k/XP 或之后版本)。例如：

<^>!m::MsgBox 你按下了 AltGr+m.
<^<!m::MsgBox 你按下了 LeftControl+LeftAlt+m.

或者，要使 AltGr 它自己成为一个热键，使用下面的热键(不用像上面出现的任何一个热键):

LControl & RAlt::MsgBox 你按了 AltGr 它本身。
*

通配符：即使附加的修饰键被按住也激发热键。这常被用来协同重映射按键或按钮。例如：

*#c::Run Calc.exe ; Win+C, Shift+Win+C, Ctrl+Win+C 等全部会触发这个热键。
*ScrollLock::Run Notepad ;即使当修饰键按住时，按下 Scrolllock 键也将触发这个热键。

这个符号在 Windows 95/98/ME 上被忽略。
~

当激发热键时，按键的原来的功能不会被屏蔽(被操作系统隐藏)。在下面的两个例子中，用户的鼠标按钮点击将被发送到激活的窗口：

~RButton::MsgBox 你点击了鼠标右键。
~RButton & C::MsgBox 你在按住鼠标右键的同时按下了 C 键。

注意：1) 和其他前缀符号不同，波浪符前缀被允许在一个热键的某些变体上出现但在其他部分不存在；2) 那些代替 alt-tab的特殊热键永远忽略波浪符前缀；3) 波浪符前缀在 Windows 95/98/ME 上被忽略。
$

这符号通常仅仅在脚本使用 Send 命令发送包含了热键自身的按键时才有必要使用，否则这可能导致发送热键触发它自己。$ 前缀确切的特性变化取决于操作系统：

在 Windows NT4/2k/XP 或之后版本上：$ 前缀强制使用键盘钩子来执行这个热键，作为一个副作用它防止了 Send 命令触发热键。$ 前缀等效于在此热键定义的上面某处指定了 #UseHook。

在 Windows 95/98/Me 上：热键在它的线程执行期间被禁用，之后重新启用。作为一个副作用，如果 #MaxThreadsPerHotkey 设成高于 1，它也将表现得像被这个热键设为 1 一样。
UP

单词 UP 可以跟在一个热键名称后面来促使热键在松开按键时激发而不是在按下按键时。下面的例子将 LWin 重映射成 LControl:

*LWin::Send {LControl Down}
*LWin Up::Send {LControl Up}

"Up" 也可以和一般的热键一起使用比如在这个例子中： ^!r Up::MsgBox 你按下并松开了 Ctrl+Alt+R 。它也可以和 组合热键 一起用(例如 F1 & e Up::)

限制: 1) "Up" 不能和游戏杆按钮一起用；2) "Up" 需要 Windows NT4/2000/XP 或之后版本；3) 不和一个普通/按下的配对热键一起用的 "Up" 热键将完全接管那个热键从而防止它卡在按下的状态。唯一能防止这种情况发生的就是添加一个波浪符前缀 (例如 ~LControl up::)

作个相关的提示，和上面相似的一个技术是让一个热键成为一个前缀键。尽管热键会在松开时激发是个有利情况，但热键仅在你如果按住它的同时不去按其他任何键的时候才会激发。例如：

LControl & F1::return ;通过让左 control 键在 "&" 前面至少使用一次来把它变成一个前缀。
LControl::MsgBox 你在没有用 LControl 去修饰其他任何键的情况下松开了它。

(请看按键列表获取一个完整的键盘按键和鼠标/操纵杆按钮列表)

多个热键可以被垂直地堆放起来让它们执行同样的动作。例如：

^Numpad0::
^Numpad1::
MsgBox 按了 Control+Numpad0 或 Control+Numpad1 都会显示这个消息。
return

通过让热键不作任何动作可以在整个操作系统中禁用一个键或者组合键。下面的例子禁用了右边的 Windows 键：

RWin::return

上下文相关的热键

#IfWinActive/Exist 指令可以被用来让一个热键视激活或存在的窗口的类型而执行一个不同的动作(或根本无动静)。例如：

#IfWinActive, ahk_class Notepad
^a::MsgBox 你在记事本激活时按了 Ctrl-A 。在其他任何窗口按 Ctrl-A 将只传递 Ctrl-A 键击到那个窗口。
#c::MsgBox 你在记事本激活时按了 Win-C 。
#IfWinActive
#c::MsgBox 你在除了记事本外的任意窗口激活时按了 Win-C 。

自定义组合键和其他特性 [Windows NT/2000/XP 或之后版本]

你可以通过在两个键之间使用 " & " 来自定义一个组合键(除了操纵杆按钮)。在下面的例子中，你能够按住 Numpad0 之后再按第二个键来触发热键：

Numpad0 & Numpad1::MsgBox 你在按住 Numpad0 的同时按下了 Numpad1 。
Numpad0 & Numpad2::Run Notepad

在上面的例子中，Numpad0 变成一个前缀键；而且也导致了通过它去按 Numpad0 它自己的时候失去了它原本/天生的功能。要避免这种情况，脚本可以像下面中的一种那样来配置 Numpad0 去执行一个新的动作：

Numpad0::WinMaximize A ;最大化激活的/前台的窗口。
Numpad0::Send {Numpad0} ;让 Numpad0 松开后去再生一个 Numpad0 键击。请见下面的内容。

上面的热键之一的存在都促使 Numpad0 松开后去执行指示的动作，但仅在 Numpad0 被按住时如果你没有去按其他任何键的情况下。

Numlock, Capslock 和 Scrolllock: 这些按键可以被强制变成 "AlwaysOn" 或 "AlwaysOff"。例如：SetNumlockState AlwaysOn

覆写 Explorer 的热键: Windows 的内置热键例如 Win-E (#e) 和 Win-R (#r) 可以通过在脚本里将它们指定为一个动作来简单地单独覆写。详见覆写页面。

替换 Alt-Tab: 热键能通过 alt-tab 提供一种交替的效果。例如，下面的两个热键可让你用右手来 alt-tab ：

RControl & RShift::AltTab ;按住右-control 然后反复地按右-shift 来向前移动。
RControl & Enter::ShiftAltTab ;甚至不需要释放右-control，直接按 Enter 键来反向移动。

详见 Alt-Tab。

鼠标滚轮热键 [Windows NT/2000/XP 或之后版本]

通过键名 WheelDown 和 WheelUp 可以支持在调节鼠标滚轮的时候激发热键。WheelLeft 和 WheelRight 需要 v1.0.48+ 以上支持, 但是在 Windows Vista 或以上没影响. 以下是 鼠标滚轮热键 的例子:

MButton & WheelDown::MsgBox 你在按住鼠标中键的时候向后滚动了滚轮。
^!WheelUp::MsgBox 你在按住 Control+Alt 的时候向前旋转了滚轮。

在 v1.0.43.03+ ，内置变量 A_EventInfo 包含了通过调节滚轮得到的触点次数，它一般情况是 1。然而，在下面的情况下， A_EventInfo 可能大于或小于1：如果鼠标硬件报告的距离不足一个刻痕(你滚动滚轮感觉到的一下)，A_EventInfo 可能包含 0；当滚轮被快速地滚动(取决于鼠标类型)，A_EventInfo 可能大于 1。例子用法：~WheelDown::ToolTip %A_EventInfo%

鼠标滚轮的一些最有用的热键涉及交替窗口的文本滚动模式。例如，下面的一对热键在你按住左边的 Control 键并调节滚轮时用水平地滚动代替了垂直地滚动：

~LControl & WheelUp:: ;向左滚动。
ControlGetFocus, fcontrol, A
Loop 2 ;<-- 调大这个数值来快速滚动。
   SendMessage, 0x114, 0, 0, %fcontrol%, A ; 0x114 是 WM_HSCROLL，它之后的 0 是 SB_LINELEFT。
return

~LControl & WheelDown:: ;向右滚动。
ControlGetFocus, fcontrol, A
Loop 2 ;<-- 调大这个数值来快速滚动。
   SendMessage, 0x114, 1, 0, %fcontrol%, A ; 0x114 是 WM_HSCROLL，它之后的 1 是 SB_LINERIGHT。
return

最后提下，由于鼠标滚轮热键只产生按下事件(从来没有弹起事件)，它们不能被用作弹起的按键热键。

热键技巧和备注

依靠 Numlock 的状态，每个数字键区的按键能启动两种不同的热键子程序。或者，一个数字键区按键能不管 Numlock 的状态而启动相同的子程序。例如：

NumpadEnd::
Numpad1::
MsgBox, 不管 Numlock 是否打开，这个热键都将被启用。
return

如果波浪操作符 (~) 和一个前缀键即使一起使用了一次，前缀键也总是会被发送到激活的窗口。例如，下面两个热键中，激活的窗口会接收到所有的右键点击即使只有一个热键定义包含了波浪符：

~RButton & LButton::MsgBox 你在按住鼠标右键的同时按了鼠标左键。
RButton & WheelUp::MsgBox 你在按住鼠标右键的同时向前推动了滚轮。

Suspend 命令能临时禁用所有热键除了你要免除的那些外。要得到更多的选择性，使用 #IfWinActive/Exist。

通过使用 Hotkey 命令，热键能在脚本运行过程中被动态地创建。Hotkey 命令也能单独地修改、禁用或启用已存在的脚本热键。

操纵杆热键目前不支持修饰键前缀例如 ^ (Control) 和 # (Win)。不过，你可以使用 GetKeyState 模仿下面例子中展示的这个效果：

Joy2::
if not GetKeyState("Control") ;左边或右边的 Control 都没有按下。
   return ;也就是什么也不做。
MsgBox 你在按住 Control 键的同时按了首个操纵杆的第二个按钮。
return

当一个热键在继续前要等它的修饰键被松开的时候可能需要一些时间。参考下面的例子：

^!s::Send {Delete}

按下 Control-Alt-S 会导致系统表现得像你按了 Control-Alt-Delete 一样(由于系统的侵略性的 Ctrl-Alt-Delete 探测)。要绕弯解决这种情况，使用 KeyWait 来等待那些键被松开；例如：

^!s::
KeyWait Control
KeyWait Alt
Send {Delete}
return

一个热键标记能被用作 Gosub 或 Goto 要跳转的目标。例如：Gosub ^!s

一个热键常用来开始和结束一个重复的动作，比如一系列的键击或鼠标点击。要得到这样一个例子，请看这个 FAQ 主题。

最后，每个脚本都是类似的多线程，其允许在前一个热键子程序还在运行时，一个新的热键也能被启动。例如，即使当一个 MsgBox 被当前热键调用显示时，新的热键也能被启动。

Alt-Tab 热键

每个 Alt-Tab 热键必须是一个双键组合，其往往通过连接符 (&) 实现。在下面的例子中，你将按住右边的 Alt 键并按下 J 或 K 来浏览 alt-tab 菜单：

RAlt & j::AltTab
RAlt & k::ShiftAltTab

AltTab 和 ShiftAltTab 是两个特殊的命令，它们仅当和热键使用在同一行时才被识别。这里有一个完整的列表：

AltTab: 如果 alt-tab 菜单可见，在菜单中前移。否则，显示菜单(仅在热键是一个用 "&" 连接的双键组合才行；否则，它什么也不做)。

ShiftAltTab: 和上面的一样，除了在菜单中是向后移动。

AltTabAndMenu: 如果 alt-tab 菜单可见，在菜单中前移。否则，显示菜单。

AltTabMenuDismiss: 关闭 Alt-tab 菜单。

要阐明上面的命令，鼠标滚轮可以来整个代替 Alt-tab。让下面的热键生效时，点击鼠标中键显示菜单并且调节滚轮可在它里面来导航：

MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab

要取消一个热键调用的 Alt-tab 菜单而不激活选中的窗口，使用一个像下面那样的热键。它可能需要依赖后面的条件来调整：1) 借助原本显示的 alt-tab 菜单；2) 脚本是否安装了键盘钩子。

LCtrl & CapsLock::AltTab
!MButton:: ;鼠标中键。前缀 ! 使它在按住 Alt 键时激发(如果 alt-tab 菜单可见，Alt 键就是按住的)。
IfWinExist ahk_class #32771 ;指示 alt-tab 菜单当前是否出现在屏幕上。
   Send !{Escape}{Alt up}
return

目前，所有特殊的 Alt-tab 动作必须像上面的例子一样直接指定到一个热键(也就是它们不能像命令那样使用)。另外，alt-tab 菜单的存在能通过 IfWinExist ahk_class #32771 探测到。

自定义 alt-tab 动作也能通过热键来创建。在下面的例子中，你将按 F1 来显示菜单并原先在里面前移。然后你将按 F2 来激活选中的窗口(或按 Escape 来取消)：

*F1::Send {Alt down}{tab} ;在这里需要星号。译注：因为按了后 Alt 处于 Down 状态，再次激发热键只能靠星号匹配 Alt 这种修饰键。
!F2::Send {Alt up} ;松开 Alt 键激活选中的窗口。
~*Escape::
IfWinExist ahk_class #32771
   Send {Escape}{Alt up} ;取消菜单而不激活选中的窗口。
return


Hotstrings and Auto-replace (similar to AutoText and AutoCorrect)

热字符串和自动替换

注意：热字符串需要 Windows NT/2000/XP 或更高版本的支持。（译注：关于中文支持，请看本页末尾部分。）

介绍和简单的例子

虽然热字符串主要被用来在你输入它们的时候扩展缩写(自动替换)，但它们也可以用来启动任何脚本化的动作。在这方面它们与热键很相似，只不过它们一般由多个字符组成(也就是字符串)。

要定义一个热字符串，只需要把触发缩写放在两个冒号之间即可，像这样：

::btw::by the way

上例中，当你输入缩写 btw 时，就会被自动地替换成 "by the way"(不过默认情况下，你必须在输入 btw 之后再输入一个结束字符，比如一个空格、句点或者回车)。

因为输入的文本被自动地清除并被替换为第二个双冒号后面指定的字符串，所以上面的 "by the way" 例子被称为一个自动替换的热字符串。相比起来，热字符串也能被定义成执行任何自定义的动作，如下所示。注意命令必须在热字符串的下面：

::btw::
MsgBox 你输入了 "btw"。
return

:*:]d::  ;这个热字符串通过下面的命令，把 "]d" 替换成了当前的日期和时间。
FormatTime, CurrentDateTime,, M/d/yyyy h:mm tt  ;看起来将是 9/1/2005 3:53 PM 这样
SendInput %CurrentDateTime% ;译注：输出的字符串末尾的 AM 或 PM 在中文操作系统下会用“上午”或“下午”来代替。但这两个中文字符会输出为乱码。关于中文支持，请看文末。
return

尽管上面的两个例子不是自动替换的热字符串，但默认情况下，你输入的缩写也将被清除。这是通过自动地退格来实现的，但可以通过 b0 选项来禁用。

结束字符

除非星号选项已经生效，要不然你必须在一个热字符串的缩写后面输入一个结束字符才能触发它。结束字符初始由下列字符组成：-()[]{}':;"/\,.?!`n `t (注意 `n 是回车，`t 是 Tab，在 `n 和 `t 之间有个空格)。可以通过编辑下例来更改这组字符，这将为所有的热字符串设置结束字符，而不只是影响此指令下面的热字符串：

#Hotstring EndChars -()[]{}:;'"/\,.?!`n `t

选项

可以使用以下两种方式改变热字符串的默认行为：

  1. #Hotstring 指令，可以影响脚本中它那个点下面的所有热字符串。下例将使 C 和 R 选项生效：
    #Hotstring c r
  2. 把选项放在第一个双冒号之间。下例使 C 和 * 选项在当前热字符串中生效：
    :c*:j@::john@somedomain.com ;区分大小写并且“不需要使用结束字符”。

下面列出了每个选项的描述。当用上面的方法指定多个选项时，可以在它们之间选择性地包含空格。（译注：我会将下列字母选项对应的英文关键词用绿色标注，以帮助记忆！）

* (星号): 不需要结束字符(比如空格、句点或回车)来触发热字符串。例如：

:*:j@::jsmith@somedomain.com

上例中，当你一输入 @ 字符时，它就会送出它的替换字串。如果在 #Hotstring 指令中使用了它，可以用 *0 来关闭这个选项。

? (问号): 就算热字符串是在另一个词里，也可以被触发；就是说，在字符串被混排前立即输入字符。例如，如果 :?:al::airline 是一个热字符串，输入 "practial " 时将会产生 "practiairline "（译注：热字符串的缩写必须在另一个词的结尾）。可用 ?0 关闭此选项。

B0 (B 后跟一个零。Backspace 0): 不使用自动退格来清除你输入的缩写。之后可以使用一个 B 再启用之前被关掉的退格功能。脚本也可以通过 {bs 5} 发送 5 个退格键来自行退格。类似地，能通过 {left 5} 发送左方向键击。例如，下面的热字符串制造出 <em></em> 并把光标向左移动 5 个位置(因此它处在标签之间了)：

:*b0:<em>::</em>{left 5}

C (Case sensitive): 区分大小写：当你输入缩写的时候，它必须和脚本中定义的大小写严格匹配。可用 C0 来关闭大小写敏感性。

C1: 不遵守输入的大小写。使用此选项可以让自动替换热字符串不区分大小写并防止热字符串遵守你实际输入的字符的大小写。如果你输入了全部大写的缩写，遵守大小写的热字符串(这是默认的)将用全部大写的方式制造它们的替换文本。如果你只输入了首个大写的字母，替换字串的首个字母(如果是字母的话)也将是大写的。如果你以任何其它方式输入大小写，替换字串将只严格地按脚本定义的那样发送。当使用 #Hotstring 指令时，C0 可被用来关闭此选项，这能使热字符串重新遵守大小写。

Kn (Key-delay n): 按键延迟：这个罕用的选项用来设置自动退格或者自动替换产生的键击之间的延迟。给 n 设定新的延迟；例如，指定 k10 将产生 10 毫秒的延迟，k-1 则没有延迟。本选项实际的表现取决于当前生效的发送模式是哪个：

  • SI (SendInput): 因为这种模式是没有延迟的，所以按键延迟将被忽略。在 SendInput 模式无效的情况下例外，这时热字符串转而采用到下面的 SendPlay 模式(它会遵从按键延迟)。
  • SP (SendPlay): 默认延迟为零，与 SendPlay 模式下的 -1(无延迟) 相同。这种模式下，延迟实际上是一个按键时长，而非键击之间的延迟。
  • SE (SendEvent): 默认延迟为零。多数情况下建议值为零，因为它快速并且与其它进程配合得较好(由于内部会做一个 Sleep 0)。指定 k-1 彻底禁止延迟，如果你的 CPU 经常高负载运作，让自动替换执行的更快这样会有所帮助。当设为 -1 时，脚本的进程优先级就成为击键发送速度的重要因素。要提高脚本的优先级，请用 Process, Priority,, High。

O (Omit): 在生成替换时，省略掉自动替换热字符串的结束字符。这在你仍需要一个结束字符来明确一个热字符串，但实际上又不想让结束字符显示在屏幕上的时候会很有用。例如，假设 :o:ar::aristocrat 是个热字符串，在输入 "ar" 后跟空格时将会生成末尾不带空格的 "aristocrat"，这就使你在输入一个单词的复数或所有格时，不用再退格了。可用 O0 (字母 O 后跟一个零)关闭此选项。

Pn (Priority n): 热字符串的优先级(比如 P1)。这个罕用的选项对自动替换热字符串无效。

R (Raw): 按照原样发送替换文本；就是说，完全按它显示的那样，而不将 {Enter} 转换为一个 ENTER 键击，也不把 ^c 转换为 Control-C，等等。对有连续部分的热字符串，此选项会自动生效。可用 R0 关闭此选项。

SI 或 SP 或 SE [1.0.43 及之后版本]: 设定自动替换热字符串发送它们键击的方法。这些选项互斥：每次仅有一个会生效。每个选项描述如下：

  • SI 代表 SendInput，由于优越的速度和可靠性，它在 1.0.43 及之后版本成为默认项。另一个好处是和下面的 SendPlay 一样，SendInput 在热字符串自动替换文本时，会延迟你输入的任何内容。这能防止替换文本被你的键击穿插。当 SendInput 无效时，热字符串将自动使用 SendPlay 来代替。
  • SP 代表 SendPlay，它能使热字符串用在很多类型的游戏中。
  • SE 代表 SendEvent，在 1.0.43 之前的版本中它是默认项。

Z: 这个罕用的选项将在热字符串每次触发后重置热字符串识别器。换句话说，脚本将开始等待一个全新的热字符串，不考虑你之前输入的任何内容。这能避免不必要的热字符串触发。要理解它，请看下面的热字符串：

:b0*?:11::
SendInput xx
return

因为上面没有 Z 选项，在输入 111(三个连续的 1)时将会触发热字符串两次，因为中间的 1 既是首次触发的末尾字符，又是第二次触发的开头字符。通过在 b0 前面添加字母 Z，你就要输入四个 1 来代替三个 1，从而触发两次热字符串。可用 Z0 关闭此选项。

超长替换

使用一个连续部分可以让产生大量替换文本的热字符串变得更具可读性和可维护性。例如：

::text1:: ;译注：由于不能直接发送中文字符，故下面三行英文保留，只在每行下面通过注解形式翻译。
(
Any text between the top and bottom parentheses is treated literally, including commas and percent signs.
;在顶部和底部圆括号之间的任何文本都作为原义来对待，包括逗号和百分号。
By default, the hard carriage return (Enter) between the previous line and this one is also preserved.
;默认，上一行与本行之间的硬回车(Enter)也将被保留。
    By default, the indentation (tab) to the left of this line is preserved.
    ;默认，本行左侧的缩进(tab)将被保留。

See continuation section for how to change these default behaviors.
;如何修改这些默认的特性，请看连续部分。
)

连续部分的出现也会使热字符串默认使用 raw 模式。要改变这种特殊默认模式的唯一方法，就是给每个使用连续部分的热字符串指定 r0 选项(比如 :r0:text1::)。

上下文相关的热字符串

#IfWinActive/Exist 指令可以使选定的热字符串产生上下文相关性。根据激活或存在的窗口类型，这样的热字符串会发送不同的替换文本，执行不同的操作或者干脆无效。例如：

#IfWinActive ahk_class Notepad
::btw::This replacement text will appear only in Notepad. ;这行替换文本将只出现在记事本中。
#IfWinActive
::btw::This replacement text appears in windows other than Notepad. ;这行替换文本将出现在任何不是记事本的窗口中。

自动校正

下面这个脚本使用了热字符串来即时校正大约 4700 个常见的英文拼写错误。它还包括一个 Win+H 热键，可以方便地添加更多拼写错误：

下载: AutoCorrect.ahk (127 KB)

作者: Jim Biancolo 以及维基百科的常见拼写错误列表

备注

当前在替换文本中不支持 %MyVar% 这样的变量引用。解决方法是，不要让这样的热字符串自动替换，而是在缩写下面使用 SendInput 命令，和一个仅包含单词 Return 的行。

要在替换文本后发送一个额外的空格或 tab，可以把它们放在替换文本后面，但是要以一个重音符/反引号(`)作为结尾字符。例如：

:*:btw::By the way `

鼠标左键或右键的任何点击都将重置热字符串的识别器。换句话说，脚本将开始等待一个全新的热字符串，不考虑你之前输入的任何内容(如果不想这样，可以在脚本的任意位置指定一行 #Hotstring NoMouse)。由于每次点击通常都会移动文本插入点(光标)或者把键盘的焦点置于一个新的控件/区域。所以这种情况下，通常需要：1) 触发热字符串，即使它没有问号选项；2) 防止你在意外地鼠标点击后输入的内容与你之前输入的那些形成一个有效的缩写从而触发。因此这种“点击后重新识别”的特性是默认的。

内置变量 A_EndChar 里包含了你用来触发最近的非自动替换型热字符串的结束字符。如果不需要使用结束字符(由于使用了 * 选项)，它将为空。在让热字符串使用 Send 命令或者那些会根据你输入的结束字符而变化的行为的时候，A_EndChar 变量将很有用。要发送结束字符它自身，可用 SendRaw %A_EndChar% (之所以使用 SendRaw，是因为普通的 Send 命令不能正确发送比如 !{} 这些字符)。

虽然在热字符串定义中的逗号、百分号和单冒号无需转义，但那些跟在空格或 tab 后面的反引号和分号是需要的。请看转义顺序中的完整列表。

虽然在自动替换型文本中支持 Send 命令的特殊字符比如 {Enter} (如果未使用 raw 选项的话)，但热字符串的缩写它们自身却不使用。而是为 ENTER 键指定 `n，为 TAB 指定 `t (或一个原义的 tab，请看转义顺序中的完整列表)。例如：当你输入 "ab" 后跟一个 tab 时，将触发热字符串 :*:ab`t::。

在热字符串定义中会原义地对待空格和 tab。例如，下面两行的结果是不同的：
::btw::by the way
::btw:: by the way

每个热字符串缩写的长度都不能超过 40 个字符。如果超出此长度，程序将会弹出警告对话框。而当发送模式是默认的 SendInput 时，热字符串的替换文本长度限制约为 5000 个字符。这个限制可以通过切换到其它发送模式而增加到 16,383 个字符。此外，在热字符串内使用 SendPlay %MyVariable% 则可以发送一个不限制数量的文本。

热字符串的定义顺序决定了它们彼此的优先级。换句话说，如果有多个热字符串可以匹配你输入的内容，那么只有脚本中首个列出的热字符串会起作用。相关主题：上下文相关的热字符串。

为了识别热字符串，你输入的所有退格都会被算进来。不过在编辑器中使用方向键, PageUp, PageDown, Home 以及 End 来导航的话，会导致热字符串识别过程被重置。换句话说，它会开始等待一个全新的热字符串。

即使激活窗口忽略你的键击时，也能输入热字符串。换句话说，就算触发的缩写不可见，热字符串也仍然会被触发。另外，你依然可以使用退格键来撤销最近输入的键击(尽管你看不见效果)。

将首对冒号(以及其中的任何选项符号)包含在热字符串名称的前面，可以 Gosub 或 Goto 到一个热字符串标签。例如：Gosub ::xyz。不过，跳转到一个单行(自动替换型)热字符串的话，将什么也不会做，只会执行一个 return。

虽然不会监视热字符串，在一个不可见的 Input 命令过程中也不会被触发，但是可见的 Input 却会触发它们。

任何 AutoHotkey 脚本产生的键击永远都不会触发热字符串。这避免了热字符串彼此反复触发而进入无限循环的可能性。

对于某些特定的目的，Input 命令会比热字符串更灵活。比如，它允许你的键击在激活窗口中不可见(比如一个游戏)。它还支持非字符型的结束按键，比如 Escape。

任何包含热字符串的脚本都会自动使用 keyboard hook 。

在下列情况中热字符串与热键具有相同的特性：

  • 它们都会受到 Suspend 命令的影响。
  • 它们都遵守 #MaxThreads 和 #MaxThreadsPerHotkey (但不遵守 #MaxThreadsBuffer)的设置。
  • 包含热字符串的脚本将会自动地持续运行。
  • 非自动替换型热字符串在启动时将会创建一个新的线程。另外，它们会更新内置的热键变量，比如 A_ThisHotkey。

已知限制：在 Java 应用程序的某些系统中，热字符串可能会干扰用户键入 diacritical 字母(通过 dead 键)。解决方法是，可以临时打开 Suspend (这会禁用所有的热字符串)。

热字符串助手

Andreas Borutta 推荐了下面的脚本，如果你是一个重度热字符串用户，它将会很有用。通过按 Win+H (或你自定义的其它热键)，当前选中的文本可以被转化成一个热字符串。例如，假设你在一个字处理软件中选择了 "by the way"，那么按下 Win+H 将会提示你输入一个缩写(比如 btw)，之后就会在脚本中添加新的热字符串。随后它会重载脚本来激活热字符串。

#h::  ; Win+H 热键
;获取当前选中的文本。使用剪贴板代替 "ControlGet Selected"
;是因为它能在更多种类的编辑器(也就是字处理软件)中起作用。
;当前剪贴板中的内容将被保存，以便之后恢复。尽管只能恢复纯文本，但总比没有的好：
AutoTrim Off  ;保留剪贴板中首尾的空白字符。
ClipboardOld = %ClipboardAll%
Clipboard =  ;为检验正确，需要清空。
Send ^c
ClipWait 1
if ErrorLevel  ; ClipWait 超时
    return
;将回车换行和/或换行符替换为 `n 以便使用在一个 "send-raw" 的热字符串中：
;对任何在 raw 模式下可能出问题的其他字符应用同样的操作：
StringReplace, Hotstring, Clipboard, ``, ````, All  ;为避免与下列替换冲突，先作这个替换。
StringReplace, Hotstring, Hotstring, `r`n, ``r, All  ;在微软 Word 等等软件中 `r 比 `n 表现得更好。
StringReplace, Hotstring, Hotstring, `n, ``r, All
StringReplace, Hotstring, Hotstring, %A_Tab%, ``t, All
StringReplace, Hotstring, Hotstring, `;, ```;, All
Clipboard = %ClipboardOld%  ;恢复记事本之前的内容
;这将把输入对话框中的光标移动到更人性化的位置：
SetTimer, MoveCaret, 10
;显示提供了缺省热字符串的输入对话框：
InputBox, Hotstring, 新建热字符串, 在光标处输入你的缩写。需要的话，你也可以编辑替换文本。`n`n 示例::R:btw`::by the way,,,,,,,, :R:`::%Hotstring%
if ErrorLevel  ;用户选择了取消
    return
IfInString, Hotstring, :R`:::
{
    MsgBox 你没有输入缩写。热字符串不会被添加。
    return
}
;否则，添加热字符串并重新加载脚本：
FileAppend, `n%Hotstring%, %A_ScriptFullPath%  ;在字符串开头放一个 `n 以防文件在它的末尾没有空行。
Reload
Sleep 200 ;如果重新加载成功，那么在 Sleep 期间就会关闭这个实例，这样就永远不会运行到下一行。
MsgBox, 4,, 刚刚添加的热字符串格式化不正确。你要打开脚本编辑么？注意，有问题的热字符串在脚本的最后一行。
IfMsgBox, Yes, Edit
return

MoveCaret:
IfWinNotActive, New Hotstring
    return
;否则，将输入对话框中的光标移动到用户输入缩写的位置。
Send {Home}{Right 3}
SetTimer, MoveCaret, Off
return

译注：关于中文支持

注意：这部分内容是译者自己添加的。

由于 AutoHotkey 不能直接发送中文字符，所以可以尝试将 Send 命令和其他方法组合使用，从而实现发送中文的目的。

热字符串支持缩写触发命令，所以只要把下面这一系列的命令写在缩写下面就可以实现热字符串发送中文了。

方法 1：把要发送的中文赋值给剪贴板，然后发送一个粘贴动作即可自动转换字符编码：

ClipboardOld = %ClipboardAll% ;保留剪贴板中原来的内容
Clipboard = 需要发送的中文内容
Send ^v
Clipboard = %ClipboardOld%  ;恢复剪贴板初始的内容
Return

方法 2：Yonken 在他的博客里有写过如何在脚本中使用 Send 发送中文。他给出的方案不依赖剪贴板，直接转换字符编码，最后通过函数的形式来调用。感兴趣的朋友可以去看看。不过转换的速度会相对慢一点。

注意，热字符串的缩写还不能使用中文，因为中文输入法输出的字符还不能被热字符串的识别器识别，解决方法未知。


Remapping Keys and Buttons

鼠标与键盘的映射

介绍

本部分介绍的方法不适用于 Windows 95/98/Me 环境下的鼠标键盘映射,也不适用于对游戏操作杆进行映射。这两部分的映射方法，可参看下面的链接：

  • Windows 9x remapping
  • Joystick remapping

限制： 其实可以直接通过修改 Windows 注册表来进行鼠标键盘映射，而且在多数情况下，这要比用 AutoHotKey 来映射鼠标键盘更直接和高效。当然两种方法还是各有其优缺点的，可参看 registry remapping 。

映射键盘和鼠标

映射鼠标键盘的语法为： OriginKey::DestinationKey 。例如，包含下面代码的脚本可将 'a' 键映射成 'b' 键(点击 'a' 键将产生点击 'b' 键的效果)。

a::b

上述代码不会改变 'b' 键，按下 'b' 键时仍然发送 'b' 键被按下的消息。当然，你也可以对 'b' 键进行映射(如下所示)。

a::b
b::a

上述的代码中使用的都是小写字母，但也会同时映射相应的大些字母(因此，按下 'a' 则输出 'b' ，按下 'A' 则输出 'B' )。如果 "::" 右边用大写字母，那么就只输出大写字母。例如，如果用下面的代码，不管你输入 'a' 还是 'A' 都只会输出 'B' (但是要保证 Capslock 没有锁住，否则输出会变成 'b' )：

a::B

映射鼠标：映射鼠标，方法一样。例如：

MButton::Shift | 将鼠标中键映射成 Shift 键。(注意，这里是指按下鼠标中键而不是拨动鼠标滚轮)
XButton1::LButton | 将鼠标的第四个键映射成鼠标左键。
RAlt::RButton | 将右 Alt 键映射成鼠标右键。

其他常用(有用)的映射：

Capslock::Ctrl | 将 Capslock 键映射成 Ctrl 键。但这样会丢失 Capslock 键，可以添加映射 +Capslock::Capslock 。(这样，当你按下 Shift 键再点击 Capslock 就可以开关大写锁定了)
XButton2::^LButton | 将鼠标的第五个键(XButton2)映射成 Control 加鼠标左键。
RAlt::AppsKey | 将右 Alt 键映射成 Apps 键(就是打开右键菜单的键)。
RCtrl::RWin | 将右 Ctrl 键映射成右 Win 键。
Ctrl::Alt | 将左右 Ctrl 键映射成 Alt 键。但是这样会产生一些问题，参看 alt-tab issues 。
^x::^c | 将 Ctrl-X 映射成 Ctrl-C 。同时会附带将 Ctrl-Alt-X 映射成 Ctrl-Alt-C 的效果。
RWin::Return | 禁用右 Win 键(在 "::" 右边返回 return 就可以禁用左边的键)。

你可以试验上面所有的例子。方法是将代码拷贝到一个文本文件中(如 "Remap.ahk" )，然后运行该文件。

可以在 Key List 查看键盘键和鼠标键的完整列表。

注意

使用 #IfWinActive/Exist 命令可以让映射仅在指定的窗口内生效。例如：

#IfWinActive ahk_class Notepad
a::b  ; 将 'a' 键映射成 'b' 键，但仅在记事本窗口内有效。
#IfWinActive  ; 这个命令后面的映射和热键将会在所有的窗口内都有效。

任何键盘和鼠标的映射都有如下性质：

  • 如果按下修饰键(就是 Ctrl 、Alt 、Shift 这些键)再按原始键(origin key)，会将修饰键的效果带入目标键(destination key)。例如映射 b::a ，按下 Ctrl-B 也会产生 Ctrl-A 的效果。
  • 通常 Capslock 对映射键和普通键的影响相同。
  • 持续按住原始键(origin key)，目标键(destination key)也处于持续按下的状态。(一些游戏不支持键的映射，在这些游戏中所有的映射都不起作用)
  • 被映射的键(原始键)被按下时也会自动重复发送击键消息。(将键盘键映射成鼠标键时除外)

被映射的键(原始键)可以触发含有目标键的普通热键，但不能触发含有目标键的鼠标热键(mouse hotkey)和 钩子热键 (可以使用 ListHotkeys 命令查看那些热键被“勾住”了)。例如，如果映射 a::b 有效，那么按下 Ctrl-Alt-A 会触发 ^!b 热键(只要 ^!b 不是一个钩子热键)。如果 ^!b 是一个钩子热键，而你又希望按下 Ctrl-Alt-A 能够触发它，你可以将 ^!a 定义成和 ^!b 一样的热键，这样按下 Ctrl-Alt-A 和按下 Ctrl-Alt-B 会执行相同的动作，从而达到“触发” ^!b 热键的效果。如下例所示：

a::b
^!a::
^!b::
ToolTip You pressed %A_ThisHotkey%.
return

如果在自动运行区(auto-execute section，就是从脚本的第一行到出现第一个 Return, Exit, hotkey/hotstring label 之前的区域)使用了 SendMode ，所有的映射将会受其影响。另外，由于映射使用的是 Send {Blind} 模式，而 SendPlay mode 不完全支持 {Blind} 模式，一些映射(尤其是包含 Control, Shift, Alt, Win 键的映射)在 SendPlay mode 下会出现一些不正常的现象。所以当脚本中有映射时，应避免在自动运行区使用 SendPlay 模式；然后在脚本其他需要的地方使用 SendPlay 命令来代替 Send 命令。或者，另一种解决这个问题的方法是，将你的脚本用相应的热键代替(下面有详细的介绍)，这些热键使用 SendEvent 代替 Send 命令。

当脚本加载时，其中的每一个映射会被翻译成一对 热键(hotkeys) 。例如，映射 a::b 会被翻译成如下两个热键：

*a::
SetKeyDelay -1  ; 如果目标键是鼠标键，则使用 SetMouseDelay 命令。
Send {Blind}{b DownTemp}  ; DownTemp 和 Down 相似，只是如果使用 DownTemp ，脚本运行到下一个 Send 命令时会不会认为 'b' 键仍处于按下的状态。
return

*a up::
SetKeyDelay -1  ; 代码中两处 SetKeyDelay 命令都没有指定按键时长(press-duration ， SetKeyDelay 命令的第二个参数)，其原因请看下面的解释。
Send {Blind}{b Up}
return

在下面的情况下，将映射翻译成热键时会作一些调整：

  1. 如果原始键(source key)是 LCtrl 键，目标键(destination key)是 Alt 键， Send {Blind}{LAlt DownTemp} 会被替换成 Send {Blind}{LCtrl Up}{LAlt DownTemp} 。当原始键是 RCtrl 时也会作类似的调整。
  2. 如果是把键盘键映射成鼠标键(如 RCtrl::RButton )，则会用 SetMouseDelay 命令代替 SetKeyDelay 命令。同时，上面的第一个热键也会被替换成下面的热键，这样就可以防止由于键盘键按下后会重复发送键击消息而产生鼠标重复点击的消息：
    *RCtrl::
SetMouseDelay -1
if not GetKeyState("RButton")  ; 换言之，鼠标右键尚未按下。
    Send {Blind}{RButton DownTemp}
return

注意 SetKeyDelay 命令的第二个参数 按键时长(press duration) 在上述的热键中被略去了。这是因为按键时长不适用于键按下和键弹起这样的事件(如 {b down} 和 {b up} )。但是按键时长却适用于涉及到 Shift/Ctrl/Alt/Win 键的事件，例如在 a::B 和 a::^b 中。因此，脚本中在 自动运行区(auto-execute section) 发生作用的按键时长参数会对所有这样的映射产生影响。

虽然不能将一对键直接映射成单个键(例如， a & c::b 这样的映射是无效的)，但只需修改上述的代码中两个热键(分别是键按下和键弹起时的热键)就可以实现：将 *a:: 替换成 a & c:: ，并将 *a up:: 替换成 a & c up:: 即可。

由于映射最终会被翻译成热键， Suspend 命令也会对映射产生影响。同样，也可以用 Hotkey 命令来禁用或修改一个映射。例如，下面两行代码可以禁用映射 a::b 。

Hotkey, *a, off
Hotkey, *a up, off

与 Alt-tab 有关的问题：如果你将一个键盘键或鼠标键映射成 Alt 键，这个键很有可能实现不了 alt-tab 的功能。在多数情况下，添加 *Tab::Send {Blind}{Tab} 这个热键解决这个问题——但是注意这很有可能会影响原始 Alt 键实现 alt-tab 的功能。因此，只有当你仅用映射键或 alt-tab hotkeys 来实现 alt-tab 的功能时才用这个方法。

除了 Key List 页面所列出来的鼠标键和键盘键外，原始键(source key)也可以是一个虚拟键(virtual key 或 VKnn)或扫描码(scan code 或 SCnnn)，在 special keys 页面中有对虚拟键和扫描码的介绍。同样，目标按键也可以使用虚拟键或扫描码，不过它还可以同时使用虚拟键和扫描码(在虚拟按键后面再指定一个扫描码)。例如，在大多数键盘布局下 sc01e::vk42sc030 与 a::b 等效。

如果想禁用一个键，而不是映射这个键，将其定义成直接 returns 的热键。例如，热键 F1::return 可以禁用 F1 键。

以下的键不支持映射：

  • 鼠标滚轮。(虽然写着不支持,不过确实支持啊)
  • Pause 键和 Break 键不能作为目标键(destination keys)。(这是因为它们在代码中会被当做命令执行)。
  • 花括号 {} 不能作为目标键。但是可以用 虚拟键/扫描码的方法(VK/SC method) 来实现。如 x::+sc01A 和 y::+sc01B
  • 百分号 % 不能作为目标键。同样可以用 虚拟键/扫描码的方法(VK/SC method) 来实现。
  • 回车符 "Return" 不能作为目标键。用 "Enter" 代替。

用键盘来移动鼠标光标

通过映射(或者热键)，键盘可以用来移动鼠标的光标，如 键盘-鼠标脚本(Keyboard-To-Mouse script) 所示。由于这个脚本能提供鼠标平滑移动、加速和其他的功能，如果你需要用键盘来实现鼠标的功能，推荐你使用这个脚本。下面是一个简化的键盘-鼠标脚本实例：

*#up::MouseMove, 0, -10, 0, R  ; Win+UpArrow hotkey => 光标上移
*#Down::MouseMove, 0, 10, 0, R  ; Win+DownArrow => 光标下移
*#Left::MouseMove, -10, 0, 0, R  ; Win+LeftArrow => 光标左移
*#Right::MouseMove, 10, 0, 0, R  ; Win+RightArrow => 光标右移

*<#RCtrl::  ; LeftWin + RightControl => 鼠标左击。
SendEvent {Blind}{LButton down}
KeyWait RCtrl  ; 防止键盘自动重复导致鼠标重复点击。
SendEvent {Blind}{LButton up}
return

*<#AppsKey::  ; LeftWin + AppsKey => 鼠标右击。
SendEvent {Blind}{RButton down}
KeyWait AppsKey  ; 防止键盘自动重复导致鼠标重复点击。
SendEvent {Blind}{RButton up}
return

使用注册表的“扫描码映射(Scancode Map)”功能来实现映射

优点：

  • 注册表映射在大多数情况下比 AutoHotkey 的映射 更加直接和有效。如，注册表映射能在更多的游戏中起作用，而且不会存在 alt-tab 问题 ；另外也能够触发 AutoHotkey 中的钩子热键(hook hotkey)。(而 AutoHotkey 中的映射需要使用 间接的方法(workaround) 才能“触发”勾住的热键)。
  • 如果你是手动地修改注册表项(下面会详细描述)，那么不需要使用任何外部软件就可以实现映射。即使你使用 KeyTweak 来修改注册表项，修改完后也不需要 KeyTweak 运行就可以让映射生效(而 AutoHotkey 则需要一直运行才能使映射生效)。

缺点：

  • 缺少灵活性：每一次修改映射，需要重启计算机后才能让修改生效。
  • 不能让映射仅对特定的用户、程序有效。
  • 不能发送包含 Shift, Control, Alt, AltGr 键的组合键击消息。也不能将一个小写字母映射成大写字母。
  • 在 Windows 95/98/Me 下不被支持。而 AutoHotkey 能实现 部分Win9x映射(limited Win9x remapping) 。
  • 仅支持对键盘的映射。而 AutoHotkey 还支持 鼠标映射 和 部分操作杆映射(limited joystick remapping) 。

如何修改注册表：至少有两种方法：

  1. 通过软件，如 KeyTweak (免费软件)来映射键盘。它会自动修改注册表。
  2. 手动创建 .reg 文件(纯文本文件)并将它载入注册表。详见 www.autohotkey.com/forum/post-56216.html#56216

Windows 95/98/Me下的映射方法

方法是直接使用热键。推荐在编写热键时使用 Send 和 KeyWait 这两个命令。例如，下面的热键可以将 'A' 键映射成左方向键：

a::
Send {Left down}  ; 按下左方向键。
KeyWait a  ; 等待用户释放 'a' 键。
Send {Left up}  ; 释放左方向键。
return

相关主题

List of keys and mouse buttons
GetKeyState
Remapping a joystick


List of Keys and Mouse/Joystick Buttons for Hotkeys and Macros

按键列表、鼠标按键和操纵杆控制

鼠标 (鼠标热键需要 Windows NT/2000/XP 或之后版本)

LButton - 鼠标左键
RButton - 鼠标右键
MButton - 鼠标中键或滚轮

WheelDown - 这相当于将鼠标滚轮向后旋转(朝向你自己)
WheelUp - 上面这种的反向。
WheelLeft 和 WheelRight [v1.0.48+] - 这两个要求鼠标有左右滚动的能力，而且它们在 Windows Vista 以前的操作系统中没有效果。
(参见 mouse wheel hotkeys 来检测鼠标滚轮被滚动了多少。)

仅支持 Windows 2000/XP 或之后版本：
XButton1 - 仅出现在某些鼠标上的一个按键
XButton2 - 同上

键盘

注意：字母和数字按键的名称和单个字母或数字是一样的。例如：b 表示 "b" 键，5 表示 "5" 键。

Space - 空格键
Tab
Enter (或 Return)
Escape (或 Esc)
Backspace (或 BS)

Delete (或 Del)
Insert (或 Ins)
Home
End
PgUp
PgDn
Up
Down
Left
Right

ScrollLock
CapsLock
NumLock

Numlock 启用 | Numlock 关闭
Numpad0 | NumpadIns
Numpad1 | NumpadEnd
Numpad2 | NumpadDown
Numpad3 | NumpadPgDn
Numpad4 | NumpadLeft
Numpad5 | NumpadClear
Numpad6 | NumpadRight
Numpad7 | NumpadHome
Numpad8 | NumpadUp
Numpad9 | NumpadPgUp
NumpadDot (.) | NumpadDel
NumpadDiv (/) | NumpadDiv (/)
NumpadMult (*) | NumpadMult (*)
NumpadAdd (+) | NumpadAdd (+)
NumpadSub (-) | NumpadSub (-)
NumpadEnter | NumpadEnter

F1 到 F24 - 在大多数键盘顶端的 12 个或更多的功能键。

AppsKey - 这是个调用右键上下文菜单的按键。（译注：一般在右 Win 键和右 Ctrl 键中间）

LWin - 左边的 windows标志 键
RWin - 右边的 windows标志 键。注意：和 Control/Alt/Shift 不同，这里没有一般的/中性的 "Win" 键因为操作系统不支持。
Control (或 Ctrl)
Alt
Shift
注意：Shift:: 、Alt:: 和 Control:: 热键在按键松开时激发除非它们有波浪符前缀例如 ~Alt:: 。相比之下，一个明确了左或右的热键例如 LAlt:: 在按下时激发。

注意：多半，下面的 6 个键不被 Windows 95/98/Me 支持。使用上面的代替：
LControl (或 LCtrl) - 左边的 control 键
RControl (或 RCtrl) - 右边的 control 键
LShift - 左边的 shift 键
RShift - 右边的 shift 键
LAlt - 左边的 Alt 键
RAlt - 注意：如果你的键盘布局用 AltGr 代替了 RAlt，你也许可以通过 <^>! 让它像这里描述的那样作为一个热键前缀来使用。此外，"LControl & RAlt::" 将让 AltGr 它自身成为一个热键。

PrintScreen
CtrlBreak
Pause
Break -- 由于此键和 Pause 是一起的，在热键中不能使用 ^Pause 或 ^Break，而用 ^CtrlBreak 来代替。

Help - 此键也许在大多数键盘上不存在。它通常和 F1 不一样。
Sleep - 注意 sleep 键在一些键盘上可能不是休眠功能。（译注：电源选项>高级 标签中可以调节。）

下面的仅存在那些有额外按键或按钮的多媒体或 Internet 键盘上：
Browser_Back
Browser_Forward
Browser_Refresh
Browser_Stop
Browser_Search
Browser_Favorites
Browser_Home
Volume_Mute
Volume_Down
Volume_Up
Media_Next
Media_Prev
Media_Stop
Media_Play_Pause
Launch_Mail
Launch_Media
Launch_App1
Launch_App2

SCnnn (这里 nnn 是一个按键的扫描代码) - 识别上面没有提到的特殊的按键。详见特殊按键。

VKnn (这里 nn 是一个按键的十六进制虚拟按键代码) - 这种极少用的方法也阻止了某些类型的热键去依赖键盘钩子。例如，后面的热键不使用键盘钩子，但作为一个副作用，通过按 Home 或 NumpadHome 都能触发它：^VK24::MsgBox 你在按住 Control 的同时按下了 Home 或 NumpadHome 键。详见特殊按键。

操纵杆

Joy1 到 Joy32: 操纵杆的按钮。要帮忙确定你的操纵杆的按钮编号，请用这个测试脚本。注意热键前缀符号例如 ^ (control) 和 + (shift) 不被支持 (虽然 GetKeyState 能用来代替)。同样注意如果激活的窗口被设计成探测操纵杆按钮的按下，操纵杆的按钮按下将总会“传递”给它。

虽然下面的操纵杆控制器名称不能被用作热键，但它们能和 GetKeyState 一起使用：
JoyX, JoyY 和 JoyZ: 操纵杆的 X (水平的) 、Y (垂直的) 和 Z (高度/深度) 轴。
JoyR: 方向舵或操纵杆的第 4 个轴。
JoyU 和 JoyV: 操纵杆的第 5 个和第 6 个轴。
JoyPOV: point-of-view (hat) 控制器。
JoyName: 操纵杆的名称或它的驱动。
JoyButtons: 操纵杆支持的按钮总数(不会总是精确的)。
JoyAxes: 操纵杆支持的轴的总数。
JoyInfo: 提供一个包含零或下面多个字母组成的字串来显示操纵杆的功能：Z (有 Z 轴), R (有 R 轴), U (有 U 轴), V (有 V 轴), P (有 POV 控制器), D (POV 控制器有少数不连续的/不同的设置), C (POV 控制器是连续的/精细的)。字串示例：ZRUVPD

多个操纵杆：如果计算机有多个操纵杆并且你想在第一个旁边使用另一个，那么在控制器名称前面包含操纵杆编号。例如，2joy1 是第二个操纵杆的第一个按钮。

注意：如果你获得的脚本在识别你的操纵杆时有问题，有一个人报告说需要指定一个操纵杆的编号为除 1 以外的数字，即使只有单独一个操纵杆存在。不清楚这种情况如何发生的或者它是否正常，但将操纵杆编号在操纵杆测试脚本中试验能帮助确定这是否适用于你的系统。

也可以看：
操纵杆重映射: 用一个操纵杆发送键击和鼠标点击的方法。
操纵杆到鼠标脚本: 将操纵杆作为鼠标使用。

手持遥控

响应手持遥控通过 WinLIRC 客户端脚本发送的信号。

特殊按键

如果你的键盘或鼠标有按键没有在上面被列出来，你也许通过采用下面的步骤仍有可能使它成为一个热键(需要 Windows XP/2000/NT 或之后版本)：

  1. 确保至少有一个使用键盘钩子的脚本正在运行。你只要通过打开一个脚本的主窗口并从菜单栏选择 "View->Key history" 就能知道它是否使用了键盘钩子。
  2. 双击那个脚本的托盘图标来打开它的主窗口。
  3. 按下你键盘上的某个“神秘按键”。
  4. 选择菜单项 "View->Key history"
  5. 向下滚动到页面的底部。在底部附近的某处就有你的按键的按下和弹起事件记录。注意：某些按键不生成事件记录，因此这里将看不到记录。如果是这种情况，你不能直接让那个特殊按键成为一个热键，因为你的键盘驱动或硬件在一个 AutoHotkey 访问不到的很低的层面处理它。要得到可能的解决方案，再往下看。
  6. 如果你的按键可被探测到，记下在列表第二列的 3 位十六进制数值 (例如 159)。
  7. 要定义此键为一个热键，参照此例：
    SC159:: ;用你那按键的数值替换 159。
MsgBox, %A_ThisHotKey% 被按下。
return

反向：要让其他某些键重映射为一个“神秘按键”，参照此例：

;用上面发现的数值替换 159。用按键的虚拟键值替换 FF (如果需要的话)，它能在按键历史页面的第一列找到。
#c::Send {vkFFsc159}

替换的解决方案：如果你的按键或鼠标按键在按键历史页面没有被探测到，下面的某种方法也许有帮助：

  1. 重新配置你的鼠标或键盘附带的软件(大多数时候能在控制面板或开始菜单进行访问) 来使“神秘按键”发送其他一些键击。然后这样的一个键击能在脚本里被定义为一个热键。例如，如果你设置一个神秘按键来发送 Control+F1 ，之后你能通过在脚本中用 ^F1:: 直接让它成为一个热键。

  2. 试试 DllCall: Support for Human Interface Devices 。你也可以在 forum (论坛) 中搜索类似 RawInput* 的关键字。

  3. 下面是一个最后的手段并且通常应该仅在绝望时尝试。这是因为成功的机会很小并且它可能导致不想要的副作用而且难以撤销：
    禁用或移除你的键盘或鼠标附带的额外的软件或者将它的驱动改变为一个更加标准的例如建立在操作系统上。这里假设的是有那么一种驱动给你特殊的键盘或鼠标，而你能不用它自定义的驱动和软件提供的特性而继续使用下去。


AutoHotkey Scripts and Macros

脚本

目录

  • 简介
  • 脚本顶部 (自动执行段): 当脚本启动时, 这部分会自动执行.
  • 转义序列: 什么时候应该使用 `% 和 `, 表示一个原义的百分号和逗号.
  • 脚本中的注释: 使用分号和 /*...*/ 给脚本添加注释.
  • 把一个过长的行分割成一系列短行: 这样可以提高脚本的可读性和可维护性.
  • 把脚本转换成 EXE 文件 (ahk2exe): 把 .ahk 脚本转换成可以在任何 PC 上运行的 .exe 文件.
  • 向脚本传递命令行参数: %1%, %2% 等变量包含了传入的参数.
  • 脚本文件代码页: 在脚本中可靠地使用非 ASCII 字符.
  • 调试脚本: 如何找出无法正常工作脚本中的问题.
  • AutoHotkey.exe 的可移植性: 有一个 AutoHotkey.exe 的副本足以执行任何的 .ahk 文件.
  • 安装程序选项: 如何无人值守/静默的安装或卸载.

简介

每个脚本都是一个纯文本文件, 其中包含了可由程序 (AutoHotkey.exe) 执行的文本行. 脚本中还可以包含 热键 和 热字串, 或者甚至完全由它们组成. 不过, 在不存在热键和热字串时, 脚本会在启动后从上往下按顺序执行其中的命令.

程序会把脚本逐行加载到内存中, 每行最多可以包含 16,383 个字符. 在加载过程中, 脚本将被 优化 和验证. 任何语法错误都会被列出, 纠正它们后脚本才能运行.

脚本顶部 (自动执行段)

脚本加载完成后, 它会从顶行开始执行, 直到遇到 Return, Exit,热键/热字串标签 或脚本的底部 (无论最先遇到哪个). 脚本的这个顶端部分被称为 自动执行 段.

如果一个脚本不是 持续运行的 并且不含有 热键, 热字串, OnMessage 和 GUI, 那么它会在自动执行段结束后终止. 否则, 它会以空闲状态继续运行, 从而对例如热键, 热字串, GUI 事件, 自定义菜单项 和 计时器 这些事件进行响应.

每个由 热键, 热字串, 菜单项, GUI 事件 或 计时器 启动的 线程 都以在自动执行段设置的下列属性值作为默认值开始. 如果未设置, 则使用标准的默认值 (与下面每个页面中注明的一样): DetectHiddenWindows, DetectHiddenText, SetTitleMatchMode, SetBatchLines, SendMode, SetKeyDelay, SetMouseDelay, SetWinDelay, SetControlDelay, SetDefaultMouseSpeed, CoordMode, SetStoreCapslockMode, AutoTrim, SetFormat, StringCaseSense, Thread 和 Critical.

如果自动执行段花了很长时间才结束 (或从未结束), 上面这些设置的默认值将在 100 毫秒后自动生效. 当自动执行段最终结束 (如果可能) 时, 在自动执行段末尾生效的那些设置才更新为默认值. 因此, 通常最好在包含 热键, 热字串, 计时器 或 自定义菜单项 的脚本顶部设置自己想要的默认值. 还要注意, 每个 线程 会保存它自己的上述这些设置的一个集合. 在一个线程中对这些设置的的改变不会影响其他 线程.

转义序列

AutoHotkey 中默认的 转义符 为重音符/反引号 (`), 它位于大多数英文键盘的左上角. 使用这个字符而不是反斜线可以避免在文件路径中使用双反斜线.

由于在 AutoHotkey 语言中逗号和百分号具有特殊含义, 因此需要使用 `, 来指定一个原义的逗号, 使用 `% 指定一个原义的百分号. 其中的一个例外 MsgBox, 它里面不需要将逗号进行转义. 另一个例外是在任意命令最后一个参数中的逗号: 它们不需要进行转义. 参见 #EscapeChar 了解转义序列的完整列表.

某些特殊的字符也需要使用转义序列的方法生成. 最常见的有 `t (tab), `n (换行) 和 `r (回车).

提示: 任意命令中的首个逗号可以省略 (除非首个参数为空或以 := 或 = 开始, 或命令单独处于 字串分段 的顶部). 例如:

MsgBox This is ok.
MsgBox, This is ok too (it has an explicit comma).

脚本中的注释

在行首使用分号可以注释脚本. 例如:

; This entire line is a comment.

也可以在命令的末尾添加注释, 此时分号左侧必须至少有一个空格或 tab. 例如:

Run Notepad  ; This is a comment on the same line as a command.

此外, 使用 /* 和 */ 符号可以注释整块, 但仅当它们出现在行首时才有效, 例如:

/*
MsgBox, This line is commented out (disabled).
MsgBox, This one too.
*/

由于脚本运行时会忽略注释, 所以它们不会影响脚本性能或占用内存.

使用 #CommentFlag 可以把默认注释符 (分号) 更改为其他字符或字符串.

把一个过长的行分割成一系列短行

过长的行可以分割成一系列较短的行来提高可读性和可维护性. 这样不会降低脚本的执行速度, 因为在脚本启动时这些短行会在内存中合并起来.

方法 #1: 以 "and", "or", ||, &&, 逗号 或 句点 开头的行会自动合并到其 (在 1.0.46+ 版本中, 以除了 ++ 和 -- 外所有其他的 表达式运算符 开头的行也会如此). 在下面的例子中, 第二行会自动附加到首行, 因为它以逗号开头:

FileAppend, This is the text to append.`n   ; 这里可以使用注释.
    , %A_ProgramFiles%\SomeApplication\LogFile.txt  ; 注释.

类似地, 下列几行会合并成单行, 因为最后两行以 "and" 或 "or" 开始:

if (Color = "Red" or Color = "Green"  or Color = "Blue"   ; 注释.
    or Color = "Black" or Color = "Gray" or Color = "White")   ; 注释.
    and ProductIsAvailableInColor(Product, Color)   ; 注释.

三元运算符 也是个不错的候选:

ProductIsAvailable := (Color = "Red")
    ? false  ; 我们没有任何红色产品, 所以不用那么麻烦去调用函数.
    : ProductIsAvailableInColor(Product, Color)

尽管在上面的例子中缩进不是必须的, 但它可以指出哪些行属于上一行从而提高代码的清晰度. 并且可以不必在以单词 "AND" 和 "OR" 开始的行的开头加上额外的空格; 程序会自动处理这些. 最后, 可以在上面例子中任意行的末尾或行与行之间添加空行或 注释.

方法 #2: 这种方法可以合并大量的行或者方法 #1 不适合处理的行. 尽管此方法对 自动替换热字串 特别有用, 但它也可以用于任意命令或 表达式. 例如:

; 示例 #1:
Var =
(
Line 1 of the text.
Line 2 of the text. By default, a linefeed (`n) is present between lines.
)

; 示例 #2:
FileAppend,  ; The comma is required in this case.
(
A line of text.
By default, the hard carriage return (Enter) between the previous line and this one will be written to the file as a linefeed (`n).
    By default, the tab to the left of this line will also be written to the file (the same is true for spaces).
By default, variable references such as %Var% are resolved to the variable's contents.
), C:\My File.txt

在上面的例子中, 一系列行被头尾的一对括号包围起来. 这被称为 字串分段. 注意在底行的闭括号后面包含了 FileAppend 的最后一个参数. 这个习惯是可选的; 这样做是为了在这种情况下把逗号视为参数分隔符而不是原义的逗号.

通过在开括号的右侧包含一个或多个下列选项, 可以覆盖字串分段的默认特性. 如果含有多个选项, 选项之间使用空格分隔. 例如: ( LTrim Join| %

Join: 指定行与行之间应该如何连接. 如果省略此选项, 除最后一行外的其他行后面都会跟一个换行符 (`n). 如果仅指定单词 Join 自身, 则行与行之间直接连接而不添加任何字符. 或者在单词 Join 后可以跟着多达 15 个字符. 例如, Join`s 会在除最后一行外的每行末尾插入一个空格 (`s 表示一个原义的空格 -- 这是个只能被 Join 识别的特殊转义序列). 另一个例子是 Join`r`n, 它会在行与行之间插入 CR+LF. 同样地, Join| 会在行之间插入管道符. 要让字串分段部分的最后一行也以连接字符串结尾, 需要在闭括号上一行添加一个空行.

LTrim: 删除每行开头的空格和 tab. 主要用来允许字串分段使用缩进. 此外, 通过在一行中指定 #LTrim 自身可以为多个字串分段打开此选项. #LTrim 是可选的: 它会影响它下面的所有字串分段. 通过 #LTrim Off 可以关闭此设置.

RTrim0 (RTrim 后面跟着一个零): 关闭自动删除每行末尾的空格和 tab 的设置.

Comments (或 Comment 或 Com 或 C) [v1.0.45.03+]: 允许在字串分段中使用 分号注释 (但不支持 /*..*/). 这样的注释 (以及它们左边的任何空格和 tab) 在连接时完全被忽略而不是当成原义文本处理. 每个注释可以放在一行的右侧或单独一行中.

% (百分号): 把百分号作为原义字符而不是变量引用. 这样就可以不需要对每个百分号 转义 成原义字符. 在百分号已经为原义的地方就不需要此选项了, 例如 自动替换热字串.

, (逗号): 把逗号作为分隔符而不是原义逗号. 这个非常少用的选项只有在命令参数之间才会用到, 因为在 函数调用 中, 逗号的类型没有影响. 并且, 此选项只会转换那些真正分隔参数的逗号. 换句话说, 一旦到达命令的最后一个参数 (或者命令没有参数), 会忽略此选项而把后续的逗号当成原义的逗号.

` (重音符): 把每个反引号作为原义字符而不是 转义符. 此选项同时也避免了需要分别对逗号和百分号进行明确地转义. 此外, 它还阻止对任何特定的转义序列例如 `r 和 `t 进行转换.

备注

未指定 重音符 (`) 选项 时, 在字串分段内支持使用 转义序列 例如 `n (换行符) 和 `t (tab).

未指定 comment 选项 时, 在字串分段内不支持使用分号和 /*..*/ 注释, 此时它们会被视为原义的文本. 但是, 可以在字串分段的顶部和底部行添加注释. 例如:

FileAppend,   ; 注释.
; Comment.
( LTrim Join    ; 注释.
     ; 此行 不是 注释; 它是原义的. 在上一行使用单词 Comments 可以让这行成为注释.
), C:\File.txt   ; 注释.

根据上面可以得出结论, 在字串分段中的分号不需要进行 转义.

使用字串分段的方法无法生成总长度大于 16,383 字符的行 (如果尝试这样做, 那么程序在启动时将弹出警告). 一种变通的解决方法是把一系列内容连接到一个变量中. 例如:

Var =
(
...
)
Var = %Var%`n  ; 通过另一个字串分段添加更多的文本到此变量中.
(
...
)
FileAppend, %Var%, C:\My File.txt

因为闭括号表示字串分段的结束, 要让某一行以原义的闭括号开头, 需要在其前面加上一个重音符/反引号: `).

一个字串分段后面可以立即跟着包含另一个字串分段的开括号的一行. 这样使得上面提到的选项可以在创建单行的过程中进行改变.

不支持通过 #Include 的方法把字串分段各部分连接起来.

把脚本转换成 EXE 文件 (ahk2exe)

在程序中包含了一个脚本编译器 (承蒙 Jonathan Bennett 提供的 AutoIt v3 源码). 不支持 AutoIt v2 脚本, 所以如果需要, 首先把你的 .aut 文件 自动转换为 .ahk.

当脚本编译完成后, 就成为了一个独立的可执行文件; 即它甚至可以在没有安装 AutoHotkey 的机器上运行 (并且这样的 EXE 文件可以随意发布或出售). 在编译过程中会对下列所有文件进行压缩和加密: 脚本, 脚本所 include 的任何文件, 以及通过 FileInstall 合并的任何文件.

编译不会提高脚本的性能. 实际上, 已编译脚本在启动时会稍慢, 因为首先必须把它解密和解压缩到内存中, 然后才像普通脚本那样进行 优化.

使用 Ahk2Exe 有下列几种方式:

  1. 图形界面: 运行开始菜单中的 "Convert .ahk to .exe" 菜单项.
  2. 右键点击: 在资源管理器窗口中, 你可以右键点击任一 .ahk 文件并选择 "Compile Script" (只有在安装 AutoHotkey 时选择脚本编译器选项才可用). 这样就创建了与原来的脚本具有相同的主文件名的 EXE 文件, 它在稍后出现在同一个的目录中. 注意: 这样会用和方法 #1 中最后一次使用的自定义图标和压缩等级相同的设置来生成 EXE 文件, 并且没有设置密码.
  3. 命令行: 编译器可以使用下列参数在命令行中运行:
    Ahk2exe.exe /in MyScript.ahk [/out MyScript.exe] [/icon MyIcon.ico] [/pass password] [/bin AutoHotkeySC.bin]
    例如:
    Ahk2exe.exe /in "MyScript.ahk" /icon "MyIcon.ico" /pass "CustomPassword"
    用法:
    • 含有空格的参数应该包围在双引号中.
    • 如果省略了 "out" 文件, 则使用脚本文件的主名作为 EXE 文件主名.

请注意:

  • 含有非 ASCII 字符的脚本文件 必须使用 UTF-8 编码. 但是, 因为 Ahk2Exe 不支持 Unicode 文件名, 所以在 #Include 和 FileInstall 文件名中只能使用 ASCII 字符.
  • 如果你打算发布自己的 EXE 文件并且不想让任何人看到脚本的源码, 考虑使用非标准的 可执行文件打包器. MPRESS, AutoHotkey_L 默认使用的打包器, 可以为大多数用户提供足够的保护. 仅在 32 位编译时支持密码保护, 并且不再支持 /NoDecompile 开关.
  • #NoTrayIcon 和 "Menu, Tray, ShowMainWindow" 命令会影响已编译脚本的行为.
  • 下载 Exe2Ahk (此工具应该在命令提示符中运行) 执行可以反编译 32 位的 EXE 文件来获取它的原始脚本. 对于 64 位的 EXE 文件, 可以使用像 Resource Hacker 这样的资源编辑器提取原始脚本, 可以得到没有使用 MPRESS 或类似工具压缩过的 EXE 文件 (是指脱壳的意思吧). 不过, 原来的所有 注释 (分号或 /**/) 都会丢失.
  • 使用像 Resource Hacker (免费软件) 这样的工具编辑 "AutoHotkeySC.bin" 文件, 可以把自定义的版本信息 (在资源管理器的文件属性对话框中看到的那些) 添加到你的已编译脚本中. 这个文件包含了 AutoHotkey 安装目录的 "compiler" 子文件夹中. 注意: Resource Hacker 会破坏已编译脚本, 这是为什么只应该编辑 AutoHotkeySC.bin 文件的原因. Compile_AHK II 可以用来简化编译的过程.
  • 上面的方法还可以用来改变所有已编译脚本中现有的图标或添加新的图标.
  • 如果脚本以已编译的形式运行, 则内置变量 A_IsCompiled 的值为 1. 否则为空.
  • 如果你不希望对已编译的脚本进行压缩, 删除或重命名 AutoHotkey 的 "Compiler" 文件夹中的 "mpress.exe" (或较旧版本中为 "upx.exe") 文件.
  • 当参数传递给 Ahk2Exe 执行时, 会在标准输出中写入一条表示编译成功与否的消息. 尽管此消息不会显示在命令提示符中, 但可以通过像重定向到文件的方法 "捕获". [v1.0.43+]

向脚本传递命令行参数

脚本支持命令行参数. 格式为:

AutoHotkey.exe [Switches] [Script Filename] [Script Parameters]

对于已编译脚本, 格式为:

CompiledScript.exe [Switches] [Script Parameters]

Switches: 零个或多个下列开关:
/f 或 /force -- 无条件运行, 跳过任何警告对话框.
/r 或 /restart -- 提示脚本应该重新加载 (在脚本内部可以使用 Reload 命令).
/ErrorStdOut -- 把阻止脚本运行的语法错误发送到标准输出而不是显示在对话框中. 参见 #ErrorStdOut 了解详情.
/Debug -- [AHK_L 11+]: 连接到调试客户端. 更多详情参见 交互调试.
/CPn -- [AHK_L 51+]: 覆盖用来读取脚本文件的默认代码页. 更多详情参见 脚本文件代码页.

Script Filename: 如果没有 Script Parameters, 那么此参数可以省略. 如果省略, 它将会运行 (或者提示你创建) 下列默认位置的其中一个文件:

[AHK_L 51+]: %AhkExeDir%\%AhkExeName%.ahk 或 %A_MyDocuments%\%AhkExeName%.ahk, 此处 %AhkExeDir% 和 %AhkExeName% 需要使用运行当前脚本的可执行文件的目录和文件名替换, 不包括 ".exe" 扩展名.

[早期版本]: AutoHotkey.ini (在当前工作目录) 或 %A_MyDocuments%\AutoHotkey.ahk.

Script Parameters: 你想要传递给脚本的字符串, 字符串之间使用空格分隔. 任何含有空格的参数应该包围在一对双引号之间. 要传递一个原义的引号, 在其前面加上一个反斜线 (\"). 因此, 任何引号包围的参数 (例如 "C:\My Documents\") 中末尾的反斜线会让紧跟着的引号被当作原义的引号进行处理 (即脚本将会接收到字符串 C:\My Documents"). 要移除这样的引号, 使用 StringReplace, 1, 1, ",, All

脚本中把传入的参数视为 变量 %1%, %2% 等等. 此外, 变量 %0% 包含了传入参数的数目 (没有则为 0). 在下面的例子中, 如果传入的参数过少脚本会退出:

if 0 < 3  ; 非表达式 if 语句 左侧总是变量名.
{
    MsgBox This script requires at least 3 incoming parameters but it only received %0%.
    ExitApp
}

如果传递给脚本的参数数目不确定 (可能由于用户拖放一组文件到脚本上), 可以使用下面的例子逐个提取它们:

Loop, %0%  ; For each parameter:
{
    param := %A_Index%  ; 取得名称为 A_Index 的值的变量中的内容.
    MsgBox, 4,, Parameter number %A_Index% is %param%.  Continue?
    IfMsgBox, No
        break
}

如果这些参数是文件名, 可以使用下列的例子把它们转换到大小写正确的长文件名 (与文件系统中储存的一致), 包含完整/绝对的路径:

Loop %0%  ; For each parameter (or file dropped onto a script):
{
    GivenPath := %A_Index%  ; 取得名称为 A_Index 的值的变量中的内容.
    Loop %GivenPath%, 1
        LongPath = %A_LoopFileLongPath%
    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%
}

已知限制: 如果 NTFS 文件系统中关闭了 8.3 (短) 文件名, 拖拉文件到 .ahk 脚本上可能无法正常工作. 一个变通的解决方法是 编译 脚本, 然后拖放文件到产生的 EXE 文件上.

脚本文件代码页 [AHK_L 51+]

脚本文件中可以使用的字符受到用来加载脚本的代码页的限制.

  • 需要编译脚本的源文件 必须 使用 UTF-8 编码或者仅使用 ASCII 字符.
  • 如果文件以 UTF-8 或 UTF-16 (LE) 字节顺序标记开头, 则会为其使用适合的代码页并且忽略 /CPn 开关.
  • 如果在命令行中传递了 /CPn 开关, 则使用代码页 n. 想了解有效的数值代码页标识符, 参见 MSDN.
  • 其他所有情况下, Unicode 版本使用 UTF-8 而 ANSI 使用系统默认的 ANSI 代码页.

由于所有的文本都被转换 (必要时) 为 原生的字符串格式, 无效的或不存在于原生代码页中的字符都被替换为占位符: ANSI '?' 或 Unicode '�'. 在 Unicode 版本中, 这样的情况只可能在脚本文件编码错误或用于保存和读取脚本的代码页不一致时发生.

请注意:
在 Unicode 版本中, 如果指定的代码页不正确, 则非 ASCII 字符很可能被曲解或替换为 �. 推荐使用 UTF-8 编码. 如果你的首选编辑器不支持 UTF-8 (或带 BOM 的 UTF-16), 使用 /CPn 开关 - 把 n 替换为 0 或者你系统 ANSI 代码页的数值标识符.

可以使用 RegWrite 为资源管理器中运行的脚本设置默认代码页 (例如双击脚本文件时):

; Uncomment the appropriate line below or leave them all commented to
;   reset to the default of the current build.  Modify as necessary:
; codepage = 0        ; System default ANSI codepage
; codepage = 65001    ; UTF-8
; codepage = 1200     ; UTF-16
; codepage = 1252     ; ANSI Latin 1; Western European (Windows)
if (codepage != "")
    codepage := " /CP" . codepage
cmd="%A_AhkPath%"%codepage% "`%1" `%*
key=AutoHotkeyScript\Shell\Open\Command
if A_IsAdmin    ; Set for all users.
    RegWrite, REG_SZ, HKCR, %key%,, %cmd%
else            ; Set for current user only.
    RegWrite, REG_SZ, HKCU, Software\Classes\%key%,, %cmd%

使用这个脚本前假定已经安装了 AutoHotkey_L. 如果没有安装结果可能不够理想.

调试脚本

ListVars 和 Pause 等命令可以帮助你调试脚本. 例如, 把下面这两行临时插入精心选择的位置时, 可以在脚本中创建 "断点":

ListVars
Pause

当脚本执行到这两行时, 将会显示所有变量当前包含的内容供你检查. 当你准备恢复时, 可以通过 File 或 Tray 菜单取消暂停. 然后脚本会继续执行直到遇到下一个 "断点" (如果有的话).

通常最好把这些 "断点" 插入到活动窗口对当前脚本没什么影响的位置, 例如在 WinActivate 命令的前一行. 这样当你取消暂停时脚本才可以正确地恢复操作.

下列命令对调试也很有用: ListLines, KeyHistory 和 OutputDebug.

交互调试 [AHK_L 11+]

通过受支持的 DBGp 客户端 可以进行交互调试. 通常支持下列动作:

  • 设置和移除行中的断点 - 遇到 断点 时暂停执行.
  • 单步调试代码 - 逐语句, 逐过程或跳出函数和子程序.
  • 检查所有变量或特殊变量.
  • 查看正在运行的子程序和函数的堆栈.

注意此功能对于已编译脚本中是无法使用的.

要启用交互调试, 首先要运行一个受支持的调试器客户端然后使用命令行开关 /Debug 运行脚本.

AutoHotkey.exe /Debug[=SERVER:PORT] ...

SERVER 和 PORT 可以省略. 例如, 下面两个是等同的:

AutoHotkey /Debug "myscript.ahk"
AutoHotkey /Debug=localhost:9000 "myscript.ahk"

[AHK_L 59+]: 要向已经在运行的脚本附加调试器, 向脚本发送消息, 如下所示:

ScriptPath = ; SET THIS TO THE FULL PATH OF THE SCRIPT
DetectHiddenWindows On
ifWinExist %ScriptPath% ahk_class AutoHotkey
    ; 可选参数:
    ;   wParam  = the IPv4 address of the debugger client, as a 32-bit integer.
    ;   lParam  = the port which the debugger client is listening on.
    PostMessage DllCall("RegisterWindowMessage", "str", "AHK_ATTACH_DEBUGGER")

一旦调试器连接后, 可以通过发送 "detach" DBGp 命令在不终止脚本的情况下分离调试器.

AutoHotkey.exe 的可移植性

运行任何 .ahk 脚本只需要 AutoHotkey.exe 这一个文件. 唯一的例外是 Windows NT4, 在此系统上运行任何使用 Process command 的脚本需要一个 psapi.dll 的副本 (存在于 AutoHotkey 文件夹).

[AHK_L 51+]: 重命名 AutoHotkey.exe 文件会同时改变 默认情况下 它运行的脚本, 这是在没有安装 AutoHotkey 的计算机上运行脚本的一种可选方法. 例如, 没有指定文件名执行 MyScript.exe 会自动运行 MyScript.ahk, 但也能运行其他脚本.

安装程序选项

要静默安装 AutoHotkey 到默认目录 (这与手动安装显示的目录相同), 向安装程序传递 /S 参数 (/S 必须是大写的). 例如:

AutoHotkey104307_Install.exe /S

可以参数 /D 指定默认目录外的其他目录作为安装目录 (未使用 /S 参数时, 这样可以改变显示在安装程序中的默认目录). 例如:

AutoHotkey104307_Install.exe /S /D=C:\Program Files\AutoHotkey

要静默卸载 AutoHotkey, 向卸载程序传递 /S 参数. 例如:

"C:\Program Files\AutoHotkey\uninst.exe" /S

脚本展示

参见 这个页面 了解一些有用的脚本.


Variables and Expressions

变量和表达式

目录

  • 变量
  • 表达式
  • 表达式中的运算符
  • 内置变量
  • 环境变量与 普通变量
  • 变量的容量和占用内存

变量

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

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

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

考虑到命名的惯例, 通常在命名变量时最好仅使用字母, 数字和下划线 (例如: 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 := ""

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

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

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 是真还是假.

单词 true 和 false 是分别包含 1 和 0 的内置变量. 使用它们可以让脚本更具有可读性, 例如:

CaseSensitive := false
ContinueSearch := true

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

不论在表达式中还是表达式外的其他地方, 整数都可以写为十六进制或十进制. 十六进制数必须以前缀 0x 开头. 例如, Sleep 0xFF 等同于 Sleep 255. 在 1.0.46.11+ 版本中, 可以识别科学计数法表示的浮点数; 但仅在它们含有小数点时才行 (例如 1.0e4 and -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%)
x.y | [AHK_L 31+]: 对象访问. 从对象 x 中取值或为其存入值或调用其方法, 这里的 y 是个原义值. 参见 对象的语法.
++
-- 		前置和后置的自增/自减. 将变量增加或减去 1 (但在 1.0.46 之前的版本中, 只有把它们放在一行中才能用; 此行中不能使用其他运算符). 此运算符可以放在变量名的前面或后面. 如果把它放在变量名的 前面, 自增运算立即执行并且把结果用于后面的运算. 例如, Var := ++X 让 X 立即自增然后把它的值赋给 Var. 相反地, 如果运算符放在变量名的 后面, 在后面的运算使用了变量 之后 才对其进行自增运算. 例如, Var := X++ 把 X 的当前值赋给 Var 后才进行自增. 由于向后兼容性, 仅在空变量在单独一行时运算符 ++ 和 -- 才把它们视为零; 例如, y:=1, ++x 和 MsgBox % ++x 当 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 和 ! 的含义相同, 但 ! 优先级更高. 在 1.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*=2 和 Var:=Var*2 得到相同的结果 (不过前者执行的更好).

除数为零时得到一个空结果 (空字符串).
+
-

加 (+) 和 减 (-). 相关提示, += 和 -= 运算符是增加或减小变量的值的一种简写形式. 例如, Var+=2 和 Var:=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)

以句点 (或任何其他运算符) 开始的行会自动 附加到 前一行的末尾.
> <
>= <= 		大于 (>), 小于 (<), 大于或等于 (>=) 和 小于或等于 (<=). 如果任何一个输入都不是数字, 则按字母顺序比较 (被引号包围的原义字符串例如 "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+=1 和 MsgBox % x-=3 当 x 为空时都得到空的结果.
,

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

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

mod()
round()
abs()

 这些和其他内置数学函数在 这里 阐述.
F(p*) | [AHK_L 60+]: 参见 可变参数函数.
x[y] | [AHK_L 31+]: 对象访问. 从对象 x 中取值或为其存入值或调用其方法, 这里的 y 是个参数列表. 参见 对象的语法.

性能: 表达式赋值运算符 (:=) 已经优化, 所以在类似下列的简单情况中可以执行得和非表达式运算符 (=) 一样快速:

x := y  ; 性能等同于 x = %y%
x := 5  ; 性能等同于 x = 5.
x := "literal string"  ; 性能等同于 x = literal string.

在 1.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 | 当前脚本所在目录的绝对路径. 为了向后兼容 AutoIt v2, 只为 .aut 脚本包含 路径末尾的反斜线 (甚至根目录也是如此). 一个对应于 .aut 脚本的示例: C:\My Documents\
A_ScriptName | 当前脚本的文件名称, 不含路径, 例如 MyScript.ahk.
A_ScriptFullPath | 上面两个变量的组合, 包含了当前脚本的完整文件描述, 例如 C:\My Documents\My Script.ahk
A_LineNumber | 当前脚本中正在执行的行所在的行号 (或其 #Include 文件 的行号). 这里的行号与 ListLines 显示的一致; 它在错误报告时比较有用, 例如: MsgBox Could not write to log file (line number %A_LineNumber%). 由于 已编译脚本 已经把其所有的 #Include 文件 合并成一个大脚本, 它的行号可能与它在未编译模式运行时不一样.
A_LineFile | A_LineNumber 所属文件的完整路径和名称, 除非当前行属于未编译脚本的某个 #Include 文件, 否则它将和 A_ScriptFullPath 一样.
A_ThisFunc [v1.0.46.16+] | 当前正在执行的 自定义函数 的名称 (没有则为空); 例如: MyFunction. 也请参见: IsFunc()
A_ThisLabel [v1.0.46.16+] | 当前正在执行的标签 (子程序) 的名称 (没有则为空); ; 例如: MyLabel. 每当脚本执行 Gosub/Return 或 Goto 时, 会更新此变量的值. 执行自动调用的标签例如 计时器, GUI 线程, 菜单项, 热键, 热字串, OnClipboardChange 和 OnExit 时也会更新此变量的值, 不过, 当执行从前面的语句 "进入" 一个标签时 A_ThisLabel 的值不会更新; 此时 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 版本中, 此变量值为 1 (真). 在 ANSI 版本中此变量未定义, 所以实际上为假.
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 | 符合 ISO 8601 标准的当前的年份和周数 (例如 200453). 要让年份和周数分离, 使用 StringLeft, Year, A_YWeek, 4 和 StringRight, Week, A_YWeek, 2. A_YWeek 的准确定义为: 如果含有新年一月一号的那个星期有四天或更多天, 则它被认为是新年的第一个星期. 否则它为前一年的最后一个星期, 而下一星期为新年的第一星期.
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% milliseconds have elapsed.

如果你需要比 A_TickCount 的 10 毫秒更高的精确度, 使用 QueryPerformanceCounter().

脚本设置

A_IsSuspended | 当前脚本 挂起时 值为 1, 否则为 0.
A_IsPaused [v1.0.48+] | 当紧随当前线程的 线程 被 暂停 时值为 1. 否则为 0.
A_IsCritical [v1.0.48+] | 当 当前线程 的 Critical 设置为 off 时值为 0. 否则它的值为一个大于零的整数, 即 Critical 使用的 消息检查频率. 由于 "Critical 0" 关闭了当前线程的关键性, Critical 的当前状态可以这样来保存和恢复: Old_IsCritical := A_IsCritical, 后来执行 Critical %Old_IsCritical%
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_FileEncoding | [AHK_L 46+] 包含了多种命令使用的默认编码; 参见 FileEncoding.
A_FormatInteger | 由 SetFormat 设置的当前整数格式 (H 或 D). [AHK_L 42+]: 此变量还可能为小写形式 h.
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, 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 菜单项或 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 键, 空格, 带下划线的快捷键等) 触发的. 此变量的值还可以用于菜单项和特殊的 Gui 事件例如 GuiClose 和 GuiEscape.

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

RightClick: 仅出现在 GuiContextMenu, ListView 和 TreeView.

Context-sensitive values: 了解详情参见 GuiContextMenu, GuiDropFiles, Slider, MonthCal, ListView 和 TreeView.
A_EventInfo

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

  • OnClipboardChange 标签
  • 鼠标滚轮热键 (WheelDown/Up/Left/Right)
  • RegisterCallback()
  • GUI 时间, 即 GuiContextMenu, GuiDropFiles, ListBox, ListView, TreeView 和 StatusBar. 如果一个事件没有额外的信息, A_EventInfo 的值为 0.

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

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

A_ThisMenuItem | 最近选择的 自定义菜单项 的名称 (没有则为空).
A_ThisMenu | A_ThisMenuItem 所在菜单的名称.
A_ThisMenuItemPos | 一个表示 A_ThisMenuItem 在 A_ThisMenu 当前 位置的编号. 菜单中的首个项目为 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\UserName\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_7 [需要 AHK_L 42+], 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 This script requires Windows 2000/XP or later.
    ExitApp
}
A_PtrSize | [AHK_L 42+]: 包含指针的大小值, 单位为字节. 值为 4 (32-位) 或 8 (64-位).
A_Language | 当前系统的默认语言, 值为 这些 4 位数字编码 的其中一个.
A_ComputerName | 网络上可以看到的当前计算机的名称.
A_UserName | 运行当前脚本的用户的登录名.
A_WinDir | Windows 目录. 例如: C:\Windows
A_ProgramFiles
或 ProgramFiles 		Program Files 目录 (例如 C:\Program Files). 在 1.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 95/98/Me 系统中, 此变量的值总是为 1.

在 Windows Vista 或更高版本的系统中, 一些脚本可能要求管理员权限才能正常运行 (例如与使用管理员权限执行的进程和窗口进行交互的脚本). 为了实现此目的, 把下列语句添加到脚本的顶部:

if not A_IsAdmin
{
   Run *RunAs "%A_ScriptFullPath%"  ; 需要 AHK_L 57+
   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 使得坐标相对于整个屏幕, 默认坐标相对于活动窗口. 如果没有活动窗口或无法确定文本插入点的位置, 这两个变量为空. 下面这个脚本可以让你四出移动文本插入点来查看显示在自动更新提示上的当前位置. 注意在某些窗口 (例如某些版本的 MS 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.
A_LastError | 操作系统 GetLastError() 函数或最近的 COM 对象调用返回的结果. 要了解详情, 参见 DllCall() 和 Run/RunWait.

循环

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

环境变量与 "普通" 变量

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

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

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

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

变量的容量和占用内存

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


函数

目录

  • 入门和简单示例
  • 参数
  • 可选参数
  • 可变参数函数
  • 局部变量
  • 动态调用函数
  • 优化布尔求值
  • 在函数中使用子程序
  • Return, Exit, 和一般说明
  • 使用 #Include 在多个脚本间共享函数
  • 函数库: 标准库和用户库
  • 内置函数

入门和简单示例

函数类似于子程序 (Gosub), 不过它可以从其调用者那里接受参数 (输入). 此外, 它还可以返回值给其调用者. 思考后面这个接受两个数字并返回它们的和的简单函数:

Add(x, y)
{
    return x + y   ; "Return" 要求一个 表达式.
}

上面的被成为函数 定义 因为它创建了一个名称为 "Add" (不区分大小写) 的函数并且确立了调用它时必须确切地提供两个参数 (x 和 y). 要调用此函数, 把它的结果通过 := 运算符 赋值给一个变量. 例如:

Var := Add(2, 3)  ; 数字 5 将被保存到 Var 中.

并且, 调用函数时可以不保存其返回值:

Add(2, 3)

但在这样的情况中, 任何函数返回的值会被丢弃; 所以除非函数产生了返回值外的其他效果, 否则这个调用没有意义.

因为函数调用是一个 表达式, 任何在其参数列表中的变量名称都不应该包围在百分号中. 与之相比, 原义的字符串应该包围在双引号中. 例如:

if InStr(MyVar, "fox")
    MsgBox The variable MyVar contains the word fox.

最后, 可以在任何命令的参数中调用函数 (除了像 StringLen 命令中的那些 OutputVar 和 InputVar 参数). 然而, 不支持 表达式 的参数必须使用 "% " 前缀, 例如:

MsgBox % "The answer is: " . Add(3, 2)

在原生支持表达式的参数中也允许使用 "% " 前缀, 但它会被简单的忽略.

参数

一个函数被定义时, 其参数都列出在其名称后面的括号中 (在其名称和开括号之间不能含有空格). 如果函数不接受任何参数, 把括号留空; 例如: GetCurrentTimestamp().

ByRef 参数: 从函数角度看, 参数的实质是 局部变量 除非它们被定义为 ByRef 类型, 例如:

Swap(ByRef Left, ByRef Right)
{
    temp := Left
    Left := Right
    Right := temp
}

在上述例子中, ByRef 的使用让每个参数变成从调用者传递进来的变量的一个别名. 换句话说, 参数和调用者的变量都引用内存中相同的内容. 这样允许 Swap 函数通过移动 Left 的内容到 Right 中来修改调用者的变量, 反之亦然.

与之相比, 在上述例子中如果没有使用 ByRef, Left 和 Right 将是调用者变量的副本, 因此 Swap 不会产生外部影响.

由于 return 只能送回一个值给函数调用者, 所以可以使用 ByRef 送回更多的结果. 这是由函数向调用者传递进来的变量 (通常为空) 储存一个值来实现的.

当传递大量字符串到函数时, ByRef 提高了性能并且通过避免生成字符串的副本节约了内存. 同样地, 使用 ByRef 送回一个长字符串给调用者通常比一些方式例如 Return HugeString 执行的更好.

[AHK_L 60+]: 如果不是可修改的变量被传递给 ByRef 参数, 函数表现的就像关键字 "ByRef" 没有那样. 例如, Swap(A_Index, i) 保存 A_Index 的值到 i, 但是一旦 Swap 返回后赋值给 Left 的值被丢弃了.

已知限制:

  • 不能向函数的 ByRef 参数传递 Clipboard, 内置变量 或 环境变量, 即使脚本中没有 #NoEnv 时.
  • 尽管一个函数可以递归调用它自身, 如果它传递它自己的一个 局部变量 或非 ByRef 参数给自身的 ByRef, 新一层的 ByRef 参数将引用它自身那个名称的局部变量而不是之前层的. 然而, 当函数传递给它自身一个 全局变量, 静态变量 或 ByRef 参数时不会产生这样的问题.
  • 如果一个参数在函数调用中被解析为一个变量(例如 Var 或 ++Var 或 Var*=2), 它左边或右边的其他参数可以在它被传递给函数前修改这个变量. 例如, func(Var, Var++) 会意外地传递 1 和 0 当 Var 初始为 0 时, 即使函数的首个参数不是 ByRef 类型. 因为这种行为是违反常规的, 可能在将来的版本中改变.

可选参数

定义一个函数时, 可以把它的一个或多个参数标记为可选的. 这可以通过在参数后添加一个等号后面跟着默认值实现. 后面的函数中其 Z 参数被标记为可选的:

Add(X, Y, Z=0) {
    return X + Y + Z
}

当调用者传递 三个 参数给上面的函数时, 参数 Z 的默认值被忽略. 但当调用者仅传递 两个 参数时, Z 自动获取默认值 0.

可选参数不能被孤立地放在参数列表的中间. 换句话说, 在首个可选参数右边的所有参数都必须标记为可选的. [AHK_L 31+]: 调用函数时参数列表中间的可选参数可以省略, 除非是函数调用是动态的:

Func(1,, 3)
Func(X, Y=2, Z=0) {  ; 注意此时 Z 必须是可选的.
    MsgBox %X%, %Y%, %Z%
}

在 1.0.46.13+ 版本中, ByRef 参数 也支持默认值; 例如: Func(ByRef p1 = ""). 每当调用者省略这样的参数时, 函数会创建一个包含默认值的局部变量; 换句话说, 函数表现的就像关键字 "ByRef" 没有那样.

参数的默认值必须是下列形式的其中一种: 真, 假, 原义的整数, 原义的浮点数或引号包围的/原义的字符串如 "fox" 或 "" (但在 1.0.46.13+ 之前的版本中字符串只支持 "").

可变参数函数 [AHK_L 60+]

定义一个函数时, 在最后一个参数后面写一个星号来标记此函数为可变参数的, 允许它接收可变数目的参数:

Join(sep, params*) {
    for index,param in params
        str .= param . sep
    return SubStr(str, 1, -StrLen(sep))
}
MsgBox % Join("`n", "one", "two", "three")

调用可变参数函数时, 通过保存在函数的最后参数中的对象可以访问剩余的参数. 函数的首个剩余参数在 params[1], 第二个在 params[2] 等等. 和所有标准对象一样, 使用 params.MaxIndex() 可以确定最大的索引值 (此时为参数的数目). 但是, 如果没有参数, MaxIndex 返回一个空字符串.

由于需要为参数列表创建一个新对象, 最简单的可变参数函数允许使用方便的简写形式创建数组:

; 创建数组的方法有三种:
arr := Object(1, x, 2, y, 3, z)
arr := Object(), arr.Insert(1, x, y, z)
arr := Array(x, y, z)

Array(values*) {
    return values
}

请注意:

  • "可变" 参数只可以出现在形式参数列表的末尾.
  • RegEx callouts 的函数不能是可变参数函数; 允许使用 "可变" 参数但必须留空.
  • Callbacks 通过地址 而不是数组传递剩余的参数.

可变参数函数调用

虽然可变参数函数可以 接受 可变数目的参数, 不过在函数调用中使用相同的语法可以把参数组成的数组传递给 任何 函数或 对象 getter/setter:

substrings := Object(), substrings._Insert(1, "one", "two", "three")
MsgBox % Join("`n", substrings*)

请注意:

  • 在源数组中参数的编号从 1 开始.
  • 数组中可选参数可以完全省略.
  • 数组中的参数可以通过编号或名称传递.
  • 目标函数也可以是可变参数的, 此时命名项目被复制即使它们没有一致的形式参数.

已知限制:

  • 只有实际中最后一个参数可以用这种方法展开. 例如, Func(x, y*) 是支持的但 Func(x*, y) 不支持.
  • 在星号 (*) 和参数列表中最后的形式参数之间不能存在任何非空白字符.
  • 对象 getters/setters/methods 不支持命名参数.

局部变量和全局变量

局部变量

默认情况下在函数中创建或引用的所有变量都是 局部 的 (除了内置变量例如 Clipboard, ErrorLevel, 和 A_TimeIdle). 每个局部变量的内容只在它所在的函数中可见. 因此, 一个局部变量可以和一个全局变量有相同的名称却有着不同的内容. 最后, 所有的局部变量在函数被调用时都以空值开始.

全局变量

要在函数中引用一个已有的全局变量 (或创建一个新的), 需要在使用前声明此变量为全局的. 例如:

LogToFile(TextToLog)
{
    global LogFileName  ; 此全局变量之前已经在函数外的某个地方赋值了.
    FileAppend, %TextToLog%`n, %LogFileName%
}

假设全局模式: 如果一个函数需要引用或创建大量的全局变量, 通过在函数的首行使用单词 "global" 或声明一个局部变量可以把函数定义为假设其所有的变量都是全局的 (除了它的参数). 例如:

SetDefaults()
{
    global  ; 如果函数的首行是类似于 "local MyVar" 这样的, 那么这个单词可以省略.
    MyGlobal := 33  ; 把 33 赋值给一个全局变量, 必要时首先创建变量.
    local x, y:=0, z  ; 在这种模式中局部变量必须进行声明, 否则它们被假设为全局的.
}

函数还可以使用这种假设全局模式来创建全局 数组, 例如循环赋值给 Array%A_Index%.

静态变量

静态变量总是隐式的局部变量, 但和局部变量的区别是它们的值在多次调用期间是记住的. 例如:

LogToFile(TextToLog)
{
    static LoggedLines = 0
    LoggedLines += 1  ; 保持局部的计数 (它的值在多次调用期间是记住的).
    global LogFileName
    FileAppend, %LineCount%: %TextToLog%`n, %LogFileName%
}

静态初始化: 在 1.0.46 以前的版本中, 所有的静态变量都是以空值开始; 所以要检查一个静态变量首次被使用的唯一方法是检查它是否为空值. 在 1.0.46+ 版本中, 静态变量可以初始化为 "" 外的其他值, 通过后面跟着 := 或 = 和下列形式的其中一种: 真, 假, 原义的整数, 原义的浮点数或引号包围的/原义的字符串如 "fox". 例如: static X:=0, Y:="fox". 每个静态变量只初始化一次 (在脚本开始执行前).

[AHK_L 58+]: Static var := expression 被支持. 在自动执行段前, 根据脚本中出现的顺序所有这样的表达式都被立即计算.

假设静态模式 [v1.0.48+]: 通过在函数的首行使用单词 "static" 可以把函数定义为假设其所有的变量都是静态的 (除了它的参数). 例如:

GetFromStaticArray(WhichItemNumber)
{
    static
    static FirstCallToUs := true  ; A static declaration's initializer still runs only once (upon startup).
    if FirstCallToUs  ; Create a static array during the first call, but not on subsequent calls.
    {
        FirstCallToUs := false
        循环 10
            StaticArray%A_Index% := "Value #" . A_Index
    }
    return StaticArray%WhichItemNumber%
}

在假设静态模式中, 任何非静态变量都必须声明为局部变量或全局变量.

关于局部和全局的更多信息

如这些例子演示的那样, 通过逗号分隔多个变量从而在同一行声明:

global LogFileName, MaxRetries := 5
static TotalAttempts = 0, PrevResult

在 1.0.46+ 版本中, 一个局部或全局变量可以在同一行初始化如同声明那样, 通过后面跟着 := 或 = 和任意 表达式 (在声明中 = 运算符作用等同于 := ). 与 静态初始化 不同, 在每次调用函数时都执行局部变量和全局变量的初始化, 但仅当控制流实际到达它们所在语句时. 换句话说, 一行像 local x = 0 和写成两个单独的行有相同的效果: local x 后面跟着 x = 0.

因为单词 local, global, 和 static 是在脚本运行时立即处理的, 所以不能使用 IF 语句 有条件的声明变量. 换句话说, IF 或 ELSE 的 区块 内的声明无条件对在声明和函数的闭括号之间的所有行生效. 同时注意目前还不能声明动态变量例如 global Array%i%.

对于创建 数组 的命令 (例如 StringSplit), 如果 假设全局模式 没有生效或数组的首个元素已经声明为局部变量时创建的数组是局部的 (如果函数的某个参数被传递时也是这样 -- 即使此参数为 ByRef 类型 -- 因为参数与局部变量相似). 相反地, 如果首个元素已经 声明为全局的, 则创建全局数组. StringSplit 的首个元素为 ArrayName0. 对于其他创建数组的命令例如 WinGet List, 首个元素为 ArrayName (即没有数字).

在函数中, 任何动态变量引用例如 Array%i% 总是解析为局部变量除非不存在这样名称的变量, 此时如果存在全局变量则使用全局变量. 如果两者都不存在那么需要先创建变量才能使用, 当 假设全局模式 模式没有生效时它被创建为局部变量. 因此, 仅当函数被定义为 假设全局 函数时, 函数中才可以手动创建全局 数组 (例如使用 Array%i% := A_Index 的方法).

常见疑点: 任何对变量的 非 动态引用都会在脚本运行时创建那个变量. 例如, 在函数外使用, MsgBox %Array1% 会在脚本运行的时候创建 Array1 为全局变量. 相反地, 在函数中使用 MsgBox %Array1% 会在脚本运行的时候创建 Array1 为函数的一个局部变量(除非 假设全局 模式生效).

动态调用函数

在 1.0.47.06+ 版本中, 可以通过百分号动态调用一个函数 (即使是 内置函数) . 例如, %Var%(x, "fox") 将调用名称保存在 Var 中的函数. 同样地, Func%A_Index%() 将调用 Func1() 或 Func2() 等., 取决于 A_Index 的当前值.

如果函数由于后面的某个原因不能被调用, 包含调用的表达式的计算结果会过早静默地停止, 这样可能会导致不合理的结果:

  • 通过使用 If IsFunc(VarContainingFuncName) 可以避免调用一个不存在的函数. 除了 内置函数, 被调用的其他函数的 定义 必须明确存在于脚本中, 通过例如 #Include 或对 库函数 的非动态调用的方法.
  • 通过检查 IsFunc() 的返回值 (这是必须参数的数目加上一的数字) 可以避免传递太少的参数. 注意: 在 1.0.48+ 版本中, 允许传递过多的参数; 每个额外的参数都被完全计算 (包括任何函数调用) 后丢弃.
  • 传递不适当的值给 a ByRef 参数.

最后, 对函数的动态调用比正常调用稍慢因为正常的调用在脚本开始运行前解析 (查询).

优化布尔求值

当在 表达式 中使用 AND, OR 和 三元运算符 时, 为了提高性能而优化它们 (不管当前是否有函数调用). 通过不计算表达式中那些不能影响它的最终结果的部分来实行优化运算. 为了说明这个观点, 请看此例:

if (ColorName <> "" AND not FindColor(ColorName))
    MsgBox %ColorName% could not be found.

在这个例子中, 如果 ColorName 变量为空的则永远不会调用 FindColor() 函数．　 这是由于 AND 的左侧结果将为 false, 因此其右边不可能让最终的结果为 true.

由于此特性, 所以必须明白, 如果在 AND 或 OR 的右侧调用函数, 函数可能永远不会产生副作用 (例如改变全局变量的内容).

同时也需要注意在嵌套的 AND 和 OR 串联表达式的求值优化. 例如, 在后面的表达式中, 每当 ColorName 为空时只会进行最左边的比较. 这是因为此时最左边的比较已经足够确定最终的结果:

if (ColorName = "" OR FindColor(ColorName, Region1) OR FindColor(ColorName, Region2))
    break   ; 搜索内容为空或找到了一个匹配.

从上面的例子可以看出, 任何耗时的函数一般应该在 AND 或 OR 的右侧调用从而提高性能. 这个方法还能避免调用接受了一个不合适的值例如空字符串的函数.

在 1.0.46+ 版本中, 三元条件运算符 (?:) 也通过不计算丢弃的分支进行求值优化.

在函数中使用子程序

尽管在一个函数中不能 定义 其他函数, 但它可以含有子程序. 与其他子程序一样, 使用 Gosub 运行它们而使用 Return 返回 (这里的 Return 属于 Gosub 而不是函数).

已知限制: 当前每个子程序 (标签) 的名称在整个脚本中必须是唯一的. 如果存在重复的标签, 程序在运行时将通知你.

如果一个函数使用 Gosub 跳转到一个公共子程序 (在函数外面的子程序), 所有外面的变量都是全局的而且在子程序返回前无法引用函数自身的 局部变量. 但是, 此时 A_ThisFunc 仍将包含正在执行的函数名称.

尽管 Goto 到函数外的语句被忽略, 但是可以在函数中使用 Gosub 到外部的/公共的子程序然后在那里使用 Goto.

尽管一般不鼓励使用 Goto, 但它能用来在同个函数中的一个位置跳转到其他位置. 这样有助于简化包含许多个返回点而所有这些点在返回前需要进行一些清理的复杂函数.

一个函数可以包含被外部调用的子程序例如 计时器, GUI g 标签, 和 菜单项. 通常把它们封装到一个单独的文件中供 #Include 使用, 这样避免了它们和脚本的 自动执行段 的冲突. 不过, 还有下面这些限制:

  • 如果它们所在的函数曾经被正常调用, 这样的子程序应该只使用 静态 和 全局 变量 (不使用 局部 变量). 这是由于中断函数调用线程的子程序 线程 (反之亦然) 可以改变被中断线程看到的局部变量的值. 此外, 在任何时候函数返回到其调用者时, 它包含的所有局部变量都被置空来释放占用的内存.
  • 这样的子程序应该只使用 全局变量 (不使用 静态变量) 作为 GUI 控件的变量.
  • 当一个子程序 线程 进入函数后, 在此线程中任何对 动态变量 的引用都被视为是 全局 的 (包括创建数组的命令).

Return, Exit, 和一般说明

如果函数内的执行流在遇到 Return 前到达了函数的闭括号, 那么函数结束并返回一个空值 (空字符串) 给其调用者. 每当函数明确的省略 Return 的参数时也返回一个空值.

当函数使用 Exit 命令终止 当前线程 时, 其调用者不会接收到返回值. 例如, 这个语句 Var := Add(2, 3) 中如果 Add() 退出了那么 Var 将保持不变. 如果函数出现了运行时错误例如 运行 一个不存在的文件 (当 UseErrorLevel 无效时), 也将发生同样的事情.

为了返回一个额外的容易记住的值函数可以修改 ErrorLevel 的值.

要使用一个或多个空值 (空字符串) 调用函数, 可以使用空的引号对, 例如: FindColor(ColorName, "")

因为调用函数不会开启一个新 线程, 函数对设置例如 SendMode 和 SetTitleMatchMode 做出的任何改变对其调用者同样有效.

函数的调用者可以传递一个不存在的变量或 数组 元素给它, 当函数期望和 ByRef 一致的参数时这很有用. 例如, 调用 GetNextLine(BlankArray%i%) 将创建变量 BlankArray%i% 自动地作为 局部 或全局的 (取决于调用者是否在函数内并且它的 假设全局模式 是否生效).

在函数中使用 ListVars 时, 它会显示函数的 局部变量 及其内容. 这样有助于调试脚本.

风格和命名规则

你会发现如果给复杂函数中的特殊变量加上独特的前缀, 会让函数更容易阅读和维护. 例如, 使用 "p" 或 "p_" 开头来命名函数中的每个参数可以让它们的性质一目了然, 尤其是当函数有许多 局部变量 吸引你注意力的时候. 同样地, 前缀 "r" 或 "r_" 可以用于 ByRef 参数, 而 "s" 或 "s_" 可以用于 静态变量.

定义函数时可以使用 One True Brace (OTB) 风格. 例如:

Add(x, y) {
    return x + y
}

使用 #Include 在多个脚本间共享函数

可以使用 #Include 指令 (即使在脚本的顶部) 从外部文件中加载函数.

说明: 当脚本的执行流遇到函数定义时, 它会跳过函数 (使用一种瞬时的方法) 并在函数闭括号后面的行恢复执行. 因此, 开始执行时执行流不会陷入函数中, 也不会因为在脚本的最顶部存在一个或多个函数而影响到 自动执行段.

函数库: 标准库和用户库 [v1.0.47+]

脚本可以不需要使用 #Include 调用外部文件中的函数. 要达到此目的, 一个和函数相同名称的文件必须存在于后面库目录的其中一个里:

%A_ScriptDir%\Lib\  ; 局部库 - 要求 AHK_L 42+.
%A_MyDocuments%\AutoHotkey\Lib\  ; 用户库.
path-to-the-currently-running-AutoHotkey.exe\Lib\  ; 标准库.

例如, 如果脚本调用一个不存在的函数 MyFunc(), 程序会在用户库中搜索名为 MyFunc.ahk 的文件. 如果这里没找到, 继续在标准库中搜索此文件. 如果仍没找到匹配的文件并且函数的名称包含一个下划线 (例如 MyPrefix_MyFunc), 程序会在两个库中搜索名为 MyPrefix.ahk 的文件如果找到则装载它. 这样使得 MyPrefix.ahk 可以同时包含 MyPrefix_MyFunc 函数和其他名称以 MyPrefix_ 开始的相关函数.

[AHK_L 42+]: 支持局部库并且局部库优先于用户库和标准库.

虽然一个库文件通常只包含和它的文件名称相同的单个函数, 但它还可以包含仅被此函数调用的私有函数和子程序. 然而, 这样的函数应该使用相当特殊的名称因为它们仍属于全局命名空间; 也就是说, 可以在脚本的任意位置调用它们.

如果在库文件中使用 #Include, #Include 的工作目录为库文件自身所在的目录. 这可以用来创建一个重定向到一个较大的库文件, 其中包含此函数和其他相关内容.

脚本编译器 (ahk2exe) 同样支持库函数. 不过, 它要求在编译器目录的上一级目录中存在一个 AutoHotkey.exe 的副本 (正常情况下是这样). 如果不存在 AutoHotkey.exe, 编译器仍可以运行但无法自动包含库函数.

包含在库中的函数和其他函数执行的一样好因为它们在脚本开始执行前已经被预加载了.

内置函数

在内置函数参数列表末尾的任何可选参数可以完全省略. 例如, WinExist("Untitled - Notepad") 是有效的, 它的其他三个参数被看成是空的.

如果脚本定义了与内置函数同名的函数, 那么内置函数会被覆盖. 例如, 脚本会调用它自己定义的 WinExist() 函数来代替标准的那个. 然而, 这样脚本将无法调用原始的函数.

在 DLL 文件中的外部函数可以使用 DllCall() 调用.

常用函数

FileExist(FilePattern): 如果 FilePattern 不存在 (如果未指定绝对路径则假定 FilePattern 在 A_WorkingDir 中) 则返回一个空值 (空字符串). 否则, 它返回首个匹配的文件或文件夹的 属性字符串 ("RASHNDOCT" 的子集). 如果文件没有属性 (很少见), 则返回 "X". FilePattern 可以是一个文件或文件夹的准确名称, 或者包含通配符 (* or ?). 由于空字符串被视为 "false", 所以函数的返回值总是可以作为一个准布尔值来使用. 例如, 语句 if FileExist("C:\My File.txt") 文件存在时将为真否则为假. 同样地, 语句 if InStr(FileExist("C:\My Folder"), "D") 仅当文件存在 并且 是个目录时才为真. 相关命令: IfExist 和 FileGetAttrib.

GetKeyState(KeyName [, "P" or "T"]): 与 GetKeyState 命令 不同 -- 它在按下时返回 D 而在弹起时返回 U -- 此函数当按下时返回真 (1) 而弹起时返回假 (0). 如果 KeyName 无效, 则返回一个空字符串. 参见 GetKeyState 了解其他返回值和用法.

InStr(Haystack, Needle [, CaseSensitive = false, StartingPos = 1, Occurrence = 1]): 返回字符串 Needle 在字符串 Haystack 中出现的位置. 与 StringGetPos 不同, 首个字符位置为 1; 这是由于 0 相当于 "假", 使其成为一个直观的 "未找到" 的提示. 如果参数 CaseSensitive 省略或为 false, 搜索不区分大小写 (不区分的模式取决于 StringCaseSense); 否则, 大小写必须准确匹配. 如果 StartingPos 省略, 默认为 1 (Haystack 的起点). 否则, 指定 2 从 Haystack 的第二个字符开始, 指定 3 从第三个开始等. 如果 StartingPos 超过了 Haystack 的长度, 则返回 0. 如果 StartingPos 为 0 或负数, 搜索将从末尾的偏移开始反向进行 (从右到左). 不管 StartingPos 的值是多少, 返回的位置总是相对于 Haystack 的首个字符. 例如, "abc" 在 "123abc789" 中的位置总为 4. 在 Occurrence 参数中指定 2 来返回第二个匹配的位置, 3 为第三个等. 相关项目: RegExMatch(), IfInString, 和 StringGetPos.

RegExMatch(Haystack, NeedleRegEx [, UnquotedOutputVar = "", StartingPos = 1]): 参见 RegExMatch ().

RegExReplace(Haystack, NeedleRegEx [, Replacement = "", OutputVarCount = "", Limit = -1, StartingPos = 1]): 参见 RegExReplace ().

SubStr(String, StartingPos [, Length]) [v1.0.46+]: 在 String 中从 StartingPos 开始向右复制不超过 Length 长度的子字符串 (如果 Length 省略, 默认为 "所有字符"). 对于 StartingPos, 指定 1 从首个字符开始, 2 从第二个开始等 (如果 StartingPos 超过了 String 的长度, 则返回一个空字符串). 如果 StartingPos 小于 1, 它被看成是从字符串末尾开始的偏移. 例如, 0 提取最后一个字符而 -1 提取最后两个字符 (但如果 StartingPos 超过了字符串的左端, 提取又从首个字符开始). Length 是需获取的字符的最大数目 (每当字符串剩余部分太短时获取的数目会比最大值少). 指定一个负的 Length 从而在返回字符串的末尾省略这个数目的字符 (如果省略了全部或更多字符则返回一个空字符串). 相关项目: RegExMatch(), StringMid, StringLeft/Right, StringTrimLeft/Right.

StrLen(String): 返回 String 的长度. 如果 String 是之前由 ClipboardAll 所赋值的变量, 则返回其总大小. 相关命令: StringLen.

WinActive([WinTitle, WinText, ExcludeTitle, ExcludeText]): 如果活动窗口匹配指定的条件则返回其 唯一 ID (HWND). 如果不匹配, 函数返回 0. 因为所有非零值都被视为 "真", 语句 if WinActive("WinTitle") 每当 WinTitle 是活动时为真. 参数 WinTitle 支持 ahk_id, ahk_class, 和其他特殊字符串. 关于窗口激活的这些和其他相关信息请参见 IfWinActive 了解详情. 注意: 获取活动窗口的唯一 ID 的简便方法是使用 ActiveHwnd := WinExist("A")

WinExist([WinTitle, WinText, ExcludeTitle, ExcludeText]): 返回以十六进制整数表示的首个匹配窗口的 唯一 ID (HWND) (没有则为 0). 因为所有非零值都被视为 "真", 语句 if WinExist("WinTitle") 每当 WinTitle 存在时为真. 参数 WinTitle 支持 ahk_id, ahk_class, 和其他特殊字符串. 关于窗口搜索的这些和其他相关信息请参见 IfWinExist 了解详情.

杂项函数

Asc(String): 返回 String 中首个字符的 ASCII 码 (介于 1 到 255 之间的数字). 如果 String 为空, 则返回 0.

Chr(Number): 返回与 Number 表示的 ASCII 码对应的单个字符. 如果 Number 不是介于 1 和 255 及其之间, 则返回一个空字符串. 常用的 ASCII 码包括 9 (Tab), 10 (换行), 13 (回车), 32 (空格), 48-57 (数字 0-9), 65-90 (大写字母 A-Z), 和 97-122 (小写字母 a-z).

DllCall(): 参见 DllCall().

FileOpen(): 提供面向对象文件 I/O. 参见 FileOpen() 了解详情.

IsFunc(FunctionName) [v1.0.48+]: 如果 FunctionName 不是显式出现在脚本中 (通过这样的方法, 例如 #Include 或对 库函数 的非动态调用), IsFunc() 返回 0. 否则, 它返回函数最少的参数个数加一 (例如 1 为函数可以不需要参数, 2 为函数至少需要一个参数等). 例如, 语句 if IsFunc("MyFunc") 和 if IsFunc(VarContainingFunctionName) 函数存在时将为真, 否则为假. 也请参见: 动态函数调用, A_ThisFunc

IsLabel(LabelName): 如果 LabelName 作为 子程序, 热键 或 热字串 (不包括 LabelName 中末尾的冒号) 存在于脚本中则返回一个非零数字. 例如, 语句 if IsLabel(VarContainingLabelName) 标签存在时将为真, 否则为假. 在类似 Gosub, Hotkey, Menu 和 Gui 的命令中指定一个动态标签时, 使用此函数对避免运行时错误很有用. 也请参见: A_ThisLabel

IsObject() [AHK_L 31+]: 判断某个值是否为对象. 也请参见: Objects.

ListView 和 TreeView 函数: 参见 ListView 和 TreeView 页面了解详情.

NumGet(VarOrAddress [, Offset = 0][, Type = "UPtr"]) [v1.0.47+]: 返回在指定地址+偏移量存储的二进制数. 对于 VarOrAddress, 传递 MyVar 相当于传递 &MyVar. 然而, 省略 "&" 可以执行地更好并确保目标地址是 有效的 (无效的地址返回 ""). 与之相比, 传递给 VarOrAddress 除裸变量之外的任何东西都被视为原始地址; 因此, 指定 MyVar+0 强制使用 MyVar 中的数字代替 MyVar 自身的地址. 对于 Type, 可以指定为 UInt, Int, Int64, Short, UShort, Char, UChar, Double, Float 或 Ptr (不过与 DllCall 有些不同, 作为原义字符串使用时它们必须包围在引号中); 更多详情参见 DllCall 类型. [AHK_L 57+]: Offset 参数可以完全省略; 例如, NumGet(var, "int") 是有效的.

NumPut(Number, VarOrAddress [, Offset = 0][, Type = "UPtr"]) [v1.0.47+]: 以二进制格式把 Number 存储到指定地址+偏移量并且返回刚写入项目右边的地址. 对于 VarOrAddress, 传递 MyVar 相当于传递 &MyVar. 然而, 省略 "&" 可以执行地更好并确保目标地址是 有效的 (无效的地址返回 ""). 与之相比, 传递给 VarOrAddress 除裸变量之外的任何东西都被视为原始地址; 因此, 指定 MyVar+0 强制使用 MyVar 中的数字代替 MyVar 自身的地址. 对于 Type, 可以指定为 UInt, Int, Int64, Short, UShort, Char, UChar, Double, Float 或 Ptr (不过与 DllCall 有些不同, 作为原义字符串使用时它们必须包围在引号中+) (在 1.0.48+ 版本中支持 UInt64); 更多详情参见 DllCall 类型. 如果一个整数太大而不适合指定的 类型, 它最重要的字节被忽略了; 例如 NumPut(257, var, 0, "Char") 将存储数字 1. [AHK_L 57+]: Offset 参数可以完全省略; 例如, NumPut(x, var, "int") 是有效的.

OnMessage(MsgNumber [, "FunctionName"]): 监视消息/事件. 请参见 OnMessage() 了解详情.

StrGet(Address [, Length] [, Encoding = None ] ) [AHK_L 46+]: 从内存地址复制字符串, 并可以对其在不同代码页间进行转换. 请参见 StrGet() 了解详情.

StrPut(String, Address [, Length] [, Encoding = None ] ) [AHK_L 46+]: 复制字符串到内存地址, 并可以对其在不同代码页间进行转换. 请参见 StrPut() 了解详情.

RegisterCallback(): 参见 RegisterCallback().

Trim() [AHK_L 31+]: 参见 Trim().

VarSetCapacity(UnquotedVarName [, RequestedCapacity, FillByte]): 增加或清空变量占用的内存. 请参见 VarSetCapacity() 了解详情.

通用数学函数

注意: 如果任一传入参数是非数值的时数学函数通常返回一个空值 (空字符串).

Abs(Number): 返回 Number 的绝对值. 返回值的类型和 Number 相同 (整数或浮点数).

Ceil(Number): 返回由 Number 向上取整到最近的整数 (不带任何 .00 后缀). 例如, Ceil(1.2) 是 2 而 Ceil(-1.2) 是 -1.

Exp(N): 返回 e (其近似值为 2.71828182845905) 的 N 次幂. N 可以为负数也可以为小数. 要计算 e 以外的其他数的次幂, 使用 ** 运算符.

Floor(Number): 返回由 Number 向下取整到最近的整数 (不带任何 .00 后缀). 例如, Floor(1.2) 是 1 而 Floor(-1.2) 是 -2.

Log(Number): 返回 Number 的对数 (底数为 10). 结果格式化为 浮点数. 如果 Number 为负数, 则返回一个空字符串.

Ln(Number): 返回 Number 的自然对数 (底数为 e). 结果格式化为 浮点数. 如果 Number 为负数, 则返回一个空字符串.

Mod(Dividend, Divisor): 求模. 返回被除数 Dividend 除以除数 Divisor 后得到的余数. 结果的正负总是与被除数一致. 例如, mod(5, 3) 和 mod(5, -3) 都得到结果 2, 但 mod(-5, 3) 和mod(-5, -3) 得到结果 -2. 如果任何一个参数为浮点数, 那么结果也是浮点数. 例如, mod(5.0, 3) 是 2.0 而 mod(5, 3.5) 是 -1.5. 如果除数为零, 函数返回空值 (空字符串).

Round(Number [, N]): 如果 N 省略或为 0, 则 Number 被取整到最近的整数. 如果 N 为正数, 则 Number 被取整到 N 个小数位. 如果 N 为负数, 则 Number 被取整到十进制小数点左边 N 位. 例如, Round(345, -1) 结果为 350 而 Round (345, -2) 结果为 300. 与 Transform Round 不同, 每当 N 省略或小于 1 时结果不含 .000后缀. 在 1.0.44.01+ 版本中, 大于零的 N 值会准确显示 N 个小数位而不服从 SetFormat 的设置. 要避免这种情况, 对 Round() 的返回值再进行一次数学运算; 例如: Round(3.333, 1)+0.

Sqrt(Number): 返回 Number 的平方根. 结果格式化为 浮点数. 如果 Number 为负数, 则函数返回空值 (空字符串).

三角函数

Sin(Number) | Cos(Number) | Tan(Number) : 返回 Number 的正弦|余弦|正切三角函数值. Number 必须用弧度表示.

ASin(Number): 返回弧度表示的反正弦值 (其正弦值为 Number). 如果 Number 小于 -1 或大于 1, 则函数返回空值 (空字符串).

ACos(Number): 返回弧度表示的反余弦值 (其余弦值为 Number). 如果 Number 小于 -1 或大于 1, 则函数返回空值 (空字符串).

ATan(Number): 返回弧度表示的反正切值 (其正切值为 Number).

注意: 要将弧度转换成角度, 将其乘以 180/pi (约为 57.29578). 要将角度转换成弧度, 将其乘以 pi/180 (约为 0.01745329252). pi 的值 (约为 3.141592653589793) 为 1 的反正切值乘以 4.

其他函数

Titan 的命令函数: 为每个有 OutputVar 的 AutoHotkey 命令提供一个可调用的函数. 可以通过 #Include 把这个库包含在任何一个脚本中.


AutoIt v2 用户注意事项

优势

  • 享受针对 AutoIt v2 近乎完整的向后兼容性. 您可以不需要学习新语法和命令.
  • 在所有 IF-类型 的命令中都可以使用 Else.
  • 在 IF 和 ELSE 中可以使用 区块 (多行的部分) (实际上消除了 Goto 的需要).
  • 在 循环 内使用 break 和 continue (另一种消除 Goto 的方法).
  • 使用许多新命令和对旧命令的增强带来的好处 (见下面).
  • 当您还没有完全准备好使用它们时, 更早地 (载入时) 而不是后面 (运行时) 捕获到低级错误和拼写错误: 捕获语法错误作为 优化 程序的一部分.
  • 获得更好的启动 性能.

运行 AutoIt v2 (.aut) 脚本

大多数 .aut 脚本可以不需要改变而使用 AutoHotkey 运行. 只有以下的 AutoIt v2 特性不被支持:

  • Adlib 部分 (可以使用 SetTimer 代替)
  • Break (现在可以在 循环 中使用 break 代替)
  • HideAutoItDebug

把脚本从 .aut 转换为 .ahk

尽管 .aut 脚本可以运行, 但为了充分利用 AutoHotkey 的新特性带来的优势 (即如果您打算改进脚本) 您应该把脚本转换为 .ahk 文件. 因为一些命令接受新的可选参数, 而这些参数如果用在 AutoIt v2 脚本上会导致其中一些命令运行不正常 (参见较远的下面获取详情), 此时转换脚本是必须的.

您可以自动地把 AutoIt v2 (.aut) 脚本转换为 AutoHotkey 格式 (.ahk). 转换中将使用重音符 (`) 代替反斜线 (\) 作为 转义符. 由于在每行中转义序列准确顺序的原因, 转换比听起来更困难, 因此您不能仅仅在文本编辑器中进行搜索替换. 自动转换功能需要处理所有这些细节:

  1. 在现在的 .aut 文件名后附加　.ahk, 使得文件名以 ".aut.ahk" 结尾.
  2. 用 AutoHotkey 运行此文件, 与直接运行此文件不同, 此时将在同一个目录中创建一个文件名以 "-NEW.ahk" 结尾的新文件. 这是转换后的版本. 原来的文件保持不变.
  3. 如果您在脚本中使用了 #EscapeChar, 请从转换后的文件中删除.

把脚本从 .aut 转成 .ahk 后, 主要需要检查在 .ahk 文件中比 .aut 文件中支持额外参数的那些命令. 如果您在转换前文件的命令最后一个参数中使用了未转义的逗号而现在此参数不是最后一个参数, 此时这些逗号被看成分隔符. 例如:

WinActivate, title, text with literal comma, here.

上面这句在转换后就出现问题了. 字符串 "here." 将被看成是新的 "exclude title" 的参数.

下面是接受新参数而可能出问题的命令列表:
StringReplace
StringGetPos
FileSelectFile
 FileRemoveDir
WinClose/Kill/Activate/Minimize/Maximize/Restore/Hide/Show
WinSetTitle/WinGetTitle

注意: 即使有些命令在 .ahk 文件中接受新的参数, 像 IfWinExist 这样的命令也不会产生上述问题因为程序可以区分 AutoIt v2 和 AutoHotkey 的方法. WinWait 这一系列命令也不会出现问题, MsgBox 命令同样如此因为它可以智能的处理逗号.

改进的语法

除了少数例外, 所有命令都支持浮点数 (例如 3.5) 和十六进制标志 (例如 0xFF).

所有 IF 类型的命令中都支持关键字 ELSE. 同时也支持 区块. 例如:

原来的风格:

IfWinExist, Notepad, , WinActivate, Notepad

新风格 (需要执行多行时则使用 {…} 创建区块):

IfWinExist, Untitled - Notepad
{
    WinActivate   ; 不需要再次指定标题, 因为它将自动使用 "最近找到" 的窗口.
    WinMaximize  ; 如果没有这行, 这段可以不用区块
}
else
    Run Notepad

嵌套的 IF 和区块例子:

if varx = 1
{
    if vary = 2
        if varz = 3
            sleep, 1
        else  ; 此 else 和它上面最近的 IF 匹配
            sleep, 1
}
else  ; 此 else 和顶端的 IF 匹配因为区块防止它和 "if vary = y" 中的 if 匹配
    sleep, 1

同样, 区块也可以用于循环. 但在下面第一个例子中不需要区块因为 if+else 被看成单个语句:

Loop, 5000
    IfNotExist, c:\semaphore.txt
        sleep, 1000
    else
        break  ; 提前终止循环

这个例子需要区块:

Loop  ; 因为没有指定循环次数, 所以这是一个无限循环除非遇到 Exit, Return, 或 Break.
{
    ...
    if var <= 5
        continue  ; 跳过区块的剩余部分并从区块的顶部开始下一次循环.
    ...
    if var > 25
        break  ; 退出循环
}

浏览文件夹内容的 file-loop 的例子(也支持 registry-loops 和 parsing-loops)

Loop, %A_ProgramFiles%\*.txt, , 1  ; Recurse into subfolders.
{
    MsgBox, 4, , Filename = %A_LoopFileFullPath%`n`nContinue?
    IfMsgBox, No
        break
}

最后, 还支持 复杂的表达式 和 函数调用, 例如:

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

LargestOfTwo := Max(x, y)

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

AutoIt v2 和 AutoHotkey 的其他不同之处

AutoHotkey.exe 运行 AutoIt v2 (.aut) 脚本时:

  • 反斜线 (\) 作为转义符. 但在其他脚本类型 (.ahk, .ini) 中使用重音符 (`). 可以用 #EscapeChar 改变此默认设置.
  • 支持禁用同行注释 (使用 #AllowSameLineComments 启用它们).
  • 在 Send 命令中可以使用井号 (#) 作为注释符号. 其他脚本类型使用 # 表示 windows 键. 例如, #y 会发送 Win-Y.
  • DetectHiddenText 默认为 OFF. 其他脚本类型中默认为 ON 因为这样执行的更好.
  • SetBatchLines 默认为 1, 意味着脚本默认执行速度非常慢. 其他脚本类型使用 10ms.
  • SetWinDelay 默认为 500. 其他脚本类型默认为 100, 这样使得窗口操作更快.
  • 对于下列命令, 扩展的 (新) 参数被禁用. 这是出于兼容性的考虑 (参见上面的转换注意事项):
    MsgBox
    FileSelectFile
    FileRemoveDir
    IniRead
    StringReplace
    StringGetPos
    WinClose
    WinKill
    WinActivate
    WinMinimize
    WinMaximize
    WinRestore
    WinHide
    WinShow
    WinSetTitle
    WinGetTitle

脚本编译器 (Ahk2Exe) 不支持 AutoIt v2 (.aut) 脚本, 因为编译后的脚本无法判断是运行在 AutoIt v2 模式还是 AutoHotkey 模式. 所以需要在编译前首先把您的 .aut 脚本转换为 .ahk (参见上面).

与 AutoIt v2 不同, IfGreater/Less 中如果其中一个输入参数不是纯数字则按字母顺序比较.

IniWrite 和 IniDelete: 对于 AutoIt v2 (.aut) 脚本: 它们不会设置 ErrorLevel 的值. 对于其他脚本类型, 如果有问题则设置 ErrorLevel 为 1 否则设置为 0.

InputBox: 对于 AutoIt v2 (.aut) 脚本: 如果用户按下了取消键, 输出变量被置空所以这样可以知道按下了取消键. 对于 AutoHotkey 脚本: 输出变量被设置为用户输入的内容, 即使用户按下了取消键. 为了进行区别, 如果按下 Cancel, Alt-F4 或 X-按钮来关闭窗口则 ErrorLevel 被设置为 1. 否则, ErrorLevel 被设置为 0. 这样可以指定取消键对输入的文本执行不同的操作.

SplashTextOn: AutoIt v2 (.aut) 脚本使用的弹出窗口比 AutoHotkey 脚本矮一些. 所以如果您把 .aut 脚本转换成 .ahk, 或从 .aut 脚本复制粘贴代码到 .ahk 脚本, 您可能要从窗口高度中减少像其标题栏的高度 (大概 20 像素, 但具体取决于您的桌面设置).

最后, 与 AutoIt v2 不同, AutoHotkey 不会把其 变量 保存为环境变量. 因为这样会降低性能并且操作系统限制这样的变量最大为 32 KBytes. 要明确地把一个值保存成环境变量, 请使用 EnvSet, 而不是 SetEnv.

新语言和命令风格

如果脚本的文件扩展名不是 .aut (AutoIt v2), 那么可以使用同行注释. 使用分号作为这类注释的前缀字符, 就和用在整行注释一样. 然而, 只有在分号左边至少有一个空格或 tab 时分号才被看成是注释的一部分. 如果需要在空格或制表符后使用 原义 的分号, 您需要在分号前使用重音符 (`) 对它进行转义. 在下面两个例子中, 变量中都含有一个原义的分号:
var = `;
var =;

为了方便, 命令中的首个逗号可以省略 (除非首个参数为空或以 := 或 = 开始, 或命令单独处于 字串分段 的顶部). 例如: Sleep 1, MsgBox test, 等.

对于一些命令, 您可以选用新语法代替原来 AutoIt v2 的语法. 这些命令是:

  • Var = value ; 可以代替 SetEnv, var, value. Value 可以为空, 例如 var =
  • if var <> value ; 您可以使用 <> != < = > 作为比较运算符代替 ifequal/notequal/greater, 等.
  • var += 5 ; 此语句等同于 envadd, var, 5. 其他运算符有 -=, *=, /=
  • 但是新旧命令的语法不要在同行使用:
    IfEqual, x, 35, y = 55 ; 其中程序将无法识别 y = 55 为 IF 的动作.
; 应该如此:
IfEqual, x, 35, SetEnv, y, 55
; 或者:
IfEqual, x, 35
    y = 55

您也可以确定一个变量是否 匹配 列表中的某个项目.
if var [not] in item1,item2,item3 ; 精确匹配
if var [not] contains item1,item2,item3 ; 子字符串匹配.

... 或者一个变量是否 介于 两个值之间:
if var [not] between 5 and 10

... 或一个变量是否为 特定的数据类型：
if var is number
if var is not float ; 不是浮点类型

SetTitleMatchMode 命令得到改进: 除了支持　1 & 2 的传统模式, 现在命令还支持单词 fast 和 slow 作为参数(例如: SetTitleMatchMode, slow). 默认为, 这是 what AutoIt v2 使用的方法. 比较起来, 对于某些类型的窗口慢速模式可以 "看见" 更多的文本. 而快速模式执行的明显更快, 这样有助于加快执行大量窗口命令的脚本速度. 只有在没有其他方法来唯一标识一个给定的窗口时才考虑使用慢速模式. 程序中包含的 Window Spy 会指出窗口中的哪部分文本只有在慢速模式才可用.

改进的命令

对于大多数窗口命令, 例如 WinActivate, 如果命令中不带有参数会使用由 IfWinExist 或 WinWait 命令 最近找到 的窗口. 此外, 在窗口标题参数中使用字母 A 可以让命令对当前活动的 (前台) 窗口进行操作. 例如: WinClose, A

同样, 大多数窗口命令支持 Exclude-Title 和 Exclude-Text 的新参数. 如果一个窗口的标题包含 Exclude-Title 或其中的文本包含 Exclude-Text 则不会被匹配.

StringGetPos 现在最后一个参数是一个新的可选参数. 如果此参数为字母 R, 搜索将从右边而不是左边开始, 并将返回最后一个子字串的位置而不是首个.

MouseClick 支持一个新的参数, 如果是字母 D, 则会一直按住按钮直到用户手动点击它或执行脚本中的下一个动作. 如果此最后一个参数是字母 U, 按钮将被释放(即使之前并没有按下这个按钮, 也将发送一个释放事件). 此外, 您也许会发现新 Click 命令 的语法更简单灵活.

A_Space 和 A_Tab 是两个新的内置变量, 分别表示单个空格和单个制表符. 这样避免了需要用其他方法获取一个含有空格的变量. 例如:

String = String with spaces
IfInString, String, %A_SPACE%
    MsgBox, A space was found.
; 但如果要赋值一个单独的空格给变量, 必须关闭 AutoTrim 这样
; 赋值才不会移除首尾的所有空格:
AutoTrim, off
MySpace = %A_SPACE%

ClipboardAll 是一个新的内置变量, 它包含剪贴板上的所有内容 (例如图片和格式). 使用它可以备份一个或多个 "已存的剪贴板" 到内存或硬盘, 这些备份可以在以后恢复. 此变量在脚本临时使用剪贴板而不用担心丢失原来用户可能保存在其中的内容时尤其有用.

Run 和 RunWait 可以运行快捷方式 (.lnk 文件), 文档, 和 URL. 例如:

Run, www.yahoo.com
RunWait, New Document.doc

此外, 还支持下列系统动作: properties, edit, print, find, explore, open, 和 print. 例如:

Run, properties c:\autoexec.bat  ; 打开此文件的属性对话框.
Run, edit %A_SCRIPTFULLPATH%  ; 执行关联的 "编辑" 动作 (如果有的话).

Send 和 ControlSend 的功能得到了改进, 您不需要使用 Sleep 命令来让用户有时间释放在 Send 命令发送的热键中包含的修饰键 (Ctrl/Alt/Shift/Win). Send 命令知道应该把修饰键变成什么来将每个键发送出去.

StringReplace 可以替换所有匹配, 只需要把最后一个参数设为 "A".

StringGetPos 现在最后一个参数是一个新的可选参数. 如果此参数是字母 R, 搜索将从右边而不是左边开始. 也就是说将返回最后一个匹配而不是首个.

MsgBox 在最后增加了一个新的可选参数: Timeout 值 (单位为秒, 经过这个时间后 MsgBox 将关闭. 此时 IfMsgBox 将检测到值 TIMEOUT). 出于兼容性的考虑, 只有当脚本扩展名不是 .aut 时才支持这个新的参数.

IniRead 在最后增加了一个新的可选参数: 如果命令读取失败, 默认赋给输出变量的值. 出于兼容性的考虑, 只有当脚本扩展名不是 .aut 时才支持这个新的参数.

FileSelectFile 增加了新功能.

新的命令和特性

下面介绍一些最值得注意的新命令和特性:

GUI: 创建和管理图形用户界面 (GUI) 的窗口和控件. 建立您自己的有专业外观的应用程序和表格而不需要困惑于复杂的编程语言.

Menu: 建立您自己定制的菜单栏, 托盘图标菜单, 和弹出菜单.

Hotkeys: 用于键盘, 游戏杆和鼠标.

Hotstrings: 当您输入缩写词时, 自动展开缩写 (自动替换).

DllCall: 调用 DLL 中的函数, 例如标准的 Windows API 函数.

OnMessage: 指定一个当脚本接收到指定消息 (来自操作系统, 外部程序或其他脚本) 时自动运行的 函数.

SendInput 和 SendPlay: 这两个新方法可以更快和更可靠的发送键击和鼠标点击. 此外, 比起其他模式 SendPlay 可以发送键击和鼠标点击到更多种类的游戏.

Progress 和 SplashImage: 显示进度条和图像, 以及可选的文字.

OnExit: 可以定义每当脚本退出时自动执行的子例程. 通过它脚本可以检测用户是否正在注销或关闭系统.

Process: 对进程执行下列的其中一个操作: 检查进程是否存在; 改变进程的优先级; 关闭进程; 等待进程关闭.

SoundSet: 改变音频设备的多种设置 (主设备静音, 主设备音量等.)

SetTimer: 以指定的时间间隔执行一个或多个子例程.

ClipWait: 等待剪贴板包含文本内容 (变成非空的).

StatusBarWait: 等待窗口的状态栏包含指定的文本, 或变成空的.

StatusBarGetText: 获取状态栏上的文本.

WinActivateBottom: 此命令与 WinActivate 相似但它激活最老的 (最底层的) 窗口而不是最新的. 如果仅有一个匹配的窗口, 此命令将执行的和 WinActivate 一样.

DriveSpaceFree, DriveGet, 和 Drive: 获取和改变驱动器的各种信息和设置 (例如它的可用空间).

AutoTrim, on/off (默认为 on): 当您把一个字符串赋值给变量时, 此命令控制是否自动去除字符串首尾的空白字符. 由于这个原因, 空白字符包括空格和制表符, 但不包括新行符/换行符. 因此我相信 "on" 设置的效果和 AutoIt v2 是一样的.

StringUpper 和 StringLower: 把一个字符串中的所有字母转换为大写或小写.

ControlFocus, ControlSetText, Control, ControlGet: 这些和其他的控件命令直接对窗口上的控件进行操作.

SoundPlay: 播放操作系统支持的任何类型的媒体文件.

SoundGet, SoundSet, 和 SoundSetWaveVolume: 获取和改变音频设备的各种设置 (主设备静音, 主设备音量, 波形音量等.)

PixelGetColor 和 PixelSearch: 这两个命令可以获取屏幕上某点的颜色, 这样可以在应用程序或游戏状态改变时进行响应.

GetKeyState: 检测一个按键或鼠标/游戏杆的按钮是按下还是弹起的; 获取游戏杆轴向的位置; 等.

WinMenuSelectItem: 直接运行菜单栏项目, 即使目标窗口不是活动的.

#AllowSameLineComments: 为了提高和 AutoIt v2 的兼容性, 扩展名为 .aut 的脚本通常不允许使用同行注释 (例如: Run, notepad ; 这是一个注释). 需要添加此行 #AllowSameLineComments 到脚本的顶部来允许同行注释.

#SingleInstance: 在脚本的任意位置加上此命令可以避免脚本在已经运行一个实例时再次运行实例. 相反, 将提示您是否保持原有 (旧) 实例的运行还是使用新的实例替换它.

#EscapeChar: 通常转义符为 "`" 但此指令允许改变它为 AutoIt v2 的转义符 (反斜线) 或您选择的其他字符. 注意默认情况下, 扩展名为 .aut 的脚本将使用反斜线作为转义符.

Suspend (和相同名称的托盘菜单项): 此命令阻止启动新的热键子程序 (它不会暂停所有已经在运行的子程序 -- 可以使用 Pause 暂停这些子程序).

Pause (和相同名称的托盘菜单项): 与 Suspend 不同 -- 它将完全禁用热键 -- 而 pause 将暂停当前正在运行的线程 (如果没有, 则 pause 什么都不做).

文件和文件夹循环, 注册表循环, 和增强的 循环.

增加了对 窗口组 的支持. 定义窗口组后, 通过 GroupActivate 命令可以遍历这个组.

最后, 还有许多其他的新命令, 可以在 按字母排序的命令列表.


Alphabetical Command List for AutoHotkey

命令列表

点击命令名称获取详情. 大字体显示 的命令是最常用的.

要了解 AutoHotkey_L 增加的命令列表, 参见 AutoHotkey_L 特性.

命令 | 描述
{ ... } 一对大括号表示一个区块. 区块通常和 函数, Else, Loop, While 循环 和 IF 命令一起使用.
AutoTrim | 决定在 "Var1 = %Var2%" 的语句中将变量 Var2 的值赋值给 Var1 时是否忽略变量 Var2 首尾的空格和 Tab.
BlockInput | 禁用或启用用户通过键盘和鼠标与计算机交互的能力.
Break | 退出 (终止) 循环. 在各种 循环 中都是有效的.
Click | 在指定的坐标点击鼠标按钮. 它还可以按住鼠标按钮, 滚动滚轮, 或移动鼠标.
ClipWait | 等到 剪贴板 包含数据.
ComObj...() --
ComObjActive()
ComObjEnwrap/Unwrap()
ComObjParameter()
ComObjType()
返回一个注册的 COM 对象.
包装/解开 COM 对象.
把值和类型包装成参数传递.
获取一个 COM 对象的类型信息.
ComObjConnect() | 连接 COM 对象的事件源到带有给定前缀的函数.
ComObjCreate() | 创建 COM 对象.
ComObjError() | 启用或禁用 COM 错误通告.
ComObjGet() | 返回由 COM 组件提供的对象引用.
Continue | 跳过当前 循环 的剩余部分并继续下一次循环. 在各种 循环 中都是有效的.
Control | 对控件做出各种改变.
ControlClick | 发送鼠标按钮或鼠标滚轮事件到控件.
ControlFocus | 设置输入焦点到窗口的指定控件上.
ControlGet | 获取控件各种类型的信息.
ControlGetFocus | 获取目标窗口的哪个控件拥有输入焦点, 如果有的话.
ControlGetPos | 获取控件的位置和大小.
ControlGetText | 获取控件的文本.
ControlMove | 移动控件或调整其大小.
ControlSend / ControlSendRaw | 发送模拟的键击到窗口或控件.
ControlSetText | 改变控件的文本.
CoordMode | 为多个命令设置坐标模式是相对于活动窗口还是屏幕.
Critical | 防止 当前线程 被其他线程中断.
DetectHiddenText | 决定窗口中隐藏的文本在探测窗口时是否 "可见". 此设置影响一些命令例如 IfWinExist 和 WinActivate.
DetectHiddenWindows | 决定脚本是否可以 "看见" 隐藏的窗口.
DllCall() | 调用 DLL 文件中的函数, 例如标准的 Windows API 函数.
Drive | 弹出/收进 CD 或 DVD 驱动器托盘, 或设置驱动器的卷标.
DriveGet | 获取计算机驱动器各种类型的信息.
DriveSpaceFree | 获取驱动器的可用磁盘空间, 单位为 MB.
Edit | 在关联的编辑器中打开当前脚本进行编辑.
Else | 指定 IF 语句计算结果为 FALSE 时执行的命令. 包含多个命令时, 需要把他们装入一个 区块 (大括号).
EnvAdd | 设置 变量 的值为它自身加上给定的值的和 (还可以从 日期-时间 值中增加或减去时间). 同义于: var += value
EnvDiv | 设置 变量 的值为它自身除以给定的值. 同义于: var /= value
EnvGet | 获取环境变量.
EnvMult | 设置 变量 的值为它自身乘以给定的值. 同义于: var *= value
EnvSet | 向系统环境中的 变量 写入值.
EnvSub | 设置 变量 的值为它自身减去给定的值 (还可以比较 日期-时间 值). 同义于: var -= value
EnvUpdate | 通知操作系统和所有运行的应用程序 环境变量 已经更新了.
Exit | 退出 当前线程 或 (如果脚本不是 持续运行的 并且不包含热键) 整个脚本.
ExitApp | 无条件终止脚本.
FileAppend | 在文件末尾处追加文本 (如果有必要, 首先创建文本).
FileCopy | 复制一个或多个文件.
FileCopyDir | 复制文件夹及其所有子文件夹和文件 (类似于 xcopy).
FileCreateDir | 创建文件夹.
FileCreateShortcut | 创建快捷方式 (.lnk) 文件.
FileDelete | 删除一个或多个文件.
FileEncoding 为 FileRead, FileReadLine, Loop Read, FileAppend, 和 FileOpen 设置默认编码.
也请参见: 文本编码
FileInstall | 封装指定的文件到脚本的 已编译版本 中.
FileGetAttrib | 报告文件或文件夹是否为只读, 隐藏等.
FileGetShortcut | 获取快捷方式 (.lnk) 文件的信息, 例如其目标文件.
FileGetSize | 获取文件的大小.
FileGetTime | 获取文件或文件夹的时间戳.
FileGetVersion | 获取文件的版本.
FileMove | 移动或重命名一个或多个文件.
FileMoveDir | 移动文件夹及其所有子文件夹和文件. 它还可以重命名文件夹.
FileOpen | 提供面向对象文件 I/O.
FileRead | 读取文件的内容到 变量 中.
FileReadLine | 读取文件指定行的文本并保存到 变量 中.
FileRecycle | 发送文件或目录到回收站, 如果可行的话.
FileRecycleEmpty | 清空回收站.
FileRemoveDir | 删除文件夹.
FileSelectFile | 显示允许用户打开或保存文件的标准对话框.
FileSelectFolder

显示允许用户选择文件夹的标准对话框.
FileSetAttrib | 改变一个或多个文件或文件夹的属性. 支持通配符.
FileSetTime | 改变一个或多个文件或文件夹的时间戳. 支持通配符.
FormatTime | 转换 YYYYMMDDHH24MISS 格式的时间戳到指定的日期/时间格式.
GetKeyState | 检查键盘按键或鼠标/游戏杆按钮是否按下或放开. 也可以获取游戏杆的状态.
Gosub | 跳转到指定的标签继续执行, 直到遇到 Return.
Goto | 跳转到指定的标签继续执行.
GroupActivate | 激活由 GroupAdd 定义的窗口组中的下一个窗口.
GroupAdd | 增加窗口规格到窗口组, 必要时创建组.
GroupClose | 关闭刚刚由 GroupActivate 或 GroupDeactivate 激活的活动窗口. 接着激活系列中的下一个窗口. 它还可以关闭组中所有窗口.
GroupDeactivate | 类似于 GroupActivate, 只是它激活 不 在目标组中的下一个窗口.
GUI | 创建和管理窗口和控件. 这种窗口可以用作数据输入窗体或自定义用户界面.
GuiControl | 对 GUI 窗口中的控件做出各种改变.
GuiControlGet | 获取 GUI 窗体中控件的各种类型的信息.
HideAutoItWin, On|Off | [已过时 -- 等价的命令是: Menu, tray, NoIcon|Icon]
Hotkey | 在脚本运行时创建, 修改, 启用或禁用热键.
if | 指定 变量 的比较结果为 TRUE 时执行的命令. 包含多个命令时, 需要把他们装入一个 区块 (大括号).
if (expression) | 指定 表达式 计算结果为 TRUE 时执行的命令.
If var [not] between | 检查 变量的 内容是否介于两个数字或字符串 (包含的) 之间.
If var [not] in/contains MatchList | 检查 变量的 内容是否匹配列表中的一项.
If var is [not] type
 检查 变量的 内容是否为数字, 大写字母等.
IfEqual/IfNotEqual
 比较 变量 和值判断它们是否相等. 同义于: if var = value | if var <> value
IfExist / FileExist()
检查文件或文件夹是否存在.
IfGreater/IfGreaterOrEqual
 比较 变量 和值. 同义于: if var > value | if var >= value
IfInString / InStr()
检查 变量 是否包含指定的字符串.
IfLess/IfLessOrEqual
 比较 变量 和值. 同义于: if var < value | if var <= value
IfMsgBox
 检查用户在最近的 MsgBox 命令中按下了哪个按钮.
IfWinActive / IfWinNotActive
 检查指定的窗口是否存在并且当前是否活动的 (在最前面).
IfWinExist / IfWinNotExist
 检查指定的窗口是否存在.
ImageSearch | 在屏幕的区域中搜索图像.
IniDelete | 从标准格式的 .ini 文件中删除值.
IniRead | 从标准格式的 .ini 文件中读取值.
IniWrite | 写入值到标准格式的 .ini 文件中.
Input | 等待用户输入一个字符串 (不支持 Windows 9x 系统: 在那里它什么都不做).
InputBox | 显示输入框让用户输入字符串.
KeyHistory | 显示脚本信息和最近按键和鼠标点击记录.
KeyWait | 等待按键或鼠标/游戏杆按钮被松开或按下.
LeftClick | [已过时 -- 使用 Click 代替灵活性更大]
LeftClickDrag | [已过时 -- 使用 MouseClickDrag 代替灵活性更大]
ListHotkeys | 显示当前脚本包含的热键, 不论它们的子程序当前是否运行, 也不论它们是否使用 键盘 或 鼠标 钩子.
ListLines | 显示最近执行的脚本行.
ListVars | 显示脚本的 变量: 它们的名称和当前的内容.
Loop (常规) | 重复执行一组命令: 指定重复次数或直到遇到 break 命令.
Loop (文件和文件夹) | 获取指定的文件或文件夹, 每次一个.
Loop (解析字符串) | 从一个字符串中获取子字符串 (片段), 每次一个片段.
Loop (读取文件内容) | 逐行读取文本文件的内容, 每次一行 (比 FileReadLine 执行的更好).
Loop (注册表) | 获取指定的注册表子键的内容, 每次一项.
Menu | 创建, 删除, 修改和显示菜单和菜单项. 改变托盘图标和它的提示. 控制是否可以打开 已编译脚本 的主窗口.
MouseClick | 点击或按住鼠标按钮, 或滚动鼠标滚轮. 注意: Click 命令 通常更灵活, 也更容易使用.
MouseClickDrag | 点击并按住指定的鼠标按钮, 接着移动鼠标到目标坐标, 然后松开按钮.
MouseGetPos | 获取鼠标光标的当前位置, 以及鼠标当前悬停的窗口和控件 (可选的).
MouseMove | 移动鼠标光标.
MsgBox | 在包含一个或多个按钮 (例如 Yes 和 No) 的小窗口中显示指定的文本.
OnExit | 指定在脚本退出时自动运行的的 子程序.
OnMessage() | 指定当脚本接收到特定消息时自动调用的 函数.
OutputDebug | 发送字符串到调试器 (如果有的话) 显示出来.
Pause | 暂停脚本的 当前线程.
PixelGetColor | 获取指定的 x,y 坐标处像素的颜色.
PixelSearch | 在屏幕区域中搜索指定颜色所在的像素.
PostMessage | 发送消息到窗口或控件的消息队列.
Process | 对进程执行下列的其中一个操作: 检查进程是否存在; 改变进程的优先级; 关闭进程; 等待进程关闭.
Progress | 创建或更新包含进度条的窗口.
Random | 生成伪随机数.
RegExMatch() | 判断字符串是否包含匹配模式 (正则表达式).
RegExReplace() | 替换字符串中匹配模式 (正则表达式) 出现的地方.
RegDelete | 从注册表中删除子键或值.
RegRead | 从注册表读取值.
RegWrite | 写入值到注册表.
RegisterCallback() | 创建机器码地址, 当它被调用时会重定向到脚本中的 函数.
Reload | 使用新的脚本实例替换当前正在运行的实例.
Repeat…EndRepeat
 [已过时 -- 使用 Loop 代替灵活性更大]
Return | 从子程序返回到之前通过 函数调用, Gosub, 使用 Hotkey, GroupActivate, 或其他方式执行跳转的地方.
RightClick | [已过时 -- 使用 Click 代替灵活性更大]
RightClickDrag | [已过时 -- 使用 MouseClickDrag 代替灵活性更大]
Run | 运行外部程序.
RunAs | 指定在所有后续的 Run 和 RunWait 命令中使用的一组用户凭据. 需要 Windows 2000/XP 或更高版本的系统.
RunWait | 运行外部程序并等待其结束.
Send / SendRaw / SendInput / SendPlay | 发送模拟键击和鼠标点击到 活动 窗口.
SendMessage | 发送消息到窗口或控件并等待确认.
SendMode | 让 Send 和 SendInput 或 SendPlay 具有相同的功能而不是默认的 (SendEvent). 也使 Click 和 MouseMove/Click/Drag 使用指定的方法.
SetBatchLines | 决定脚本的执行速度 (影响 CPU 使用率).
SetCapslockState | 设置 Capslock 键的状态. 还可以强制此键保持打开或关闭状态.
SetControlDelay | 设置在每个控件修改命令执行后自动的延时.
SetDefaultMouseSpeed | 设置未指定时在 Click 和 MouseMove/Click/Drag 命令中使用的鼠标速度.
SetEnv (Var = Value) | 把指定的值赋值给 变量.
SetFormat | 设置数学运算得到的整数和浮点数的格式.
SetKeyDelay | 设置每次 Send 或 ControlSend 发送键击后自动的延时.
SetMouseDelay | 设置每次鼠标移动或点击后自动的延时.
SetNumlockState | 设置 Numlock 键的状态. 还可以强制此键保持打开或关闭状态.
SetScrollLockState | 设置 Scrolllock 键的状态. 还可以强制此键保持打开或关闭状态.
SetStoreCapslockMode
 设置在 Send 命令后是否恢复 CapsLock 的状态.
SetTimer | 以指定的时间间隔自动重复运行子程序.
SetTitleMatchMode | 设置在类似 WinWait 命令中 WinTitle 参数的匹配模式.
SetWinDelay | 设置在每次执行窗口命令例如 WinActivate 后自动的延时.
SetWorkingDir | 改变脚本的当前工作目录.
Shutdown | 关闭, 重启或注销系统.
Sleep | 在继续前等待指定的时间量.
Sort | 以字母, 数字或随机顺序排列变量的内容 (可以选择是否移除重复项).
SoundBeep | 从 PC 扬声器发出蜂鸣音.
SoundGet | 从音频设备中获取各种设置 (主静音, 主音量等.)
SoundGetWaveVolume | 获取音频设备的波形输出音量.
SoundPlay | 播放音频, 视频或其他支持的文件类型.
SoundSet | 改变音频设备的各种设置 (主静音, 主音量等.)
SoundSetWaveVolume | 改变音频设备的波形输出音量.
SplashImage | 创建或更新包含 JPG, GIF, 或 BMP 图像的窗口.
SplashTextOn | 创建自定义文本的弹出窗口.
SplashTextOff | 关闭上面的窗口.
SplitPath | 把文件名或 URL 分解成它的名称, 目录, 扩展名和驱动器.
StatusBarGetText | 获取标准状态栏控件的文本.
StatusBarWait | 等待窗口的状态栏包含指定的字符串.
StringCaseSense | 决定在字符串比较中是否区分大小写 (默认为 "不区分大小写").
StringGetPos / InStr() | 获取指定的子字符串在某个字符串中的位置.
StringLeft | 从字符串的左边提取一些字符.
StringLen / StrLen() | 获取字符串中包含的字符数量.
StringLower | 把字符串中的英文字母转换成小写.
StringMid / SubStr() | 从字符串的指定位置提取一个或多个字符.
StringReplace | 用新字符串替换指定的子字符串.
StringRight | 从字符串的右边提取一些字符.
StringSplit | 使用指定的分隔符把一个字符串分解成多个子字符串并保存到数组中.
StringTrimLeft | 从字符串的左边移除一些字符.
StringTrimRight | 从字符串的右边移除一些字符.
StringUpper | 把字符串中的英文字母转换成大写.
Suspend | 禁用或启用所有的或选择的 热键 和 热字串.
SysGet | 获取屏幕分辨率, 多显示器信息, 系统对象的尺寸和其他系统属性.
Thread | 设置 线程 的优先级或是否可以被中断. 它也可以临时禁用所有的 计时器.
ToolTip | 在屏幕的任意位置创建总是置顶的窗口.
Transform | 执行各种数学功能, 按位运算, 和类似 ASCII/Unicode 转换的任务.
TrayTip | 在托盘图标附近创建气球提示窗口. 需要 Windows 2000/XP 或更高版本的系统.
Trim | 移除字符串的开始和/或末尾的某些字符.
UrlDownloadToFile | 从互联网下载文件.
Var = value | 把指定的值赋值给 变量.
Var := expression | 计算 表达式 的结果并保存到 变量 中.
VarSetCapacity() | 增加或清空变量占用的内存. 通常只有在特殊情况例如 DllCall 下才必要.
While 循环 | 重复执行一组命令直到指定的 表达式 计算结果为假.
WinActivate | 激活指定的窗口 (让它置于最前面).
WinActivateBottom | 和 WinActivate 一样, 只是此命令激活最下面的 (最早激活的) 匹配窗口而不是最上面的.
WinClose | 关闭指定的窗口.
WinGetActiveStats | 把 WinGetActiveTitle 和 WinGetPos 的功能合并到一个命令.
WinGetActiveTitle | 获取活动窗口的标题.
WinGetClass | 获取指定窗口的类名.
WinGet | 获取指定窗口的 uID, 进程 ID, 进程名, 或控件列表. 它还可以获取匹配指定条件的所有窗口的列表.
WinGetPos | 获取指定窗口的位置和大小.
WinGetText | 获取指定窗口的文本.
WinGetTitle | 获取指定窗口的标题.
WinHide | 隐藏指定的窗口.
WinKill | 强制关闭指定的窗口.
WinMaximize | 最大化指定的窗口.
WinMenuSelectItem | 调用指定窗口菜单栏中的菜单项.
WinMinimize | 缩小指定的窗口为任务栏上的按钮.
WinMinimizeAll | 最小化所有窗口.
WinMinimizeAllUndo | 与前面 WinMinimizeAll 命令的效果相反.
WinMove | 改变指定窗口的位置和/或大小.
WinRestore | 如果指定的窗口处于最小化或最大化状态则还原它.
WinSet | 对指定的窗口进行各种设置, 例如 "总是置顶" 和透明度.
WinSetTitle | 改变指定窗口的标题.
WinShow | 显示指定的窗口.
WinWait | 等到指定的窗口出现.
WinWaitActive | 等到指定的窗口处于活动状态.
WinWaitClose | 等到指定的窗口消失.
WinWaitNotActive | 等到指定的窗口处于不活动状态.
#AllowSameLineComments | 仅适用于 AutoIt v2 (.aut) 脚本: 允许注释和命令出现在同一行.
#ClipboardTimeout | 改变当首次访问剪贴板失败后脚本继续尝试访问剪贴板多长时间.
#CommentFlag | 把脚本的注释符号从分号改为其他字符串.
#ErrorStdOut | 把阻止脚本运行的任何语法错误发送到标准输出而不是显示在对话框中.
#EscapeChar | 改变脚本的转义符 (例如: 反斜杠与重音符).
#HotkeyInterval | 与 #MaxHotkeysPerInterval 一起指定 热键 激活的速率, 超过此速率将显示警告对话框.
#HotkeyModifierTimeout | 影响 热键 修饰符的行为: CTRL, ALT, WIN, and SHIFT.
#Hotstring | 改变 热字串 选项或终止符.
#If | 类似于 #IfWinActive, 但可以是任意类型的表达式.
#IfTimeout | 设置计算单个 #If 表达式可以使用的最大时间.
#IfWinActive / #IfWinExist | 创建上下文相关的 热键 和 热字串. 根据窗口活动的或存在的不同情况, 这样的热键会执行不同的动作 (或什么都不做).
#Include | 使得脚本认为指定文件的内容会出现在这个准确的位置.
#InstallKeybdHook | 强制无条件安装键盘钩子.
#InstallMouseHook | 强制无条件安装鼠标钩子.
#KeyHistory | 设置 按键历史 窗口中显示的键盘和鼠标事件的最大数目. 设置为 0 可以禁用按键历史.
#MaxHotkeysPerInterval | 与 # HotkeyInterval 一起指定热键激活的速率, 超过此速率将显示警告对话框.
#MaxMem | 设置每个 变量 可使用的最大内存兆数.
#MaxThreads | 设置可同时存在的 线程 的最大数目.
#MaxThreadsBuffer | 使得某些或所有的 热键 缓冲而不是忽略键击, 当达到它们的 #MaxThreadsPerHotkey 限制时.
#MaxThreadsPerHotkey | 设置每个 热键 或 热字串 可同时存在的 线程 的最大数目.
#MenuMaskKey | 改变使用哪个键来屏蔽 Win 或 Alt 按键弹起事件.
#NoEnv | 不检查空变量是否为环境变量 (建议所有新建脚本使用).
#NoTrayIcon | 不显示托盘图标.
#Persistent | 让脚本持久运行 (即直到用户关闭或遇到 ExitApp 命令).
#SingleInstance | 决定当脚本已经运行时是否允许它再次运行.
#UseHook | 强制使用钩子实现全部或部分键盘 热键.
#WinActivateForce | 跳过温和的方法而直接使用强制的方法激活窗口.


AutoHotkey Script Showcase

AutoHotkey 脚本展示

NiftyWindows (美妙的窗口)-- by Enovatic-Solutions: 此脚本让你轻松地控制所有基本的窗口交互，例如拖拽、调整大小、最大化、最小化以及关闭。它最强大的特点是用鼠标右键拖拽来激发。想象将每个窗口分成一个 虚拟的三行三列 9 个单元的网格。中心的单元是最大的一个：通过点击并按住鼠标右键你能抓取并且将一个窗口到处移动。用同样的方法，其他八个单元被用来调整一个窗口的大小。 NiftyWindows 也可提供“对齐到网格”，“保持窗口长宽比”，卷起一个窗口至它的标 题栏，透明度控制，以及其它有用的快捷功能。

屏 幕放大镜-- by Holomind: 此屏幕放大镜包含了操作系统的一些功能，集多个好处于一身，包括：可自定义的刷新间隔和放大倍数 (包括收缩/反放大)；抗锯齿从而提供更优的输出；并且它是开源的 (因此，可以从中挑选很多变体，或者你可以自己调整脚本)。

LiveWindows: 以缩略图查看对话框-- by Holomind: 此脚本通过显示每个对话框和它的进度条的一个小型副本(会自动地检测对话框，即使它们位于其它窗口后方)可让你监视下载进度、文件复制以及其它对话框。预 览窗口置顶显示，但使用非常小的屏幕空间(它也能通过拖拽它的边缘来调整大小)。你也能监视任意窗口，通过在感兴趣的区域拖拽出一个矩形选框(用 Control+Shift+拖拽)，然后按 Win+W 用实时更新的预览窗口来显示选区。

鼠标手势-- by deguix: 此脚本在你按住鼠标右键时会监视如何移动鼠标。如果它看到你“画”出一个能识别的形状或符号，它将启动一个程序 或者执行其它由你选择的自定义动作(就像热键一样)。如何定义手势，请看内置的 README 文件。

在任意编辑器内上下文相关的帮助 -- by Rajat: 此脚本让 Ctrl+2 (或你选择的其它热键)显示选中的 AutoHotkey 命令或者关键词的帮助文件页面。如果未选字词，将在当前行开头提取命令名称。

轻松拖拽窗口 (需要 XP/2k/NT): 通常，窗口仅能在它的标题栏按住左键才能被拖拽。此脚本扩展了此功能以便窗口内的任何一个点都能用来拖拽。要激活此模式，在点击时按住 CapsLock 或者鼠标中键，然后拖拽窗口到一个新的位置。

轻松拖拽窗口-- KDE 风格(需要 XP/2k/NT)-- by Jonny: 此脚本使得移动或者调整一个窗口的大小更加轻松：1)按住 ALT 键并在窗口内的任何地方点击左键，从而拖拽它到一个新的位置；2)按住 ALT 并在窗口内的任何地方点击右键后拖拽，从而轻松地调整它的大小；3)按 ALT 两次但在第二次松开前，左键点击鼠标指针下的窗口使它最小化，右键点击使它最大化，或者中键点击来关闭它。

轻松打开收藏的文件夹-- by Savage: 当你在某些类型的窗口激活时按下鼠标中键，此脚本会显示一个你收藏的文件夹菜单。在上面选择一个收藏的文件夹，脚本会在激活的窗口中立即切换到那个文件 夹。支持下列窗口类型：1)标准的文件打开或者文件保存对话框；2)资源管理器窗口；3)控制台(命令提示符)窗口。对于不支持的窗口类型，菜单也可以随 意地显示，在这种情况下选择的收藏文件夹就在一个新的资源管理器窗口中打开。

IntelliSense(智能感应)-- by Rajat (需要 XP/2k/NT): 此脚本在你编辑一个 AutoHotkey 脚本时会开始监视。当它看到你输入了一个命令紧跟一个逗号或空格时，它将显示那个命令的参数列表来引导你。此外，你可以按 Ctrl+F1 (或你选择的其它热键)来显示帮助文件里那个命令的页面。要消除命令列表，按 Escape 或者 Enter 键。

把游戏操纵杆当作鼠标用: 此脚本把游戏操纵杆转换成一个三键鼠标。它允许每个按钮像鼠标按键那样拖拽并且它几乎不使用 CPU 时间。而且，你从中央将操纵杆推得越远，鼠标指针也将移动得越快。你可以在脚本的顶部个性化各种设置。

游戏操纵杆测试脚本: 此脚本能帮助你确定游戏操纵杆的按钮数量以及其它的属性。它也可能显示出你的游戏操纵杆是否需要校准；就是说，它的每个轴的活动范围是否是从百分之零到百 分之百就如它应该的那样。如果需要校准，请使用操作系统的控制面板或者你的游戏操纵杆随带的软件。

屏幕键盘(需要 XP/2k/NT)-- by Jon: 此脚本在你屏幕的底端创建一个模拟的键盘来实时显示你按下的按键。我让它来帮助我学盲打(来习惯不去看键盘)。在脚本的顶部可以自定义屏幕键盘的尺寸。而 且，你可以双击托盘图标来显示或者隐藏屏幕键盘。

最小化窗口至托盘菜单: 此脚本会分配出一个你选好的热键用来隐藏任何窗口，以便窗口在脚本的托盘菜单底部成为一个菜单项。通过在菜单上选择相应的项目，隐藏的窗口到时能单独地或 者一次性全部反隐藏出来。如果脚本由于任何原因而退出，那么它隐藏的所有窗口将被自动地反隐藏出来。

更改 MsgBox 的按钮名称: 这是一个可用的例子脚本，使用一个定时器来更改一个 MsgBox 对话框里的按钮名称。虽然按钮名称被更改，但仍需要提交那些按钮原本的名称给 IfMsgBox 命令。

数字小键盘区的 000 按键: 此示例脚本让出现在某些小键盘上的特殊的 000 按键变成一个发送等号的按键。你可以用你自定义的命令行替换 "Send, =" 这行来改变这个按键动作。

将数字小键盘当鼠标用-- by deguix: 此脚本让你的键盘当鼠标用并且几乎和用一个真正的鼠标一样(也许对某些任务来说甚至更轻松)。它支持多达五个鼠标按键以及鼠标滚轮的调节。它还有自定义移 动速度、加速以及 "axis inversion"(反转轴)的特性。

Seek(搜 索)-- by Phi: 浏览开始菜单可能变成一件麻烦事，如果你之前安装了很多程序的话会尤其严重。'Seek' 能让你指定一个不区分大小写的关键词/短语，用它从开始菜单里仅筛选出匹配的程序和目录，以便你能轻松地从少量匹配的项目中打开你的目标程序。这样就不用 在开始菜单里干查找和穿越的苦力活了。

鼠标菜单型的工具提示(需要 XP/2k/NT)-- by Rajat: 此脚本对暂时地按住鼠标中键的动作做出反应而显示一个弹出菜单(译注：在松开后)。通过左键点击选择一个菜单项。在菜单外左键点击来取消菜单。最近的一个 改进是可以根据激活窗口的类型来改变菜单的内容(记事本和 Word 在这里被用作例子)。

屏显(OSD)音量-- by Rajat: 此脚本将指定你选择的热键来提高以及降低总音量和/或波形音量。这两种音量以不同的颜色条图形显示。

窗口遮蔽(将窗口卷起到它的标题栏)-- by Rajat: 此脚本将窗口裁减至它的标题栏，而之后通过按单个热键恢复它原本的大小。任意数量的窗口都能以这种方式裁减(脚本能记住每个窗口的原本大小)。如果脚本因 为某种原因退出，所有“卷起”的窗口会被自动地恢复到它们原来的高度。

WinLIRC 客户端: 每当你在遥控器上按一个按键，此脚本就会 WinLIRC 接收到通知。它能用来自动化 Winamp, Windows Media Player 等等。它配置起来很简单。例如，如果 WinLIRC 能识别你遥控器上一个称为 "VolUp" 的按钮，创建一个命名为 VolUp 的标签并在它下方使用命令 "SoundSet +5" 来按 5% 增加声卡的音量。

1 小时软件-- by skrommel: 这里收集了大量有用的脚本，专业地用简短的描述以及截屏来呈现。

Titan 的脚本: 此收藏包括了有用的脚本例如：
1) XML 阅读器/编辑器: 对 XML 文件有简单界面来读取以及编辑它的值，就像 JavaScript。
2) Anchor(锚): 让 GUI 控制器附属在一个可调大小的 GUI 窗口的右边缘或者底部边缘。
3) 函数: wrapper(包装)函数的收藏，它给每个有 OutputVar 参数的 AutoHotkey 命令调用。
4) 天气: 在托盘菜单中显示当前的天气或者在一个 rich GUI 中显示预报。

Toralf 的脚本: 此收藏包括了有用的脚本例如：
1) AHK 窗口信息: 在窗口、控件等上面显示信息。
2) 电子节目指南: 浏览你当地的电视节目/时间表(支持多个国家)。
3) 自动语法整理: 更改缩进以及在脚本里整理命令使其格式/样式一致。

Sean 的脚本: 包括了有用的脚本例如：
1) 网络下载/上传流量计: 在一个小小置顶的进度条上显示网络下载/上传了多少 KB。
2) StdoutToVar (标准输出到变量): 重定向命令或程序的输出到脚本的某个变量。
3) 截取一个矩形屏幕: 一个截取部分屏幕并保存为文件(BMP/JPG/PNG/GIF/TIF)的可调用函数。它也能截取透明的窗口和鼠标指针。
4) 颜 色放大器/选取器: 放大鼠标指针附近的区域，允许选取单像素以及识别它的颜色。
5) 嵌 入一个 Internet Explorer 控件: 在一个脚本的 GUI 窗口中包含一个 MSIE(微软IE)控件。控件能显示网页或者其他兼容浏览器的内容。

论坛的 Scripts & Functions 版块: 这是一个近 1000 个待运行可供搜索的脚本和函数收藏。由 AutoHotkey 的用户建设并维护，此存档每天增长并改进。

-- 主页 --


Changes & New Features

This changelog only concerns AutoHotkey. Read AutoHotkey_L's changelog.

1.0.48.05 - September 25, 2009

Fixed crash of SendMessage and PostMessage when wParam or lParam is omitted (broken by 1.0.48.04). [thanks Lexikos]

1.0.48.04 - September 25, 2009

Fixed StringSplit to work properly inside functions of compiled scripts (broken by 1.0.35.01). [thanks engunneer & Lexikos]

Fixed SendPlay not to wait for the release of the Windows key prior to sending an "L" keystroke (broken by 1.0.48.01). [thanks Lexikos]

Fixed A_EndChar to be valid when the B0 option is present, and to be empty when there is no ending character (broken by 1.0.44.09). [thanks Al2000]

Fixed FormatTime to yield a valid time of day even when the specified month is out-of-range (broken by 1.0.48.00). [thanks silveredge78]

Fixed FileCreateDir to support a leading backslash even when it is the only backslash; e.g. \dir. [thanks jaco0646]

Fixed GuiControl/GuiControlGet/Gui/SendMessage to work reliably even when they trigger a callback or OnMessage function. [thanks Lexikos]

Fixed RegExMatch() not to produce too few replacements when an empty-string match is followed by a non-empty-string match.

Changed "While()" to be recognized as a loop rather than a function. [thanks Crash&Burn]

Improved UrlDownloadToFile to support FTP and Gopher. [thanks Lexikos]

Improved the stdout/asterisk mode of FileAppend to write immediately rather than lazily to standard output. [thanks Lexikos]

Added full support for "if % expression". [thanks kenomby]

1.0.48.03 - May 3, 2009

Fixed "ListLines On" not to erase the most recent log entry in the line history. [thanks Lexikos]

Fixed ListView to respond properly to mouse dragging when timers are running. [thanks Solar]

Fixed key-up hotkeys so that if one is created while its key is being held down, the release of the key doesn't trigger the wrong hotkey. [thanks Peter & engunneer]

1.0.48.02 - April 19, 2009

Changed and fixed Gosub and GroupActivate so that when a function calls an external/public subroutine, that subroutine will treat all dynamic variables as globals, and will have outside-of-function GUI behavior. [thanks kenomby & Lexikos]

Improved performance of True/False/A_EventInfo in expressions by treating them as integers vs. strings.

1.0.48.01 - April 15, 2009

Changed: For Windows Vista and later, hotkeys that include the Windows key (e.g. #a) will wait for LWin and RWin to be released before sending any text containing an "L" keystroke. This prevents such a hotkey from locking the PC. This behavior applies to all sending modes except SendPlay (which doesn't need it) and blind mode.

Fixed A_LoopFileExt to be blank for any filename having no extension but a period in its pathname. [thanks Yek-Toho-Tua].

Fixed the assignment of integers that are 19 or 20 characters long to work as they did prior to v1.0.48. [thanks Laszlo & Lexikos]

Fixed function definitions to work properly inside a block. [thanks rmarko]

Improved performance of A_Index in expressions by treating it as an integer rather than a string.

Improved performance of "if var [not] in/contains". [developed by Lexikos]

Improved ListLines with an option to turn line-logging Off or On. [thanks kenomby & ruespe]

1.0.48 - February 25, 2009

Compatibility: The change most likely to affect backward compatibility is that floating point numbers stored in variables now have higher precision. Scripts that rely on tiny differences in precision would either need to be reviewed and updated, or have their compatibility improved by using "SetFormat Float" (e.g. SetFormat, Float, 0.6) anywhere in the script. "SetFormat Float" disables the higher precision, but gives up some of the new, faster floating point performance.

Performance: The main theme of this release is faster performance. Almost all scripts should run faster -- especially those that make heavy use of expressions and integer math/comparisons (which may run up to three times as fast). To achieve the full benefit, a script either should avoid using SetFormat or should use SetFormat's fast mode.

Performance improvements

Expressions and function calls are compiled more heavily, making them much faster (especially complex integer expressions, including those with commas).

Binary numbers are cached for variables to avoid conversions to/from strings. This makes numerical operations involving variables much faster.

Literal integers in expressions and math/comparison commands are replaced with binary integers, which makes them faster; e.g. X+5 and "if x > 5".

LOOPs, IFs, and ELSEs that have blocks (braces) are faster due to skipping the opening '{'. A side-effect is that the '{' is omitted from ListLines.

Thread-creation performance is improved, which should help rapid-fire threads in OnMessage(), RegisterCallback(), and GUI events.

Changes that might affect existing scripts (other than higher-precision floating point described at the top)

When "SetFormat, Integer, Hex" is in effect, assigning a literal decimal integer to a variable also converts it to hex. Usually this is only a display issue.

For OnMessage() performance, the message number and HWND arrive as standard numbers rather than appearing unconditionally as hex. Usually this is only a display issue.

To achieve various improvements in performance, scripts now use slightly more memory (proportionate to the number of variables and expressions).

Changed and fixed "if var is time" and other uses of YYYYMMDDHHMISS date-time stamps to recognize that months outside the range 1-12 are invalid. [thanks Nick]

Changed and improved dynamic function calling to allow passing more parameters than defined by a function, in which case the parameters are evaluated but discarded. [developed by Lexikos]

Other improvements

Added function IsFunc(), which indicates whether a function may be called dynamically. [developed by Lexikos]

Added the while-loop, which repeats its commands until its expression evaluates to false. [developed by Lexikos]

Added an assume-static mode for functions. [developed by Lexikos]

Added built-in variables A_IsPaused and A_IsCritical. [developed by Lexikos]

Improved NumPut() to support UInt64 like DllCall(). [thanks Sean]

Improved mouse wheel support by adding WheelLeft and WheelRight as hotkeys and supporting them in Send, Click, and related commands. However, WheelLeft/Right has no effect on operating systems older than Windows Vista. [developed by Lexikos]

Upgraded compiled script compressor from UPX 3.00 to 3.03.

Fixes

Fixed inability to use MsgBox's timeout parameter when the "Text" parameter had an expression containing commas.

Fixed "Menu, Delete, Item-that's-a-submenu" not to disrupt the associated submenu. [thanks animeaime & Lexikos]

Fixed the GUI Hotkey control to return usable hotkey names even for dead keys (e.g. "^" instead of Zircumflex). [thanks DerRaphael]

Fixed RegDelete so that it won't delete an entire root key when SubKey is blank. [thanks Icarus]

Fixed registry loops to support subkey names longer than 259 (rare). In prior versions, such subkeys would either be skipped or cause a crash. [thanks Krzysztof Sliwinski & Eggi]

Fixed FileSelectFolder by providing an option to make it compatible with BartPE/WinPE. [thanks markreflex]

Fixed window/control IDs (HWNDs), which in rare cases wrongly started with 0xFFFFFFFF instead of just 0x. [thanks Micahs]

Fixed inability of Send commands to use the Down/Up modifiers with the "}" character. [thanks neovars]

1.0.47.06 - March 9, 2008

Fixed crash when a function was called concurrently with an optional ByRef parameter omitted by one thread but not omitted by the other. [thanks DeathByNukes]

Fixed "Menu, Tray, MainWindow" to enable the menu items in the main window's View menu. [thanks Lexikos]

Added dynamic function calling. [developed by Lexikos]

1.0.47.05 - November 21, 2007

Fixed the Sort command: 1) fixed the "function" option not to misbehave when it's the last option in the list; 2) fixed the "unique" option so that when the delimiter is CRLF, the last item can be detected as a duplicate even when it doesn't end in CRLF; 3) fixed the "unique" option not to append a trailing delimiter when the last item is a duplicate. [thanks Roland]

Fixed RegExMatch() and RegExReplace() to yield correct results even when Haystack and OutputVar are both the same variable. [thanks Superfraggle]

Fixed inability to pass a parameter that is "a variable to which ClipboardAll has been assigned". [thanks Joy2DWorld & Lexikos]

Updated RegEx/PCRE from 7.0 to 7.4. For a summary of the major changes, see www.pcre.org/news.txt. For full details of every change and fix, see www.pcre.org/changelog.txt.

Added GUI control "Tab2" that fixes rare redrawing problems in the original "Tab" control (e.g. activating a GUI window by clicking on a control's scrollbar). The original Tab control is retained for backward compatibility because "Tab2" puts its tab control after its contained controls in the tab-key navigation order. [thanks Xander]

1.0.47.04 - August 28, 2007

Fixed key-up hotkeys like "a up::" not to block the pressing of the "a" key unless the hotkey's #IfWin criteria are met. [thanks Roland]

Fixed Round(Var, NegativeNumber), which in rare cases was off by 1. [thanks Icarus]

Fixed crash of scripts that end in a syntax error consisting of an orphaned IF-statement (broken by 1.0.47.00). [thanks msgbox of the German forum]

Eliminated the "GetClipboardData" error dialog. Instead, an empty string is retrieved when the data cannot be accessed within the #ClipboardTimeout period. [thanks ManaUser & Sean]

Changed GUI checkboxes and radio buttons to default to "no word-wrap" when no width, height, or CR/LF characters are specified. This solves display issues under certain unusual DPI settings. [thanks Boskoop]

1.0.47.03 - August 1, 2007

Fixed expressions to allow literal negative hexadecimal numbers that end in "E"; e.g. fn(-0xe). [thanks Laszlo]

Fixed block syntax to allow a function-call immediately to the right of a '}'. [thanks Roland]

1.0.47.02 - July 19, 2007

Fixed the Number option of Edit controls to properly display a balloon tip when the user types something other than a digit. [thanks tfcahm]

Fixed WM_TIMER not to be blocked unless it's posted to the script's main window. [thanks tfcahm]

Fixed wildcard hotkeys not to acquire tilde behavior when the same hotkey exists in the script with a tilde. [thanks Lexikos]

Fixed declaration initializers not to retain whitespace at the end of literal numbers. Also, they now allow spaces between a closing quote and the next comma. [thanks Hardeep]

1.0.47.01 - July 8, 2007

Fixed RunAs not to crash or misbehave when a domain is specified. [thanks Markus Frohnmaier]

Changed relational operators to yield integers even when the inputs are floating point; e.g. 1.0 < 2.0 yields 1 vs. 1.0. [thanks Lexikos]

1.0.47 - June 19, 2007

Added support for function libraries, which allow a script to call a function in an external file without having to use #Include.

Added RegisterCallback(), which creates a machine-code address that when called, redirects the call to a function in the script. [developed by Jonathan Rennison (JGR)]

Added NumGet() and NumPut(), which retrieve/store binary numbers with much greater speed than Extract/InsertInteger.

Improved Sort with an option to do custom sorting according to the criteria in a callback function. [thanks Laszlo]

Improved OnMessage() with an option to allow more than one simultaneous thread. [thanks JGR]

Improved Critical with an option to change the message-check interval, which may improve reliability for some usages. [thanks Majkinetor and JGR]

Changed Critical to put SetBatchLines -1 into effect.

Changed the error messages produced by #ErrorStdOut to contain a space before the colon. [thanks Toralf]

Fixed OnMessage() functions that return one of their own local variables to return the number in that variable, not 0.

Fixed potential crashing of built-in variables that access the registry (e.g. A_AppData, A_Desktop, A_MyDocuments, A_ProgramFiles). [thanks Tekl]

1.0.46.17 - May 31, 2007

Fixed A_UserName (broken by 1.0.46.16).

1.0.46.16 - May 30, 2007

Fixed "Gui, Tab, TabName" when used after a previous "Gui Tab". [thanks Toralf]

Improved SetTimer to treat negative periods as "run only once". [thanks Majkinetor]

Added "GuiControlGet Hwnd", which is a more modular/dynamic way to retrieve a control's HWND. [thanks Majkinetor]

Added built-in variables A_ThisLabel and A_ThisFunc, which contain the names of the currently-executing label/function. [thanks Titan & Majkinetor]

1.0.46.15 - May 9, 2007

Fixed GuiControl, GuiControlGet, and "Gui ListView/TreeView" to support static variables and ByRefs that point to globals/statics. [thanks Peter]

Fixed FileInstall causing the Random command to become non-random in compiled scripts. [thanks Velocity]

Reduced the size of compiled scripts by about 16 KB due to UPX 3.0. [thanks to atnbueno for discovering the optimal command-line switches]

1.0.46.14 - May 2, 2007

Added the "require administrator" flag to the installer to avoid a warning dialog on Windows Vista. [thanks Roussi Nikolov]

1.0.46.13 - May 1, 2007

Fixed hotkeys like *x to fire even when x is also a hotkey that is prevented from firing due to #IfWin. [thanks Joy2DWorld & Engunneer]

Improved optional parameters to accept quoted/literal strings as default values.

Improved ByRef parameters with the ability to be optional (i.e. they may accept default values). [thanks Corrupt]

1.0.46.12 - April 24, 2007

Fixed inability to recognize a literal scientific notation number that begins with 0, such as 0.15e+1. [thanks Laszlo]

1.0.46.11 - April 23, 2007

Fixed inability to have a function-call as the first item in certain comma-separated expressions. [thanks Majkinetor]

Fixed WinTitles like "ahk_id %ControlHwnd%" in ControlGet's FindString/Choice/List, and Control's Add/Delete/Choose. [thanks Freighter & PhiLho]

Improved floating point support to recognize scientific notation; e.g. 1.2e-5 (the decimal point is mandatory). Also improved "SetFormat Float" with an option to output in scientific notation. [thanks Laszlo]

1.0.46.10 - March 22, 2007

Fixed StringSplit inside assume-local functions so that it creates a local array even when OutputArray0 exists as a global but not a local. [thanks KZ]

Improved ListView's item-changed notification ("I") to indicate via ErrorLevel whether the item has been selected/deselected, focused/unfocused, and/or checked/unchecked. [thanks foom]

Added an additional layer of protection to compiled scripts. It is recommended that scripts containing sensitive data or source code be recompiled with the /NoDecompile switch.

1.0.46.09 - March 4, 2007

Fixed ":=" deep inside expressions when used to assign the result of a recursive function to a local variable (broken by 1.0.46.06). [thanks Laszlo]

Fixed inability to pass certain ternary expressions to ByRef parameters. [thanks Titan]

Fixed "GuiControlGet, OutputVar, Pos" so that it doesn't make the OutputVar blank. [thanks PhiLho]

Changed and fixed continuation sections so that the "Comment" option doesn't force the LTrim option into effect. [thanks Titan]

Changed the Terminal Server Awareness flag back to "disabled" on AutoHotkey.exe and compiled scripts. This improves flexibility and backward compatibility (see discussion at forum).

1.0.46.08 - February 7, 2007

Fixed unreliability of ComSpec and environment variables on Windows 9x (broken by v1.0.46.07). [thanks Loriss]

Changed: When AutoHotkey.exe is launched without a script specified, it will now run (or prompt you to create) the file AutoHotkey.ahk in the My Documents folder. The only exception is when AutoHotkey.ini exists in the working directory, in which case it uses the old behavior of executing that file.

Improved DllCall to support an integer in place of the function name, which is interpreted as the address of the function to call. [thanks Sean]

1.0.46.07 - January 23, 2007

Fixed crash of illegally-named dynamic variables on the left of an equal-sign assignment (broken by v1.0.45). [thanks PhiLho]

Fixed FileMoveDir's "Option 2" to work properly even when the directory is being both renamed and moved. [thanks bugmenot]

Fixed inability to pass a variable ByRef if that same expression changed it from empty to non-empty (when #NoEnv is absent). [thanks Joy2DWorld]

Changed DllCall's A_LastError to reflect only changes made by the script, not by AutoHotkey itself. [thanks Azerty]

1.0.46.06 - January 16, 2007

Applied minor fixes and improvements to regular expressions by upgrading from PCRE 6.7 to 7.0. One of the most notable improvements is the `a option, which recognizes any type of newline (namely `r, `n, or `r`n). Similarly, the \R escape sequence means "any single newline of any type". See also: Full PCRE changelog

Changed and fixed all Control commands and StatusBarWait to obey SetTitleMatchMode RegEx as documented.

Changed RegExReplace() to return the original/unaltered string rather than "" when an error occurs.

Changed: Enabled the Terminal Server Awareness flag on AutoHotkey.exe and compiled scripts.

Improved performance when assigning large strings returned from user-defined functions. [thanks Laszlo]

1.0.46.05 - January 4, 2007

Fixed the Input command to allow named end keys like {F9} to work even when the shift key is being held down (broken by v1.0.45). [thanks Halweg]

Fixed inability of "Gui Show" to focus the GUI window when the tray menu is used both to reload the script and to show the GUI window. [thanks Rnon]

Fixed inability to pass some types of assignments (:=) to a ByRef parameter. [thanks Laszlo]

1.0.46.04 - January 2, 2007

Fixed inability to pass the result of an assignment (:=) to a ByRef parameter. [thanks Titan]

1.0.46.03 - December 18, 2006

Fixed ListView's floating point sorting to produce the correct ordering. [thanks oldbrother/Goyyah/Laszlo]

1.0.46.02 - December 17, 2006

Fixed environment variables to work properly as input variables in various commands such as StringLen and StringReplace (broken by 1.0.44.14). [thanks Camarade_Tux]

1.0.46.01 - December 15, 2006

NOTE: Although this release has been extensively tested, several low-level enhancements were made. If you have any mission-critical scripts, it is recommended that you retest them and/or wait a few weeks for any bugs to get fixed.

Fixed comma-separated declaration initializers such as "local x = 1, y = 2" to work even when immediately below an if/else/loop statement.

Fixed comma-separated expressions so when the leftmost item is an assignment, it will occur before the others rather than after. [thanks Laszlo]

Changed and fixed function-calls so that any changes they make to dynamic variable names, environment variables, and built-in variables (such as Clipboard) are always visible to subsequent parts of the expression that called them.

Changed: When a multi-statement comma is followed immediately by a variable and an equal sign, that equal sign is automatically treated as a := assignment. For example, all of the following are assignments: x:=1, y=2, a=b=c

Changed comma-separated expressions to produce the following effects: 1) the leftmost /= operator becomes true divide rather than EnvDiv; 2) blank values are not treated as zero in math expressions (thus they yield blank results).

Improved the performance of expressions by 5 to 20% (depending on type).

Improved the new assignment operators such as .= to support the Clipboard variable (even in comma-separated expressions).

Improved the .= operator so that it doesn't require a space to its left.

Improved GUI controls to accept static variables as their associated variables (formerly only globals were allowed).

Added option HwndOutputVar to "Gui Add", which stores a control's HWND in OutputVar. [thanks Corrupt & Toralf]

1.0.46 - November 29, 2006

NOTE: Although this release has been extensively tested and is not expected to break any existing scripts, several low-level enhancements were made. If you have any mission-critical scripts, it is recommended that you retest them and/or wait a few weeks for any bugs to get fixed.

Added function SubStr(), which retrieves the specified number of characters at the specified position in a string.

Added assignment operators //=, .=, |=, &=, ^=, >>=, and <<=, which can be used anywhere in expressions. For example, Var .= "abc" appends the string "abc" to Var's current contents.

Added full support in expressions for the operators :=, ++, --, +=, -=, *=, and /= (formerly, they could be used only as the leftmost operator on a line). All assignment operators (especially ++ and --) behave in a C-like way when their result is used by some other operator.

Added the ternary operator (?:), which is a shorthand replacement for the if-else statement. For example, var := x>y ? 2 : 3 assigns the value 2 if x is greater than y; otherwise it assigns 3.

Added support for comma-separated expressions, which allow a single line to contain multiple assignments, function calls, and other expressions. [thanks PhiLho & Titan]

Improved variable declarations to support initialization on the same line. Note: A static variable's initialization occurs only once, before the script begins executing.

Improved line continuation to support all expression operators. For example, a line that starts with "?" or "+" is automatically appended to the line above it.

Improved performance of operators "." and ".=" to be as fast as the percent-sign method of appending a string.

Improved expressions to allow more types of consecutive unary operators such as !!Var. [thanks Laszlo]

Changed Critical to check messages less often (20 vs. 10ms), which improves the reliability of frequently-called OnMessage functions. [thanks Majkinetor]

Changed: A variable named simply "?" is no longer valid in expressions due to the new ternary operator.

Fixed hotkeys to support ":::" (colon as a hotkey) and ": & x" (colon as a hotkey prefix).

Fixed the installer to remove psapi.dll from the AutoHotkey folder (except on Windows NT4). This avoids a conflict with Internet Explorer 7. [thanks to all who reported it]

1.0.45.04 - November 15, 2006

Fixed crash on Windows 9x when a script doesn't actually run (e.g. due to syntax error) (broken by v1.0.45). [thanks rogerg]

Changed "Control Style|ExStyle" to report ErrorLevel 0 vs. 1 when the requested style change wasn't necessary because it was already in effect.

Improved #Include to support %A_AppData% and %A_AppDataCommon%. [thanks Tekl]

1.0.45.03 - November 12, 2006

Fixed file-pattern loops not to crash when recursing into paths longer than 259 characters. In addition, such paths and files are now ignored (skipped over) by file-pattern loops, FileSetAttrib, and FileSetTime. [thanks PhilR]

Fixed functions that call themselves and assign the result to one of their own locals (broken by v1.0.45). [thanks bjennings]

Fixed crash of scripts containing regular expressions that have compile errors. [thanks PhiLho]

Fixed GuiControl not to convert checkboxes into 3-state unless requested. [thanks JBensimon]

Changed UrlDownloadToFile to announce a user-agent of "AutoHotkey" to the server rather than a blank string. [thanks jaco0646]

Improved continuation sections to support semicolon comments inside the section via the option-word Comments.

1.0.45.02 - November 8, 2006

Fixed StringUpper and StringLower to work when OutputVar is the clipboard (broken by v1.0.45). [thanks songsoverruins]

Fixed the hotkeys ~Alt, ~Control, and ~Shift to fire upon press-down rather than release (broken by v1.0.44).
Background: Without the tilde, Alt/Control/Shift fire upon release to avoid taking over both the left and right key. But a specific left/right hotkey like LAlt or RShift fires upon press-down.

1.0.45.01 - November 7, 2006

Fixed FileReadLine and FileSelectFile not to crash or misbehave when other threads interrupt them (broken by v1.0.45). [thanks toralf]

Fixed RegExMatch() so that when there's no match, named subpatterns are properly set to "" in the output array. [thanks PhiLho]

Fixed RegExMatch()'s "J" option to properly write duplicate named subpatterns to the output array. [thanks PhiLho]

Changed SetWorkingDir and #Include DirName to succeed even for a root directory such as C: that lacks a backslash.

Improved DllCall() to display a warning dialog if the called function writes to a variable of zero capacity.

1.0.45 - November 4, 2006

NOTE: Although this release has been extensively tested and is not expected to break any existing scripts, several low-level performance enhancements were made. If you have any mission-critical scripts, it is recommended that you retest them and/or wait a few weeks for any bugs to get fixed.

Added support for regular expressions via RegExMatch(), RegExReplace(), and SetTitleMatchMode RegEx. [thanks Philip Hazel & PhiLho]

Improved performance and memory utilization of StringReplace.

Improved performance of the := operator for expressions and functions involving long strings.

Improved ControlClick with a new option "NA" that avoids activating the target window (this mode also improves reliability in some cases). In addition, it's been documented that SetControlDelay -1 can improve the reliability of ControlClick in some cases. [thanks nnesori]

Changed GUI buttons to default to "no word-wrap" when no width, height, or CR/LF characters were specified. This may solve button display issues under some desktop themes.

Fixed "Transform HTML" for the following characters: &`n><

Fixed misinterpretation of lines starting with "if not is" such as "if not IsDone".

Fixed inability of "Gui Show" to move a window vertically downward to where its bottommost row of pixels is now.

Fixed inability to use GroupActivate as the only line beneath an IF or ELSE.

Fixed inability of the Input command to differentiate between end-keys enclosed in braces and their (un)shifted counterparts; e.g. '{' vs. '['. [thanks Laszlo]

Visit www.autohotkey.com/changelog/ for the older changes and a list of planned features.


AutoHotkey_L Features

AutoHotkey_L 特性 [主页]

流程控制 |
Break LoopLabel | 退出一个循环或任意数目的嵌套循环.
Continue LoopLabel | 继续一个循环, 即使在任意数目的嵌套循环中.
For x,y in z | 从头到为尾循环对象的内容
Loop Until | 循环直到条件为真. 可用于任意类型的循环.
命令 |
FileEncoding | 为 FileRead, FileReadLine, Loop Read, FileAppend 和 FileOpen 设置默认编码. 也请参见: 文本编码
Menu, Icon | 设置或移除菜单项图标.
SendInput {U+nnnn} | 发送 Unicode 字符. 在 Unicode 版本中可以直接使用 Unicode 字符.
SetFormat, IntegerFast, h|H | 设置小写或大写的十六进制格式.
Transform, HTML | 执行代码页或 HTML 转换.
指令 |
#If expression | 类似于 #IfWinActive, 但可以是任意类型的表达式.
#IfTimeout | 设置计算单个 #If 表达式可以使用的最大时间.
#MenuMaskKey | 改变使用哪个键来屏蔽 Win 或 Alt 按键弹起事件.
#Include <Lib> | 包含函数库文件夹中的脚本文件.
#Warn | 启用或禁用为选择的情况提示开发者错误的警告.
函数 |
ComObj... -- ComObjActive ComObjEnwrap/Unwrap ComObjParameter ComObjType | 获取注册的 COM 对象. 包装/解开 COM 对象. 把值和类型包装成参数传递. 获取 COM 对象的类型信息.
ComObjArray | 创建用于 COM 的 SAFEARRAY.
ComObjConnect | 连接 COM 对象的事件源到带有给定前缀的函数.
ComObjCreate | 创建 COM 对象.
ComObjError | 启用或禁用 COM 错误通告.
ComObjFlags | 获取或改变控制 COM 包装器对象行为的标志.
ComObjGet | 返回由 COM 组件提供的对象引用.
ComObjQuery | 查询 COM 对象的接口或服务.
ComObjType | 从 COM 对象获取类型信息.
ComObjValue | 获取存储在 COM 包装器对象中的值或指针.
FileOpen | 提供面向对象的文件 I/O.
IsObject | 判断某个值是否为对象.
StrPut / StrGet | 复制字符串到内存地址或来自内存地址, 并可选地对其在不同代码页间进行转换.
Trim | 移除字符串的开始和/或末尾的某些字符.
RegEx (?CNumber:Function) | 在正则表达式进行模式匹配期间调用函数.
可变参数函数 | 函数可以通过数组接受可变数目的参数.
对象 |
概述 | 对象的常规行为和用法.
Object | 使用其他功能扩展关联数组.
枚举数 | 可以枚举容器中的项目.
File | 提供访问文件的接口. FileOpen 返回文件类型的对象.
ComObject | 参见上面的 ComObj 函数.
变量 |
A_IsUnicode | 在 Unicode 版本中, 此变量值为 1 (真). 在 ANSI 版本中此变量未定义, 所以实际为 假.
A_FileEncoding | 包含用于多种命令的默认编码; 参见 FileEncoding.
A_OSVersion | 在 Windows 7 上值为 WIN_7, 其他值参见 此处.
A_PtrSize | 包含指针的大小, 单位为字节. 此大小为 4 (32 位) 或 8 (64 位).
数据类型 |
Ptr | 在 32 位版本中等同于 Int 而在 64 位版本中为 Int64. 由 DllCall, NumPut 和 NumGet 所支持.
AStr, WStr | 仅 DllCall 支持; 参见 脚本兼容性.
Unicode |
兼容性 | 在 DllCall 中如何处理 Unicode 等.
脚本文件 | 在脚本文件中使用 Unicode 编码.
SendInput | 在 SendInput 中使用 Unicode.
其他 |
调试 | 交互式调试特性 (单步执行等).
图标支持 | 资源标识符和改进的对各种图标大小的支持.
Gui 文本品质 | 控制 Gui 中文本的反锯齿效果.
其他变化 | 影响脚本兼容性的改变.
版本历史 | AutoHotkey_L 的修订历史.

命令的变化

文本编码

FileRead, FileReadLine, Loop Read 和 FileAppend 支持 Windows 所支持的大部分文本编码, 而不仅系统默认的 ANSI 代码页. 可以用 FileEncoding 设置默认编码, 此设置在 FileRead 和 FileAppend 中可以使用如下方法覆盖:

FileRead, OutputVar, *Pnnn Filename
FileAppend [, Text, Filename, Encoding]

此处 nnn 必须是数值的 代码页标识符, 而 Encoding 遵循与 FileEncoding 相同的格式.

也请参见: 脚本兼容性

图标支持的改进

不常见的大小

可以从可执行文件中提取操作系统支持的任意大小的图标资源. 当图标组中存在多种大小的图标资源时, 则使用其中最合适的大小. 在修订号 17 之前的版本中, 系统先选择任意的图标资源, 接着调整到系统的大图标尺寸, 然后调整回请求的尺寸.

资源标识符

使用负数的图标编号可以标识可执行文件中的一组图标资源. 例如, 下面的语句设置托盘图标为 ahk 文件的默认图标.

Menu, Tray, Icon, %A_AhkPath%, -160


Debugging Features

调试器客户端

AutoHotkey_L 通过 DBGp 可以添加调试特性的支持, DGBp 是一种常见的支持多语言和调试器 UI 通信的调试器协议. 参见 交互式调试 了解更多细节. 在这个页面中列出了已知兼容于 AutoHotkey_L 的一些 UI 或 "客户端".

XDebugClient

XDebugClient 是一个基于 .NET Framework 2.0 的简单开源前端 DBGp 客户端. XDebugClient 和 Xdebug 一起最初设计用于 PHP, 不过下面有一个自定义版本可用于 AutoHotkey_L 中.

改变:

  • 允许调试器引擎报告 "php" 外的其他语言.
  • 添加 AutoHotkey 语法高亮.
  • 自动监听调试器引擎的连接, 而不需要等待用户点击 开始监听.
  • 截去属性值中首个空字符及其后面的内容, 因为当前 AutoHotkey_L 返回整个变量的内容而 XDebugClient 无法正确显示二进制内容.

下载: 二进制; 源代码 (也请参见 SharpDevelop, Dockpanel Suite 和 Advanced Treeview.)

用法:

  • 运行 XDebugClient.
  • 运行 AutoHotkey_L /调试. XDebugClient 会自动打开脚本文件.
  • 在左边距点击以至少设置一个断点.
  • 在调试菜单中选择运行或按下 F5.
  • 执行到断点时, 使用调试菜单或快捷键进行单步调试或继续执行脚本.

特性:

  • 源码语法高亮只读显示.
  • 断点.
  • 运行, 逐语句/逐过程/跳出.
  • 查看调用堆栈.
  • 检查变量 - 选择变量名, 右击, 检查.

已知问题:

  • 当脚本运行时用户界面不响应用户的输入.
  • 没有提供列出变量或设置变量值的结构.

Notepad++ DBGp 插件

一个可作为 Notepad++ 插件使用的 DBGp 客户端. 它设计用于 PHP, 不过用于 AutoHotkey_L 时同样工作地很好.

下载: 参见 Notepad++ 插件目录.

用法:

  • 运行 Notepad++.
  • 通过 插件, DBGp, 配置... 配置 DBGp 插件

    注意: 必须配置文件映射. 大多数用户不进行远程调试, 因此可以简单地复选 忽略所有映射 (本地 windows 安装).

  • 通过工具栏或 插件, DBGp, 调试器 显示调试器面板.
  • 打开需调试的脚本文件.
  • 至少设置一个断点.
  • 运行 AutoHotkey_L /调试.
  • 使用调试器工具栏或快捷键控制调试器.

特性:

  • 根据用户的配置进行语法高亮显示.
  • 断点.
  • 运行, 逐语句/逐过程/跳出, 运行到光标, 停止.
  • 查看局部/全局变量.
  • 监视用户指定的变量.
  • 查看调用堆栈.
  • 悬停在变量上时显示其内容.
  • 可配置的快捷键 - 设置, 快捷映射..., 插件命令.

已知问题:

  • 悬停在单字母的变量名上时不会显示变量内容 - 例如, 悬停在 "a" 将试图获取 " a" 或 "a " 变量的内容.
  • 悬停在文本上将试图把文本作为变量名获取其内容, 即使文本中含有非法字符.
  • 如果属性获取失败 Notepad++ 会变得不稳定, 在上述问题的来源中这是显著的问题. 为了避过此问题, AutoHotkey_L 接到获取一个不存在或非法变量的请求时发送一个空属性而不是错误码.

基于脚本的客户端

可用于开发中的一个基于脚本的 DBGp 库 和两个基本的客户端:

  • dbgp_console.ahk: 简单的命令行客户端.
  • dbgp_test.ahk: 演示异步调试.

命令行客户端

xdebug.org 上有一个可用的命令行客户端, 然而它不适合大多数用户, 因为需要深入理解 DBGp (协议) 才能使用它.

其他

其他还有一些可用的 DBGp 客户端, 不过没有在 AutoHotkey_L 测试过. 关于这个, 参见 Xdebug: 文档.


Script Compatibility

脚本兼容性

由于 AutoHotkey Basic 和 AutoHotkey_L 的一些基本差异 (尤其是 Unicode 和 x64 版本), 为 AutoHotkey Basic 编写的脚本可能无法正常运行在 AutoHotkey_L 上. 此文档描述了当前已知的兼容性问题和解决方法.

Unicode 和 ANSI 的比较

由内置命令, 函数和运算符所需要或返回的存放在内存中的字符串使用特殊的二进制格式, 参考 原生格式. 这种格式取决于使用的 AutoHotkey 版本: Unicode 或 ANSI. 使用一种特殊格式设计的脚本使用错误的 AutoHotkey 版本运行时常常会遇到问题. 如果您不确定您正使用的是哪个版本, 则运行后面的脚本:

MsgBox % A_IsUnicode ? "Unicode" : "ANSI"

ANSI: 字符串存储为系统默认 ANSI 代码页编码, 和在 AutoHotkey Basic 一样. 每个字符为一个字节 (8 位).

Unicode: 字符串存储为 UTF-16 编码, 这里每个字符为两个字节 (16 位).

技术上, 一些 Unicode 字符表示为 两个 16-位代码单元, 一起被称为 "代理项对." 同样地, 一些 ANSI 代码页 (通常称为 双字节字符集) 含有一些双字节字符. 然而, 为了方便和实用它们实际上被视为两个单独的 "字符".

脚本文件

注意尽管 AutoHotkey 的每个版本仅支持一种特定的在内存中的字符串格式, 不过在脚本源代码文件中可以使用一些不同的编码. 如果包含有非 ASCII 字符的脚本使用的错误的编码, 那么将无法正确加载它们. Ahk2Exe 和 AutoHotkey_L 的 Unicode 版本默认要求 UTF-8, 而 ANSI 版本要求 ANSI. 想了解更多信息, 参见 脚本文件代码页.

VarSetCapacity

VarSetCapacity 设置一个变量占用的空间, 单位为字节. 由于一个字符占用空间的大小变化决定于字符串的编码格式，所以可能需要进行一些计算：

VarSetCapacity(ansi_var,    size_in_chars)
VarSetCapacity(unicode_var, size_in_chars * 2)
VarSetCapacity(native_var,  size_in_chars * (A_IsUnicode ? 2 : 1))
VarSetCapacity(native_var, t_size(size_in_chars))  ; 参见 下面
VarSetCapacity 内部将添加一个 字符 的容量以确保变量以空终止符结尾。然而，如果使用 非原生 编码的字符串将存储到变量中时为了保持一致性，size_in_chars 通常应该包含空终止符的大小。

DllCall

使用 "Str" 类型时，表示字符串使用当前版本原生的编码格式。由于一些函数可能需要或返回特殊格式的字符串，所以有时还需要使用下列的字符串格式：

 | 字符大小 | C / Win32 类型 | 编码
WStr | 16-位 | wchar_t*, WCHAR*, LPWSTR, LPCWSTR | UTF-16
AStr | 8-位 | char*, CHAR*, LPSTR, LPCSTR | ANSI （系统默认 ANSI 代码页）
Str | -- | TCHAR*, LPTSTR, LPCTSTR | 相当于 Unicode 版本中的 WStr 和 ANSI 版本中的 AStr。

如果 "Str" 或在当前版本中的等价类型用于参数中，那么字符串或变量的地址被传递给函数，否则创建一个期望格式的字符串临时副本进行传递。函数可以修改临时副本，但 不能 写入到这个字符串空终止符右边的任何位置。一般地， "AStr" 和 "WStr" 不应该用于输出参数中。

注意： "AStr" 和 "WStr" 用于参数和函数的返回值同样是有效的。

一般而言，如果脚本通过 DllCall 调用接受字符串参数的函数，那么必须采取以下其中一种方式：

  1. 如果函数的 Unicode (W) 和 ANSI (A) 都可用，那么为当前版本调用匹配的那个。在下面的例子中, "DeleteFile" 在内部被称为 "DeleteFileA" 或 "DeleteFileW"。由于 "DeleteFile" 自身实际并不存在，DllCall 自动根据当前版本尝试适合的 "A" 或 "W"。
    DllCall("DeleteFile", "Ptr", &filename)
DllCall("DeleteFile", "Str", filename)

    在这个例子中，&filename 准确按原样传递字符串地址，所以函数必须期望接受和 "Str" 类型相同编码格式的字符串。注意在 AutoHotkey Basic 中 "UInt" 必须使用 "Ptr" 代替，但得到的代码可能不兼容 64 位。

    注意： 如果无法根据名称准确找到指定的函数，在 AutoHotkey_L 中不管指定哪个 DLL 都会在函数名称后添加 "A" 或 "W" 后缀查找。然而，AutoHotkey Basic 则仅为 User32.dll，Kernel32.dll，ComCtl32.dll 或 Gdi32.dll 中的函数添加 "A" 后缀。

  2. 如果函数仅接受特殊类型的字符串作为输入，那么脚本可能必须使用相应的字符串类型：
    3. DllCall("DeleteFileA", "AStr", filename)
DllCall("DeleteFileW", "WStr", filename)
  3. 如果函数必须修改字符串（非原生格式），那么脚本必须如 上面 描述的那样分配缓存并且把缓存的地址传递给函数。如果参数接受输入，脚本还必须把输入字符串转换为适当的格式；这可以用 StrPut 实现。

NumPut / NumGet

当使用 NumPut 或 NumGet 操作字符串时，对于给定类型的字符串其偏移和类型都必须正确。可以参考下面的代码：

;  8 位/ANSI   字符串:  size_of_char=1  type_of_char="Char"
; 16 位/UTF-16 字符串:  size_of_char=2  type_of_char="UShort"
nth_char := NumGet(var, (n-1)*size_of_char, type_of_char)
NumPut(nth_char, var, (n-1)*size_of_char, type_of_char)

如果 var 含有原生格式的字符串，那么根据 A_IsUnicode 的值可以确定变量的值。

nth_char := NumGet(var, t_size(n-1), t_char())
NumPut(nth_char, var, t_size(n-1), t_char())

; 为了方便和清晰定义的函数:
t_char() {
    return A_IsUnicode ? "UShort" : "Char"
}
t_size(char_count=1) {
    return A_IsUnicode ? char_count : char_count*2
}

指针大小

指针在 32 位版本（包括 AutoHotkey Basic）中是 4 个字节大小而在 64 位版本中是 8 个字节。使用结构体或 DllCall 的脚本可能需要为在两种平台上正常运行进行考虑。受影响的特殊地方包括：

  • 含有一个或多个指针的结构体字段的偏移计算。
  • 含有一个或多个指针的结构体大小计算。
  • 在 DllCall，NumPut 或 NumGet 中使用的类型名称。

对于大小和偏移计算，使用 A_PtrSize。对于 DllCall，NumPut 和 NumGet，使用适当的 Ptr 类型。

记住一个字段的偏移常常是在它之前所有字段的总大小。同时注意句柄（包括类似 HWND 和 HBITMAP 的类型）实际上是指针类型。

/*
  typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess;    // Ptr
    HANDLE hThread;
    DWORD  dwProcessId; // UInt (4 字节)
    DWORD  dwThreadId;
  } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
*/
VarSetCapacity(pi, A_PtrSize*2 + 8) ; Ptr + Ptr + UInt + UInt
DllCall("CreateProcess", <简短地省略>, "Ptr", &pi, <省略>)
hProcess    := NumGet(pi, 0)         ; 默认为 "Ptr".
hThread     := NumGet(pi, A_PtrSize) ;
dwProcessId := NumGet(pi, A_PtrSize*2,     "UInt")
dwProcessId := NumGet(pi, A_PtrSize*2 + 4, "UInt")

其他变化

默认脚本

没有指定脚本运行 AutoHotkey_L 时，默认脚本文件名和当前可执行文件名相同但扩展名为 "ahk"。想了解更多细节，参见 传递命令行参数到脚本 。

变量和函数名

在变量名中字符 [ ] 和 ? 不再合法。因此，? （用于三元操作符）不再要求其两边为空格。也请参见 对象语法。

语法检查

命令名必须以空格，Tab 或逗号终止。与 AutoHotkey Basic 不同，后面的字符都必须符合这个要求：<>:+-*/!~&|^[]. 因此，像 MsgBox< foo 和 If!foo 这样的语法错误可以在加载时捕捉到，而不会作为 MsgBox,< foo 或 If !foo 那样解释。

Transform

一些 Transform 子命令在 Unicode 版本中发生了变化：

  • Unicode 不可用。要赋值 Unicode 文本到剪贴板，使用正常赋值。也请参见：StrPut/StrGet。
  • HTML 支持 附加特性。

If var is

此命令忽略系统区域设置，除非使用了 StringCaseSense, Locale。

FileRead

在某些情况下 FileRead 在代码页之间转换文本，因此可能输出错误的二进制数据。

Control-Z

Loop Read 和 FileReadLine 不会把字符 Control-Z (0x1A) 解释为文件末尾标记。因此任何的 Control-Z，即使某一个恰好出现在文件末尾，都原样加载。FileRead 已经采用这样的方式。

SetFormat, Integer[Fast], H

使用大写字母 H 时，十六进制数字中 A-F 也将为大写。不过在 AutoHotkey Basic 中总是使用小写数字。参见 SetFormat。

兼容模式

如果用于运行脚本的 EXE 文件属性中设置 兼容模式 为 Windows 95、98/ME 或 NT4，脚本可能无法正常运行。这是由于兼容模式会把特定的 Windows 版本报告给应用程序, 但预构建的二进制文件不支持这些版本。例如设置兼容模式为 Windows 95 或 98/ME 将使得 MsgBox %A_OSVersion% 报告 WIN_NT4.

Run / RunWait [AHK_L 57+]

除了自定义操作支持 (Run *verb file) 外，修订号 57 中还把从 Target 参数中提取操作及其参数的方式做了一些改变。具体地：

  • 如果 Target 以引号开始，那么到下一个引号之间的所有内容被视为操作。
  • 否则首个以空格结束并且为一个现有文件或以 .exe、.bat、.com、.cmd 或 .hta 结尾的子字符串被视为操作。这样就允许 .ahk、.vbs 或 .lnk 这样的文件类型接受参数，同时也允许像以前的版本那样不需要绝对路径运行“已知”的可执行文件例如 wordpad.exe。


Changes & New Features

This changelog only concerns AutoHotkey_L. Read AutoHotkey's changelog.

1.1.00.00 - May 1, 2011

New features:

Implemented basic class definition syntax.

Implemented the new keyword for creating a derived object.

Added Func() for retrieving a reference to an existing function and improved IsFunc to recognize function references.

Added support for ++ and -- with object fields, such as x.y[z]++.

Changes:

Changed __Delete to not trigger __Call.

Changed OnClipboardChange to use AddClipboardFormatListener when available (i.e. on Windows Vista and later) to improve reliability.

Auto-concat with ( is more selective, so some invalid expressions like 12(34) will no longer work.

Fixes:

Fixed SetTimer Label, -0 to be treated as "run-once, very soon".

Fixed A_MyDocuments etc. to use SHGetFolderPath instead of undocumented registry keys.

Fixed non-empty ExcludeText causing windows with no text to be excluded.

1.0.97.02 - April 14, 2011

Fixed misinterpretation of comma as an arg delimiter when enclosed in {} in an expression.

Fixed For-loop to set A_Index only after the Expression arg is evaluated, so that the outer loop's value can be used.

Fixed default script location to be based on the directory containing the EXE (as documented), not the working directory.

Improved load-time validation to detect invalid attempts to jump out of a function with Goto.

1.0.97.01 - April 2, 2011

Fixed the 64-bit build to not truncate HWNDs or SendMessage/PostMessage params to 32 bits.

Fixed */:: being treated as an invalid hotkey (broken since L54).

Fixed the icons.

1.0.97.00 - March 28, 2011

Added {key: value} as syntax sugar for Object("key", value).

Added [x, y, z] as syntax sugar for Array(x, y, z), which is a new function equivalent to Object(1, x, 2, y, 3, z).

Added slight optimization: resolve any reference to True, False, A_PtrSize or A_IsUnicode in expressions at load-time.

Fixed hotkey parser to treat x & ^y as an error instead of ignoring ^.

1.0.96.00 - March 21, 2011

New features:

ComObjQuery: Queries a COM object for an interface or service.

ComObjFlags: Retrieves or changes flags which control a COM wrapper object's behaviour.

ComObjCreate allows non-dispatch objects to be created if an interface identifier (IID) is given.

COM arrays support for-loops and the Clone() method.

ListVars shows the inner variant type and value of each COM wrapper object, in addition to the wrapper's address.

Changes:

When a literal integer or variable containing both a numeric string and cached binary integer is assigned to a field of an object, an integer is stored instead of a string. This particularly benefits scripts calling COM methods which accept integers but not strings, or have different behaviour depending on the type of value.

NULL values are now allowed with ComObjParameter for the VT_UNKNOWN and VT_DISPATCH types.

Improved support for Common Language Runtime (.NET) objects via COM.

FileRecycle should now warn before deleting a file which is too large to recycle.

When a SafeArray created with ComObjArray is assigned to an element of another SafeArray, a separate copy is created. This prevents the script from crashing due to a second attempt at "destroying" the array. ComObjFlags allows this behaviour to be avoided.

Fixes:

Assigning to a COM array of VT_DISPATCH or VT_UNKNOWN crashed the script.

Break and Continue were tolerated outside of loops in some cases.

Standalone carriage-return (`r) was not correctly interpreted as end-of-line.

MouseMove miscalculated negative coordinates with the Input and Event send modes.

Selecting Edit This Script from the tray menu or using the Edit command crashed the script (broken by v1.0.95).

Error dialogs pointed at irrelevant lines of code in some cases.

1.0.95.00 - March 12, 2011

All file I/O has been heavily optimized.

Added #Warn to assist with debugging; initial design by ac.

By default, if name_var contains a function name, name_var.() calls the function. This can be overidden via the default base object, as before.

Run supports verbs with parameters, such as Run *RunAs %A_ScriptFullPath% /Param.

If an operator which can accept either one operand (&x) or two numeric operands (x & y) follows a quoted literal string, auto-concat occurs and the operator is applied only to the right-hand operand. This is because quoted literal strings are always considered non-numeric and are therefore not valid input for numeric operators. For example, expressions like "x" &y and "x" ++y now work.

Fixed:

  • Wildcard hotkeys were not respecting modifiers such as ^!+ in specific cases.
  • File.Pos returned garbage for non-seeking file types; now it returns -1.
  • File.AtEOF was incorrectly true in some cases.
  • COM wrapper objects left A_LastError unset in some cases.
  • Gui submenu icons did not work on Windows 2000/XP/Server 2003.
  • SplashImage clipped the image if height > width.
  • ComObjConnect did not alert when the first parameter is invalid.
  • SplashImage now uses GDI+ only when the other methods fail, for compatibility.
  • Tilde in ~x:: now affects x & y:: in the same way that ~x & z:: would, instead of having no effect.
  • A_PriorHotkey and A_TimeSincePriorHotkey now have the expected values when used with #If.
  • RegExReplace did not advance through the string correctly after a match failure if the string contained non-ASCII characters.

1.0.92.02 - January 19, 2011

Fixed a memory leak which occurred when the return value of an object invocation or built-in function was not used, such as file.ReadLine() or SubStr(x,y,z) alone on a line.

Replaced the fix from v1.0.92.01 with a better fix, which also fixes k::MsgBox(),x:=y and doesn't break if().

1.0.92.01 - January 18, 2011

Changed: FileCreateDir now sets A_LastError.

Fixed: GuiControl() or similar was sometimes misinterpreted as a command.

1.0.92.00 - January 13, 2011

Added support for compound assignments with objects, such as x.y += z.

Improved IniWrite in Unicode builds to prevent an empty line from appearing at the top of each new file.

Improved the parser to be more permissive about what can follow {/}/Else, especially when combined.

1.0.91.05 - January 1, 2011

Fixed: Cleanup code in COM method calls was freeing the wrong parameters.

Fixed (ANSI): DllCall set incorrect length for wstr parameters on output.

Fixed: Variadic function calls were unstable when param object was empty.

1.0.91.04 - December 29, 2010

Fixed (Unicode): RegExReplace omitted all text up to StartingPosition (broken by v1.0.90.00).

1.0.91.03 - December 27, 2010

Fixed: RegEx callout subpattern vars - broken by v1.0.90.00.

1.0.91.02 - December 26, 2010

COM: Added protection against NULL IDispatch/IUnknown pointers.

COM: Skip QueryInterface for IDispatch if VT_DISPATCH is passed explicitly.

Minor fix for maintainability: obj.field := var now correctly yields SYM_STRING, not SYM_OPERAND.

1.0.91.01 - December 24, 2010

Fixed: Unexpected results with File.Write(Str) after text-reading.

Fixed: UTF BOM check caused unexpected results in files without a BOM.

Fixed (ANSI): Parsing loops and File.ReadLine() treated Chr(255) as EOF.

Fixed (Unicode): RegExReplace errors where the UTF-8 and UTF-16 lengths differed.

Fixed: Disabling the last hook hotkey breaks Input.

Added: Simple optimization for RegExMatch/Replace.

1.0.91.00 - December 21, 2010

All changes in this release are COM-related.

Added: ComObjError now returns the previous setting.

Added: ComObjType(co) and ComObjValue(co).

Added: ComObjMissing().

Added: ComObjArray() and basic SAFEARRAY support.

Added: "Take ownership" parameter for ComObjParameter().

Changed: Values passed to COM functions via ComObjParameter are no longer freed in the process of calling the function.

Changed: ComObj.x() now falls back to PROPERTYGET if member 'x' is not found. This fixes for-loops for some objects.

Changed: Wrap unhandled variant types in an object rather than returning integer value.

Changed: Manage VT_UNKNOWN/VT_ARRAY lifetime automatically, by default.

1.0.90.00 - November 27, 2010

Fixed: UrlDownloadToFile in Unicode builds on Windows < 7.

Fixed: Upper-ANSI characters were sent as Alt+0 in ANSI build.

Fixed: File.Pos was incorrect after attempting to read past EOF.

Fixed: Escape sequences in #If expressions and static initializers.

Fixed: ClipboardAll sometimes crashed the script with certain formats.

Fixed: Transform HTML calculated length incorrectly for &#NNN; entities.

Fixed: VarSetCapacity now correctly ignores #MaxMem for ByRef variables.

Fixed: FileAppend,,file.txt set ErrorLevel=1 even on success.

Fixed: Match length was miscalculated for RegEx callouts with the P) option.

Integrated Sean's improvements to number handling in COM interop.

Optimized RegExReplace and RegExMatch in Unicode builds.

Revision 61 - October 3, 2010

Added: ObjClone(Object), forgotten when Object.Clone() was implemented.

Added: Support for RegEx Unicode properties in Unicode builds. Also upgraded PCRE to 8.10.

Added: Object.Remove(int, "") removes Object[int] without affecting other keys.

Changed: ComObj.xyz() is now always treated as a method-call.

Changed: Var := 123 is now left as an expression, for consistency. This makes Var := 123 and Var := (123) equivalent, whereas previously the former assigned only a string and the latter assigned both a string and a cached binary integer. In particular, this avoids some confusing type mismatch errors with COM objects.

Fixed: Dynamic variadic calls to functions with mandatory parameters.

Fixed: The final parameter of an assume-global variadic function had to be explicitly declared local.

Fixed: Static initializers interfering with setting of breakpoints.

Fixed: More pointer size-related errors with PCRE callouts on x64 builds.

Fixed: Input with 'M' option treated Ctrl-M (`r) as Ctrl-J (`n).

Fixed: Object.Remove(n) returned 0 (not "") if Object[n] didn't exist.

Revision 60 - September 24, 2010

Added: File.Encoding for changing or retrieving the codepage in use by a File object.

Added: Variadic functions and function-calls and indirect mode for callbacks.

Added: Object.Clone()

Changed: ByRef parameters no longer require the caller to supply a variable.

Changed: Obj.foo := "" now frees foo's contents as originally intended (but still doesn't remove the field).

Changed: OnMessage functions now tolerate optional and ByRef parameters.

Changed: RegisterCallback now enables execute access on callbacks in 32-bit builds (already did in 64-bit builds).

Changed: RegisterCallback now treats explicit ParamCount="" as omitted.

Fixed: For-loop was treating non-expression "0" as true for scripted enumerators.

Fixed: ComEvent (ComObjConnect) not working on the ANSI build.

Fixed: ComEvent (ComObjConnect) not correctly backing up/restoring local vars when calling a function which is already running.

Fixed: Buffer overflow in A_EndChar when there is no end char.

Fixed: Func->mNextFunc not inititialized to NULL (used only by LowLevel scripts).

Debugger: Added the capability to retrieve an object's contents (with a supported debugger client).

Debugger: Fixed a few bugs.

Revision 59 - September 12, 2010

Fixed: #If expression should now evaluate each expression at most once per keypress in all cases.

Changed: SplashImage uses common image-loading routines; now supports PNG and similar, but results may differ from before for icon files.

Added: For x,y in z.

Added: Loop .. Until expression, usable with any Loop or For-loop.

Added: Named loops; continue outer_loop, break 2, etc.

Debugger: Encode stdout and stderr packets as UTF-8.

Debugger: Allow user to Abort, Retry or Ignore when the initial connection fails.

Debugger: Allow attaching a debugger client by sending the script a registered window message.

Debugger: Allow detaching debugger client by sending the "detach" DBGp command.

Revision 58 - September 5, 2010

Added: static var := expression

Revision 57 - September 4, 2010

Fixed Str*, WStr* and AStr* DllCall return types on x64.

Added functionality to InStr to bring it in line with StringGetPos:

  • If StartingPos is negative, the search is conducted right-to-left beginning at that offset from the end.
  • An additional parameter is available to specify which occurrence of the string to find.

Added #include <LibName> for explicitly including a script from a function library folder.

Added functionality to IniRead and IniWrite allowing an entire section to be read or written.

Added functionality to IniRead allowing a list of section names to be retrieved.

Added support for custom verbs to Run/RunWait: Run *verb file.

Made improvements to the way Run/RunWait extracts the action and its parameters from the Target parameter.

Changed NumGet/NumPut to allow Offset to be omitted entirely since Type is always non-numeric.

Removed the restriction that a label can't point to the end of a block.

Revision 56 - August 29, 2010

Added support for x64 compiled scripts. Requires Ahk2Exe_L and x64 AutoHotkeySC.bin.

Fixed: Deref operator (*addr) rejected addresses outside 32-bit range.

Fixed: #If expression memory allocation error on x64.

Fixed: Custom hotstring end chars with code points greater than U+00FF.

Fixed: Special characters being sent out of sequence by SendInput/Play.

Fixed: */ being discarded in continuation sections (see L54).

Revision 55 - August 19, 2010

Fixed: GroupActivate not setting ErrorLevel=1 if no Label was specified.

Fixed: Tab controls in x64 build.

Fixed: String-copy mode of StrPut when length is omitted; broken by L53.

Fixed: Data-alignment issues in x64 builds.

Changed: Set A_LastError for more File* commands to assist debugging.

Includes FileAppend, FileRead, FileReadLine, FileDelete, FileCopy, FileMove, FileGetAttrib/Time/Size/Version and FileSetAttrib/Time.

Excludes FileCopyDir, FileRecycle, FileMoveDir, FileRemoveDir, FileRecycleEmpty, FileCreateDir and FileInstall as the APIs used do not consistently set or return a Win32 error code.

Revision 54 - August 15, 2010

Fixed: RunAs in Unicode build. [jackieku]

Fixed: RegisterCallback in x64 build. [fincs]

Fixed: Executables failing to run on Win2k and WinXP prior to SP2. Win2k requires SP4 and updates (probably KB 816542). XP not tested.

Fixed: Dialogs such as MsgBox became unresponsive when interrupted by another script thread. Message filter/workaround added in L45 had to be removed. [Bug report]

Fixed: Multi-byte characters in default ANSI codepage; this was also causing a memory leak. [Bug report]

Fixed: ComObject now allows purely numeric property/method names. [Bug report]

Enhanced usability and capabilities of FileOpen/File object.

  • FileOpen's Flags parameter accepts a human-readable string of flags.
  • FileOpen's "update" mode has been renamed "read/write" and now creates the file if it didn't already exist.
  • FileOpen sets A_LastError as appropriate.
  • File := FileOpen(handle,"h") wraps an existing file handle in an object.
  • File.Seek(n) defaults to SEEK_END when n is negative.
  • File.Pos (or File.Position) can be used in place of Tell and Seek.
  • File.Pos, File.Length, File.AtEOF and File.__Handle can be used without empty parentheses().
  • File.Length can be set, as in File.Length:=n.
  • File.ReadNum() and File.WriteNum(n) read or write a number, where Num is a NumGet-compatible type name.
  • File.WriteLine(s) is equivalent to File.Write(s "`n"), for symmetry with File.ReadLine().
  • File.Read() reads and returns the remainder of the file when used without parameters.
  • File object now returns "" for unrecognized methods and invalid syntax rather than the numeric address of "".

Changed: GroupAdd's Label parameter now applies to the whole group. [Discussion]

Changed: GroupActivate sets ErrorLevel on success/failure. (Same thread as above.)

Changed: */ at the beginning of a line is ignored if there was no /*. [Discussion]

Removed ToCodePage and FromCodePage subcommands of Transform.

Revision 53 - August 8, 2010

Merged AutoHotkey64 - COM support and x64 compatibility.

x64 (changes since AutoHotkey64):

  • Fixed floating-point return values and exception handling for DllCall.
  • Fixed RegEx callouts.
  • Re-enabled GetProcAddress optimisation for DllCall.
  • NumPut and NumGet default to "Int64" in x64 builds.

COM (changes since AutoHotkey64):

  • Allow ComObjParameter to wrap 64-bit values in 32-bit builds.
  • Implemented more standard ref counting conventions in ComObjActive.
  • Prevent extraneous AddRef for new ComObjects in certain cases.
  • Don't treat pdispVal==NULL return value from Invoke as an error.
  • Fail more predictably when given wrong type of object.
  • Require explicit second param in ComObjType, don't assume "IID".
  • Free local vars after ComEvent calls a function.
  • Remove pVarResult param from ComEvent; use return value instead.
  • Pass the original wrapper ComObject in each ComEvent call.
  • Add context to ComError dialog; let the buttons make more sense.

Implemented common syntax validation code for enumerators. Enum[] and Enum.Next() are now supported with or without parameters. Enum[]:=val and similar obscure forms which worked in AutoHotkey_COM/AutoHotkey64 are not allowed.

"Ptr" type is still signed (unlike AutoHotkey64), for maximum flexibility and consistency.

Other changes:

Added: Object.HasKey(key).

Added: Object(obj) increments obj's reference count and returns its address.

Added: ObjAddRef() and ObjRelease().

Fixed: A_ThisHotkey now has the expected value when used with #If.

Fixed: RunAs in Unicode build (fixed by jackieku).

Changed: Default script codepage for ANSI builds is now CP0 (ANSI).

Changed: x.y[] is now equivalent to (x.y)[] rather than x["y"].

Changed: Built-in methods can now be called with or without the underscore prefix (e.g. obj.MaxIndex() or obj._MaxIndex()).

Revision 52 (again) - July 10, 2010

Added support for built-in and environment variables in double-derefs.

Improved support for multi-byte characters in certain codepages (previously only 932, 936, 949, 950 and 1361 were supported).

Fixed: StrPut failed for codepages which don't support WC_NO_BEST_FIT_CHARS, such as UTF-7.

Fixed: Double-deref as object - literal%var%.literal.

Fixed: StrPut("", Encoding) null-terminated an invalid address.

Revision 52 - June 12, 2010

Fixed: ObjRemove's Key parameter is now optional, as with Object._Remove.

Fixed: Files were improperly locked while reading, unlike in older versions.

Fixed: Uppercase Hex format caused negative integers to become unsigned.

Fixed: RegExMatch was corrupting output array items when specific conditions were met. See bug report.

Revision 51 - April 11, 2010

Changed: Use <EXENAME>.ahk instead of AutoHotkey.ini or AutoHotkey.ahk.

Changed: Default to UTF-8 for script files; override with /CPnnn.

Fixed: Unpause when the script exits so that object __Delete meta-functions can run.

Revision 50 - March 27, 2010

Improved flexibility of Object._Insert.

  • Object._Insert(x) - inserts x at _MaxIndex()="" ? 1 : _MaxIndex() + 1.
  • Object._Insert(i,x,y,z) - inserts x,y,z at i,i+1,i+2.

Improved flexibility of Object._Remove.

  • Object._Remove(k) - removes and returns the value associated with k.
  • Object._Remove() - removes and returns the value at _MaxIndex().

Added file share mode flags to FileOpen [by jackieku].

Fixed: 'P' option of RegExMatch incorrectly output 1 for subpatterns which did not match anything.

Fixed: Object._SetCapacity(key,n) was not null-terminating in some cases.

Fixed: StatusBarGetText returned only half of the text in Unicode builds.

Revision 49 - March 14, 2010

Added obj._NewEnum().

Added ObjMethod(obj) for each built-in obj._Method().

Changed: ObjSet/Get/Call can no longer be called/overridden by script.

Fixed: Potential crash caused by VK_PACKET check added in L48.

Fixed: Character codes in VK_PACKET events were potentially misinterpreted as scancodes.

Fixed: ExcludeText was ineffective after the first matching control.

Revision 48 - February 21, 2010

Fixed: Standalone obj.() was not recognized as a valid expression.

ControlSend now uses WM_CHAR to support characters which have no associated keycode. For instance, this applies to "…" (en-US), "∞" in a Unicode build and {U+221e} in either build.

KeyHistory now shows the full 16-bit character code for VK_PACKET (VK=E7) events. Send may indirectly cause these to be generated for Unicode characters.

Revision 47 - February 13, 2010

Fixed (Unicode): ControlGet,List with ListView controls.

Revision 46 - February 11, 2010

Added A_FileEncoding, which returns the current default file encoding.

Added StrPut and extended StrGet with additional features.

Revision 45 - February 8, 2010

Added _GetAddress; _SetCapacity/_GetCapacity may now operate on a given field. [more info]

Added workaround for WM_PAINT infinite loop often caused by subclassing.

Allow obj.() as a means to call the default method of an object; equivalent to obj[""]().

Dev: Added solution and project files for MSBuild 4.0 & VS2010. [more info]

Fixed (Unicode): 'Running' column in ListHotkeys.

Revision 44 - February 7, 2010

Fixed: Attempting to set "nothing" crashed the script. For instance, x[]:=z.

Fixed (Unicode): Unable to find default script (Documents\AutoHotkey.ahk).

Fixed (Unicode): A_Desktop, A_ProgramFiles and several other built-in variables which read their value from the registry caused strings to be incorrectly terminated.

Fixed (ANSI): Characters in the range 0x80-0xFF couldn't be found by InStr or StringReplace.

Changed (ANSI): Treat ToCodePage/FromCodePage like other unsupported/invalid subcommands.

Revision 43 - January 29, 2010

Fixed: obj.Func() resulting in a random integer when it should be an empty string.

Revision 42 - January 28, 2010

Merged with AutoHotkeyU.

Numerous bug-fixes and improvements, some relating to the merge.

Revision 41 - December 20, 2009

Fixed: Floating-point numbers were equivalent to an empty string when used as keys in objects. They are now converted to numeric strings in the current float format, as originally intended.

Revision 40 - December 13, 2009

Changed meta-functions and multi-param behaviour to improve flexibility. Meta-functions are now invoked *before* searching for an appropriate field in each base object; however, values in x.base will override meta-functions defined in x.base.base. Chaining meta-functions (inheritence) is now possible by avoiding "Return"

Improved Default Base functionality to be more consistent with real objects.

Changed (Debugger): While stepping through code, skip all braces except those which end a function.

Changed (Debugger): When stepping onto the hidden "Exit" at end of the script, consider it to be *below* the last physical line to avoid confusion.

Revision 39 - December 2, 2009

Fixed (Debugger): Error in Base64 decoding used by property_set.

Revision 38 - November 17, 2009

Added: #MenuMaskKey directive to change which key is used to mask Alt/Win keyup events. See this thread for background information.

Changed: If x[1,2]:=3 creates an object for x[1], it's base is no longer automatically set to x.base. See the documentation for a method of controlling this behaviour.

Revision 37 - November 7, 2009

Added: Support for obj[method_name](params) object-call syntax.

Revision 36 - November 4, 2009

Changed: If x.y or similar is immediately followed by an open-bracket ([), the right-most identifier preceding the bracket is treated as the first parameter of the operation. For instance, a.b.c[d] is equivalent to ObjGet(a.b,"c",d) and x.y[z]:=v is equivalent to ObjSet(x,"y",z,v). Previously each sub-expression preceding a bracket was evaluated separately.

Changed: If a method-call such as x.y() is followed immediately by an assignment, the parentheses are treated as brackets. For instance, x.y(z):=v is now equivalent to ObjSet(x,"y",z,v).

Fixed: If(expr) and While(expr) with no delimiting space or comma.

Revision 35 - October 25, 2009

Fixed: Standalone expressions beginning with two or more "dots", such as x.y.z(). (Broken by L34.) Note that '(' or '[' or ':=' is still required.

Revision 34 - October 24, 2009

Changed: Setting a value within an object to an empty string now stores the empty string rather than removing the key-value pair from the object. _Remove can still be used to completely remove key-value pairs.

Changed: Command names must be terminated with a space, tab or comma. The following characters no longer bypass this requirement: <>:+-*/!~&|^[]. For instance, syntax errors such as MsgBox< foo and If!foo are now caught at load-time.

Fixed: Return now properly handles expressions which result in a variable containing an object. For instance, Return x:=y, Return (x), Return x,... and similar should work now (Return x already worked).

Fixed: Multi-parameter get/set did not correctly support meta-functions for multiple objects (such as for x and x[y] in the expression x[y,z]).

Fixed: Cascading object-assignments such as the x[y]:=z in r:=x[y]:=z could not yield numbers or objects - broken by L33.

Fixed: x._Remove(y) crashed the script or removed the wrong item if x did not contain y.

Fixed: x.=y, if x.y=... and similar. May affect other expressions.

Fixed: Standalone ternary expressions no longer requires spaces. For instance, x? F(1) : F(2) is now allowed.

Debugger: On script exit, disconnect debugger *after* releasing objects to allow debugging of __Delete handlers.

Revision 33 - October 3, 2009

Fixed: Local variables were not automatically freed for functions which return objects or pure numbers.

Fixed: Two separate reference-counting errors related to ternary operator and Object().

Fixed: If a string returned by a scripted object function was assigned directly to a variable, the variable's length was set incorrectly.

Fixed: If the last operation in an expression retrieved a string from a temporary object, the object and string were freed prematurely.

Fixed: Numeric strings with special formatting were not preserved when returned from a function via a variable or passed to a recursive function.

Fixed: If the final result of an expression (other than for Return) is an object, correctly yield an empty string instead of silently aborting the thread.

Fixed: __Delete meta-functions sometimes overwrote temporary values in the deref buffer.

Added: An address retrieved via &object may be cast back into an object reference by using Object(address).

Revision 32 - September 26, 2009

Fixed: Send/PostMessage crash when less than three parameters were specified.

Revision 31 - September 26, 2009

Added: Object/array support and numerous minor changes to make this possible.

Added: Support for While(expression) with no delimiting space.

Added: Trim, LTrim, RTrim.

Added: A ~= B; equivalent to RegExMatch(A, B). May be removed in a future revision.

Fixed: An incompatibility with LowLevel.

Changed: Characters [, ] and ? are no longer valid in variable names. Consequently, ? (ternary) no longer requires a space on either side.

Changed: Optional parameters may now be omitted at any position in the parameter list of a non-dynamic function call. Since this works by automatically inserting the parameter's default value at load-time, it is not supported or allowed for dynamic function-calls.

Debugger: Various minor changes to make program flow easier to follow while stepping through code.

Optimization: If DllCall's first parameter is a literal string which identifies a function already present in memory, it is replaced with the actual address of the function.

Updated from v1.0.48.03 to v1.0.48.04.

Revision 30 - May 31, 2009

Updated from v1.0.48.02 to v1.0.48.03.

Revision 29 - May 2, 2009

All supported image formats may now be used as menu icons. Currently it is necessary to specify "actual size" when setting the icon to preserve transparency on Windows Vista and later. For example:

Menu, Icon, MenuItemName, Filename.png,, 0

Revision 28 - May 2, 2009

Improved average-case performance of dynamic function calls by implementing binary search for function name look-ups. This change also applies to other areas, such as load-time resolution of function references in expressions and run-time resolution by OnMessage, RegisterCallback, etc.

Revision 27 - April 26, 2009

Updated from v1.0.48.00 to v1.0.48.02.

Revision 26 - April 11, 2009

Fixed: Menu icons were not drawn on items which have sub-menus if owner-drawing was in use.

Fixed: Menu icons were not freed if all menu items were deleted at once.

Changed (Source): Renamed AutoHotkey.sln to AutoHotkey_L.sln to allow VS window to be identified more easily.

Revision 25 - March 30, 2009

Fixed: Send {U+xxxx} correctly sets modifier key-state as with any normal key.

Fixed: Send {U+..xx} no longer triggers hotkey SCxx.

Revision 24 - March 30, 2009

Added: Support for Send {U+xxxx}. SendInput() is used where available for proper unicode support, otherwise falls back to Alt+Numpad.

Revision 23 - March 30, 2009

Fixed: GuiControl, Enable/Disable now only resets focus if the focused control was disabled.

Revision 22 - March 26, 2009

Optimized If var [not] in/contains MatchList, especially for long lists containing shorter fields.

Revision 21 - March 16, 2009

Minor optimizations to While. [thanks Chris]

Fixed (Debugger): Revisions 19 and 20 omitted timer threads from the call stack.

Fixed (Debugger): XML-reserved characters were not escaped in most situations.

Fixed (Debugger): Incorrect command and transaction_id were used in the final response before exiting the script.

Revision 20 - February 27, 2009

Changed: If an icon cannot be loaded with the new method, fall back to the old method.

Revision 19 - February 26, 2009

Added: Gui, Font, qN option to set font quality/control anti-aliasing, where N is between 0 and 5.

Fixed: IL_Add now loads icons at the most appropriate size when multiple sizes exist.

Merged with AutoHotkey v1.0.48, introducing bug fixes, optimizations and other changes by Chris. Some AutoHotkey_L features were integrated into the mainstream release; changes to these features since previous revisions are as follows:

  • Legacy behaviour is no longer applied to While - e.g. "While %x%" is correctly interpreted as a double-deref rather than as "While x".
  • One-True-Brace style is now supported for While.
  • Static vars may now be declared and initialized in assume-static functions.
  • Passing too few parameters in a dynamic function call is no longer allowed, as it allows the function's caller to second-guess the function's designer, reduces the ability to detect script bugs at runtime, and may cause the application to crash if calling a built-in function.

Revision 18 - February 21, 2009

Fixed: Incomplete bug-fix in previous revision causing concat followed by assignment to skip the rest of the expression in some cases.

Revision 17 - February 20, 2009

Added: Menu icons via Icon and NoIcon sub-commands of the Menu command.

Changed: Negative icon numbers can now be used to indicate a resource ID within an executable.

Changed: Set default style of menus to include MNS_CHECKORBMP.

Changed: Load both small and large versions of custom tray icons to allow the correct icons to be shown in the appropriate places.

Fixed: Loading of icons from executable files at sizes other than the system small/large.

Revision 16 - February 4, 2009

Fixed: Deleting a menu item partially deleted its associated sub-menu.

Revision 15 - February 1, 2009

Fixed: SetFormat's presence in a *compiled* script was not disabling binary number write-caching. SetFormat should now work correctly in compiled scripts.

Revision 14 - February 1, 2009

Numerous bug-fixes and optimizations by Chris (pre-v1.0.48 beta).

Added: Support for regex callouts and the auto-callout option 'C'.

Changed: A_AhkVersion now includes the revision number. For instance, this is 1.0.47.07.L14.

Fixed: HWND's/window ID's were sign-extended to 64-bit. For instance, 0xb482057e became 0xffffffffb482057e.

Revision 13 - November 29, 2008

Fixed: Invalid DllCall types were treated as INT in some build environments.

Added: Workaround for GuiEscape issue when disabling focused control.

Changed version info: InternalName, ProductName and FileDescription are now "AutoHotkey_L" instead of "AutoHotkey".

Revision 12 - September 6, 2008

Fixed: Potential access violation when using property_get on a built-in variable. -- DBGP

Revision 11 - September 5, 2008

Fixed: Remove checksum from AutoHotkeySC.bin via post-build script (AutoHotkey must be installed).

Added: .L suffix to A_AhkVersion.

Added: Preliminary support for DBGp (interactive debugging).

Revision 10 - August 2, 2008

Fixed: WheelLeft/WheelRight support, which was broken in revision 9.

Revision 9 - July 29, 2008

Fixed: Allow Break/Continue in While.

Fixed: TrayTip in non-English Windows and possibly other side-effects of using Vista headers.

Revision 8 - July 27, 2008

Added: #IfTimeout directive to set the timeout for evaluation of #If expressions, in milliseconds. Default is 1000.

Added: Assume-static mode for functions. "Static" must precede any local/global variable declarations.

Added: One-true-brace support for While.

Changed: While now sets A_Index to the iteration about to begin.

Revision 7 - July 26, 2008

Added: IsFunc(FuncName) - Returns a non-zero number if FuncName exists in the script or as a built-in function.

Revision 5 - July 19, 2008

Cleaned up obsolete references to test scripts.

Added basic default test script.

Revision 4 - July 18, 2008

Added: #if (expression) - Similar to #IfWinActive, but for arbitrary expressions.

Added: WheelLeft, WheelRight - Support for WM_MOUSEHWHEEL, which was introduced with Windows Vista. (Requires Vista.)

Added: While, expression - Loop while a condition is true.

Added: A_IsPaused - True if the underlying thread is paused.

Added: A_IsCritical - True if the current thread has been marked uninterruptible by the "Critical" command.

Changed: Allow any number of parameters to be passed in dynamic function calls.

Fixed: Access Violation caused by WinGetClass and subclassed windows.

Fixed: Access Violation caused by empty dynamic function references.


对象

AutoHotkey 中的 对象 是一种抽象数据结构, 它提供三个基本功能:

  • 取值.
  • 设置值.
  • 调用方法 (即可以对目标对象进行某些操作的函数).

对象 引用 是指向特殊对象的指针或 "句柄". 和字符串和数字一样, 对象引用可以存储到变量中, 传递给函数或从函数返回以及保存到对象中. 在从一个变量复制引用到另一个后, 例如 x := y , 两个变量都引用相同的对象.

IsObject 可以用来确定一个值是否为对象:

Result := IsObject(expression)

目前主要有三种对象类型:

  • 对象 - 脚本化关联数组.
  • 文件 - 为文件输入/输出提供接口.
  • ComObject - 打包 IDispatch 接口 (COM 或 "自动化" 对象).

目录

  • 基本用法 - 简单数组, 关联数组, 对象, 备注
  • 扩展用法 - 函数引用, 数组嵌套, 函数数组
  • 自定义对象 - 原型, 类, 创建和销毁, 元函数
  • 默认基对象 - 自动初始化变量, 伪属性, 调试
  • 实现 - 引用计数, 指向对象的指针

基本用法

简单数组

创建数组:

Array := [Item1, Item2, ..., ItemN]
Array := Array(Item1, Item2, ..., ItemN)

获取项:

Value := Array[Index]

对项进行赋值:

Array[Index] := Value

附加项:

Array.Insert(Value)

在指定的索引插入一项或多项:

Array.Insert(Index, Value, Value2, ...)

移除项:

RemovedValue := Array.Remove(Index)

如果数组不是空的, 那么 MinIndex 和 MaxIndex 分别返回数组中当前使用的最小和最大的索引. 由于最小的索引几乎总是 1, 所以 MaxIndex 经常返回项目数. 对数组内容进行依次循环可以通过索引或 For 循环实现. 例如:

array := ["one", "two", "three"]

; 从 1 到项目数进行重复:
Loop % array.MaxIndex()
    MsgBox % array[A_Index]

; 枚举数组内容:
For index, value in array
    MsgBox % "Item " index " is '" value "'"

关联数组

关联数组是包含唯一键集合和值集合的对象, 其中每个键和一个值关联. 键可以为字符串, 整数或对象, 而值可以为任何类型. 关联数组可以用如下方法创建:

Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}
Array := Object("KeyA", ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)

使用 {key:value} 表示法时, 对于仅由单词字符组成的键, 其两边的引号标记是可选的. 可以使用任何表达式作为键, 但使用变量作为键时, 它必须包围在小括号中. 例如, {(KeyVar): Value} 和 {GetKey(): Value} 都是合法的.

获取项:

Value := Array[Key]

对项进行赋值:

Array[Key] := Value

移除项:

RemovedValue := Array.Remove(Key)

枚举项:

array := {ten: 10, twenty: 20, thirty: 30}
For key, value in array
    MsgBox %key% = %value%

关联数组可以是稀疏居住的 - 即 {1:"a",1000:"b"} 仅包含两个键值对, 而不是 1000.

到现在, 您也许已经注意到关联数组使用与简单数组非常相似的语法. 事实上, 在 v1.x 中它们是相同的东西. 然而, 把 [] 视为简单线性数组有助于保持其作用清晰, 并且改善您脚本与 AutoHotkey 未来版本的兼容性, 未来版本中可能改变实现方式.

对象

获取属性:

Value := Object.Property

设置属性:

Object.Property := Value

调用方法:

ReturnValue := Object.Method(Parameters)

使用可推算的方法名调用方法:

ReturnValue := Object[MethodName](Parameters)

COM 对象和用户定义对象的一些属性可以接受参数:

Value := Object.Property[Parameters]
Object.Property[Parameters] := Value

相关: 对象, 文件对象, Func 对象, COM 对象

已知限制:

  • 当前 x.y[z]() 会被视为 x["y", z](), 这是不受支持的. 作为一种变通方法, `(x.y)[z]() 首先计算 x.y, 然后把结果作为方法调用的目标. 转义的左括号 (`() 使得表达式可以在行首使用, 然而行首的左括号没有进行转义时将开始一个延续片段. 注意 x.y[z].() 没有这个限制, 因为对它求值的方式和 (x.y[z]).() 一样.

备注

语法

数组语法 (小括号) 和对象语法 (点) 可以替换使用.

同时, 对象引用自身也可以用在表达式中:

  • 当对象引用使用 = == != <> 中的一种比较运算符和其他值比较时, 仅在两个值都为指向相同对象的引用时它们才被视为相等的.
  • 进行逻辑运算时对象总是被视为 true, 例如在 if obj, !obj 或 obj ? x : y 中.
  • 使用 & 取址运算符可以获取对象的地址. 它从此对象创建时到此对象的最后一个引用被 释放 期间唯一标识此对象.

如果在不期望对象的地方使用对象, 那么它被视为空字符串. 例如, MsgBox %object% 显示空的 MsgBox 且 object + 1 产生空字符串. 由于这种特性可能会变化, 所以不要依赖它.

当方法调用紧接着赋值运算符, 那么它等同于用参数来设置属性. 例如, 下面的语句是等同的:

obj.item(x) := y
obj.item[x] := y

还支持复合赋值例如 x.y += 1 和 --arr[1].

键

对于哪种值可以在通过 [], {} 或 new 运算符创建的对象中作为键使用的一些限制:

  • 整数键使用本机有符号整数类型存储. AutoHotkey 32 位支持使用从 -2147483648 到 2147483647 范围内的整数作为键. AutoHotkey 支持 64 位整数, 但仅 AutoHotkey 64 位版本才支持完整范围的整数在对象中作为键使用.
  • 由上面这点可知, 整数值的字符串格式不会被保留. 例如, x[0x10], x[16] 和 x[00016] 都是等同的. 这点同样适用于不含小数点的数值型字符串.
  • 用引号括起来的原义字符串在 v1.x 中被视为纯非数值型, 所以 x[1] 和 x["1"] 是 不 等同的. 同时, 如果原义字符串和另一个值串联在一起 (如同在 "0x" x), 结果被视为纯非数值型. 不过, 这不适用于变量, 所以 x[1] 和 x[y:="1"] 是等同的. 此问题将在 v2 中解决, 所以脚本应避免使用用引号括起来的原义字符串作为键.
  • 不支持使用浮点数作为键 - 而是把它们转换成字符串. 在 v1.x 中, 浮点数文字保留它们原始的格式, 而纯浮点数 (例如 0+1.0 或 Sqrt(y) 的结果) 被强制转换成当前的 浮点格式. 考虑到一致和清晰, 脚本中应避免使用浮点文字作为键.
  • 字符串键 "base" 没有和 Insert 一起使用时具有特殊含义.

扩展用法

函数引用 [v1.1.00+]

如果变量 func 包含一个函数名, 此函数可以通过两种方式进行调用: %func%() 或 func.(). 然而, 由于这样需要每次都对函数名进行解析, 所以多次调用函数时效率低下. 为了改善性能, 脚本可以获取到函数的引用并保存以供后面使用:

Func := Func("MyFunc")

通过引用调用函数时, 必须使用下面的语法:

RetVal := Func.(Params)

有关函数引用的附加属性的详细信息, 参见 Func 对象.

已知限制:

  • 如果它所调用的函数或子程序中使用了 Exit, 它表现的如同函数调用创建了新线程. 即它立即返回到函数的调用者而不会终止当前线程. 但是, 如果脚本不是 持续运行的, 那么它仍会使脚本终止.

数组嵌套

通过透明地把数组存储到其他数组中 AutoHotkey 可以支持 "多维" 数组. 例如, 表格可以表示为行数组, 这里每个行自身是一个列数组. 此时, x 行 y 列的内容可以用以下两种方法的其中之一进行设置:

table[x][y] := content  ; A
table[x, y] := content  ; B

如果 table[x] 不存在, A 和 B 在两个方面有区别:

  • A 失败而 B 会自动创建一个对象并把它存储到 table[x] 中.
  • 如果 table 的 base 定义了 元函数, 可以用如下方式调用它们:
    table.base.__Get(table, x)[y] := content   ; A
table.base.__Set(table, x, y, content)     ; B
    因此, B 可以让对象为全面赋值定义定制的行为.

这种行为仅适用于由脚本创建的对象, 而不适合特殊的对象类型例如 COM 对象或 COM 数组.

函数数组

函数数组是包含函数名或引用的简单数组. 例如:

array := [Func("FirstFunc"), Func("SecondFunc")]

; 调用每个函数, 传递 "foo" 参数:
Loop 2
    array[A_Index].("foo")

; 调用每个函数, 隐式地把数组自己作为参数传递:
Loop 2
    array[A_Index]()

FirstFunc(param) {
    MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)
}
SecondFunc(param) {
    MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)
}

为了能够向后兼容, 如果 array[A_Index] 含有函数名而非函数引用时, 在第二中形式中 array 将不会作为参数被传递. 但是, 如果 array[A_Index] 继承 自 array.base[A_Index], 那么 array 将作为参数被传递.

自定义对象

AutoHotkey 中的对象是基于原型而不是基于类. 即对象可以从其原型或 base 对象中继承属性和方法, 但不需要有预定义结构. 在任何时候, 属性和方法还可以添加到 (或从中移除) 一个对象或它所派生自的任何对象. 不过, AutoHotkey 通过把 类定义 转化为普通对象来模仿类. 有关更多复杂或特殊解决方法, 通过定义 元函数 基对象可以覆盖标准行为.

要从其他对象继承创建对象, 脚本可以赋值 base 或使用 new 关键字:

baseObject := {foo: "bar"}
obj1 := Object(), obj1.base := baseObject
obj2 := {base: baseObject}
obj3 := new baseObject
MsgBox % obj1.foo " " obj2.foo " " obj3.foo

原型

原型或 base 对象和其他任何对象一样创建和操作. 例如, 带有单属性和单方法的普通对象可以这样创建:

; 创建对象.
thing := {}
; 存储值.
thing.foo := "bar"
; 通过存储函数引用创建方法.
thing.test := Func("thing_test")
; 调用方法.
thing.test()

thing_test(this) {
   MsgBox % this.foo
}

调用 thing.test() 时, thing 会自动被插入到参数列表的开始处. 然而, 为了能够向后兼容, 通过名称 (而不是通过引用) 把函数直接保存到对象中 (而不是继承自基对象) 时这种情况不会发生. 按照约定, 通过结合对象 "类型" 和方法名来命名函数.

如果另一个对象继承自一个对象, 那么这个对象被程为 原型 或 基:

other := {}
other.base := thing
other.test()

此时, other 从 thing 继承了 foo 和 test. 这种继承是动态的, 所以如果 thing.foo 被改变了, 这改变也会由 other.foo 表现出来. 如果脚本赋值给 other.foo, 值存储到 other 中并且之后对 thing.foo 任何改变都不会影响 other.foo. 调用 other.test() 时, 它 这里的 参数包含到 other 而不是 thing 的引用.

类 [v1.1.00+]

为了方便和熟悉性, "class" 关键字可以用来创建基对象. 基类定义看起来也许像这样:

class ClassName extends BaseClassName
{
    var ClassVar := Expression

    class NestedClass
    {
        ...
    }

    Method()
    {
        ...
    }
}

在加载脚本时, 这里会创建对象并将其存储到全局变量 ClassName 中. 因此要引用函数中的这个类, 如果函数不处于 假设全局模式, 那么需要进行声明例如 global ClassName. 如果出现了 extends BaseClassName, 那么 BaseClassName 必须为之前定义的类的完整名称. 每个类的完整名称存储在 object.__Class 中.

类定义可以包含类变量声明, 方法定义和内嵌的类定义.

    var ClassVar := Expression

类变量 声明例如上面这个比把一个值保存到类对象中做的更多一点. 如同类对象包含的任何值或方法, 这个值可以被派生自 ClassName 的对象继承. Expression 仅在脚本自动执行段之前计算一次. 类和 静态 变量声明根据它们在脚本中定义的次序计算.

    class NestedClass
    {
        ...
    }

嵌套类 定义允许类对象存储到另一个类对象中而不作为单独的全局变量. 在上面的例子中, class NestedClass 创建了一个对象并把它保存到 ClassName.NestedClass. 因此, NestedClass 可以被派生自 ClassName 的任何类或对象继承.

    Method()
    {
        ...
    }

方法 定义看起来和函数定义相同. 每个方法都有一个名称为 this 的隐藏参数, 它实际上包含了指向继承自此类的对象的引用. 不过, 它也可以包含指向此类自身或派生类的引用, 取决于如何调用这个方法. 方法被 通过引用 存储到类对象中.

除了隐藏参数 this, 方法定义中还可以使用伪关键字 base 以调用包含了此方法定义的类的基类. 例如, 在上面的方法中 base.Method() 相当于 BaseClassName.Method.(this), 除非全局变量 BaseClassName 不需要进行声明. 注意这里与 this.base.base.Method() 在其他两方面有区别:

  • 它总是调用当前类的基, 即使 this 继承自当前类的 子类.
  • 它自动传递 this, 而不是 this.base.base.

base 仅在后面跟着点 . 或方括号 [] 时才有特殊含义, 所以像 obj := base, obj.Method() 这样的代码将不起作用. 通过为 base 赋值这样脚本可以禁用其的特殊行为; 但是不建议这样做. 因为变量 base 必须为空, 所以如果脚本中不含有 #NoEnv 指令那么性能可能会降低.

创建和销毁

每当使用 new 关键字 [需要 v1.1.00+] 创建派生对象时, 那么调用由其基对象定义的 __New 方法. 此方法可以接受参数, 初始化对象并通过返回值覆盖 new 运算符的结果. 销毁对象时, 则调用 __Delete. 例如:

m1 := new GMem(0, 20)
m2 := {base: GMem}.__New(0, 30)

class GMem
{
    __New(aFlags, aSize)
    {
        this.ptr := DllCall("GlobalAlloc", "uint", aFlags, "ptr", aSize, "ptr")
        if !this.ptr
            return ""
        MsgBox % "New GMem of " aSize " bytes at address " this.ptr "."
    }

    __Delete()
    {
        MsgBox % "Delete GMem at address " this.ptr "."
        DllCall("GlobalFree", "ptr", this.ptr)
    }
}

元函数

元函数是由对象的基定义的方法, 这里可以明确定义在接受未知键的请求时对象应如何处理. 例如, 如果 obj.key 尚未赋值, 那么它会调用 __Get 元函数. 同样地, obj.key := value 调用 __Set 而 obj.key() 调用 __Call.

在这些情况中, 按如下方式调用基对象:

  • 如果此基对象定义了相应的元函数, 那么调用它. 如果元函数明确 return, 那么把返回值作为运算的结果且不进行进一步的处理.

    Set: 如果运算成功, __Set 应该返回这个字段的新值, 这可能与原始的 r 值不同. 这样允许赋值链, 例如 a.x := b.y := z. 如果赋值失败那么应该返回空字符串, 这样脚本可以检测到发生了错误.

  • 如果是 get 或 call 运算, 那么在基对象自身的字段中搜索匹配的键.

    Get: 如果找到, 那么返回这个字段的值.
    Call: 如果找到, 那么 (通过名称或 引用) 调用保存在这个字段中的函数, 并把原始目标对象作为 this 参数传递过去.

  • 递归调用其自己的基对象. 这样就可以从其基对象, 基对象的基等 "继承" 对象的属性.

当 (且仅当) 没有基对象处理运算时, 处理照常进行:

  • Get: 如果此键为 "base", 那么获取对象的基.
  • Set: 如果此键为 "base", 那么设置对象的基; 非对象的值会移除现有的基.

    否则创建一个新键值对并存储到对象中.

  • Call: 调用 内置方法.

已知限制:

  • 使用不带值的 return 等同于 return "". 这种情况可能在未来的版本中改变, 所以可以使用 return 来从元函数 "退出" 而不覆盖默认行为.
  • 参见 Exit 限制.

动态属性

__Get 和 __Set 可以用来实现在某些情况下可以计算或限制的值的属性. 例如, 可以用来实现含 R, G, B 和 RGB 属性的 "Color" 对象, 这里只有 RGB 值是实际存储的:

red  := new Color(0xff0000), red.R -= 5
cyan := new Color(0x00ffff)

MsgBox % "red: " red.R "," red.G "," red.B " = " red.RGB
MsgBox % "cyan: " cyan.R "," cyan.G "," cyan.B " = " cyan.RGB

class Color
{
    __New(aRGB)
    {
        this.RGB := aRGB
    }

    __Get(aName)
    {
        if (aName = "R")
            return (this.RGB >> 16) & 255
        if (aName = "G")
            return (this.RGB >> 8) & 255
        if (aName = "B")
            return this.RGB & 255
    }

    __Set(aName, aValue)
    {
        if aName in R,G,B
        {
            aValue &= 255

            if      (aName = "R")
                this.RGB := (aValue << 16) | (this.RGB & ~0xff0000)
            else if (aName = "G")
                this.RGB := (aValue << 8)  | (this.RGB & ~0x00ff00)
            else  ; (aName = "B")
                this.RGB :=  aValue        | (this.RGB & ~0x0000ff)

            ; 必须使用 'Return' 表示不应该创建一个新键值对.
            ; 这里也定义了在 'x := clr[name] := val' 中将要存储到 'x' 中的内容:
            return aValue
        }
    }
}

对象作为函数

生成一个调用时例如 obj.func(param), obj.func 可以包含函数名或对象. 如果 obj.func 包含对象, 那么把 obj 作为键进行调用. 在大多数情况下 obj.func[obj] 不存在, 所以调用 obj.func 的 __Call 元函数 代替. 这可以用来以一种抽象的方式改变函数调用的行为, 如以下示例所示:

; 为函数数组创建原型.
FuncArrayType := {__Call: "FuncType_Call"}
; 创建函数数组.
funcArray := {1: "One", 2: "Two", base: FuncArrayType}
; 把此数组作为方法创建对象.
obj := {func: funcArray}
; 调用方法.
obj.func("foo", "bar")

FuncType_Call(func, obj, params*)
{
    ; 调用函数列表.
    Loop % ObjMaxIndex(func)
        func[A_Index](params*)
}

One(param1, param2) {
    ListVars
    Pause
}
Two(param1, param2) {
    ListVars
    Pause
}

把这种技术和类定义组合在一起为定义类似于前面部分的动态属性提供了便利的方法:

blue := new Color(0x0000ff)
MsgBox % blue.R "," blue.G "," blue.B

class Properties
{
    __Call(aTarget, aName, aParams*)
    {
        ; 如果 this 属性对象包含此半属性的定义, 那么调用它.
        ; 小心别使用 this.HasKey(aName), 因为这样会递归进 __Call.
        if IsObject(aTarget) && ObjHasKey(this, aName)
            return this[aName].(aTarget, aParams*)
    }
}

class Color
{
    __New(aRGB)
    {
        this.RGB := aRGB
    }

    class __Get extends Properties
    {
        R() {
            return (this.RGB >> 16) & 255
        }
        G() {
            return (this.RGB >> 8) & 255
        }
        B() {
            return this.RGB & 255
        }
    }

    ;...
}

子类化数组嵌套

在 多参数赋值 例如 table[x, y] := content 会隐式地创建一个新对象, 这个新对象一般不含基, 因此没有自定义方法或特殊行为. __Set 可以用来初始化这样的对象, 如下所示.

x := {base: {addr: Func("x_Addr"), __Set: Func("x_Setter")}}

; 赋值, 隐式调用 x_Setter 来创建子对象.
x[1,2,3] := "..."

; 获取值并调用示例方法.
MsgBox % x[1,2,3] "`n" x.addr() "`n" x[1].addr() "`n" x[1,2].addr()

x_Setter(x, p1, p2, p3) {
    x[p1] := new x.base
}

x_Addr(x) {
    return &x
}

由于 x_Setter 含有四个必需参数, 所以只有在有两个或更多键参数时才会调用它. 当上面的赋值出现时, 会发生下面的情况:

  • x[1] 不存在, 所以调用 x_Setter(x,1,2,3) (由于参数过少所以 "..." 不会被传递).
    • x[1] 被赋值为与 x 含有相同基的新对象.
    • 不返回任何值 – 赋值继续.
  • x[1][2] 不存在, 所以调用 x_Setter(x[1],2,3,"...").
    • x[1][2] 被赋值为与 x[1] 含有相同基的新对象.
    • 不返回任何值 – 赋值继续.
  • x[1][2][3] 不存在, 但由于 x_Setter 需要四个参数而这里只有三个 (x[1][2], 3, "..."), 所以不会调用它且赋值正常完成.

默认基对象

当非对象值用于对象语法时, 则调用 默认基对象. 这可以用于调试或为字符串, 数字和/或变量定义全局的类对象行为. 默认基可以使用带任何非对象值的 .base 进行访问; 例如, "".base. 尽管默认基无法像 "".base := Object() 这样进行 set, 不过它可以有自己的基如同在 "".base.base := Object() 中那样.

自动初始化变量

当使用空变量作为 set 运算的目标时, 它直接被传递给 __Set 元函数, 这样它就有机会插入新对象到变量中. 为简洁起见, 此示例不支持多个参数; 如果需要, 可以使用 可变参数函数 实现.

"".base.__Set := Func("Default_Set_AutomaticVarInit")

empty_var.foo := "bar"
MsgBox % empty_var.foo

Default_Set_AutomaticVarInit(ByRef var, key, value)
{
    if (var = "")
        var := Object(key, value)
}

伪属性

对象 "语法糖" 可以适用于字符串和数字.

"".base.__Get := Func("Default_Get_PseudoProperty")
"".base.is    := Func("Default_is")

MsgBox % A_AhkPath.length " == " StrLen(A_AhkPath)
MsgBox % A_AhkPath.length.is("integer")

Default_Get_PseudoProperty(nonobj, key)
{
    if (key = "length")
        return StrLen(nonobj)
}

Default_is(nonobj, type)
{
    if nonobj is %type%
        return true
    return false
}

注意也可以使用内置函数, 不过这时不能省略大括号:

"".base.length := Func("StrLen")
MsgBox % A_AhkPath.length() " == " StrLen(A_AhkPath)

调试

如果不希望把一个值视为对象, 每当调用非对象值可以显示警告:

"".base.__Get := "".base.__Set := "".base.__Call := Func("Default__Warn")

empty_var.foo := "bar"
x := (1 + 1).is("integer")

Default__Warn(nonobj, p1="", p2="", p3="", p4="")
{
    ListLines
    MsgBox A non-object value was improperly invoked.`n`nSpecifically: %nonobj%
}

实现

引用计数

当脚本不再引用对象时, AutoHotkey 使用基本引用计数结构来自动释放对象使用的资源. 脚本作者不应该明确调用此结构, 除非在直接处理指向对象的未托管指针时. 想了解更多细节, 参见 ObjAddRef.

; 增加对象的引用数以 "使其保持活跃":
ObjAddRef(address)
...
; 减少对象的引用数, 这样可以释放它:
ObjRelease(address)

然而, 最初通过 Object(obj) 获取地址时不需要使用 ObjAddRef.

通常每个新的对象地址副本都应被视为对象引用, 除非脚本会负责在适当时调用 ObjAddRef 和/或 ObjRelease. 例如, 每当通过类似 x := address 这样的方式复制地址时, 应调用 ObjAddRef 来增加引用数. 同样地, 每当含对象地址特殊副本的脚本结束时, 它应该调用 ObjRelease. 这样确保了当指向对象的最后一个引用失去时对象被释放 - 而不是在这之前.

要在指向对象的最后一个引用被释放时运行代码, 实现 __Delete 元函数.

已知限制:

  • 在释放对象前必须断开循环引用. 例如:
    ; 创建两个对象.
x := {}, y := {}
; 创建循环引用.
x.child := y, y.parent := x

; 糟糕的做法:
x := "", y := ""

; 好的做法:
y.parent := ""  ; 断开循环.
x := "", y := ""
  • 尽管在程序退出时静态和全局变量中的引用会自动释放, 但在非静态局部变量或表达式求值堆栈中的引用则不会. 只有让函数或表达式正常结束这些引用才会释放.

尽管当程序退出时操作系统会回收对象所使用的内存, 但只有在指向对象的所有引用都释放时才会调用 __Delete. 这样释放了不会由操作系统自动回收的其他资源, 例如临时文件, 所以这很重要.

指向对象的指针

在一些罕见的情况中, 可能需要通过 DllCall 传递对象到外部代码或把它存储到二进制数据结构以供以后取回. 通过 x := &obj 可以获取对象的地址; 然而, 如果变量 obj 被清除, 此对象可能被过早释放. 为确保不发生这样的情况, 按上面演示那样使用 ObjAddRef 或按下面演示那样使用 Object():

address := Object(object)

此外, 还可以使用此函数把地址转换回引用:

object := Object(address)

在这两种情况中, 对象的 引用数 都会自动增加, 这样对象不会被过早释放.

注意此函数同样适用于不是由 Object() 创建的对象, 例如 COM 对象包装器 或 文件对象.


Object

对象

所有由 Object() 创建的对象的内置方法都可以作为正常的函数或方法访问:

result := obj.Method(params)

这种调用方法允许每个对象为此方法实现自身的行为. 但是如果一个对象撤销了内置方法, 通常需要一种方式访问原始的功能. 可以使用函数的形式进行访问:

result := ObjMethod(obj, params)

直接调用函数会执行得稍快些, 因为函数名称在装载时解析, 不过语法往往不够直观. 对象实现的任何自定义行为都被忽略, 所以这些函数一般应该仅对象自身使用.

Insert [AHK_L 31+]

插入键值对到对象中, 在合适时自动调整现有的键.

Object.Insert(Index, Value1 [, Value2, ... ValueN ]) Object.Insert(Value) Object.Insert(Key, Value)
Index | 表示 Value1 插入位置的整数键. 后续的值插入到 Index+1, Index+2 等. 如果省略, 默认为 MaxIndex()="" ? 1 : MaxIndex() + 1.
Key | 字符串或目标键. 如果键已经存在, 其值会被改写.
Value | 字符串, 数字或对象.
返回值 | 成功时返回 true, 而脚本内存不足时返回一个空字符串.

备注

注意此方法忽略 __Set 结构和 base 键的特殊行为. 例如, Object.Insert("base","") 会使得 Object.base 返回一个空字符串而不是真正的基础对象, 但这样不会阻止触发对象元函数的其他操作.

Remove [AHK_L 31+]

移除对象中的键值对.

Object.Remove(FirstKey, LastKey)
FirstKey, LastKey | 需移除的整数或字符串键的范围. 如果两个键都是整数, 任何大于 LastKey 的整数键通过减去 (LastKey - FirstKey + 1) 来模仿典型的基于数值索引的数组. 两个键必须为相同的类型 (整数或字符串).
返回值 | 成功时返回被移除的实际键值对数目, 没有找到键则为零, 而失败时为空字符串.
Object.Remove(Key = MaxIndex())
Key | 任何有效键. 如果省略, 默认为最大的现有整数键; 如果不存在, 则什么都不移除. 调整现有的键就像使用 Remove(Key,Key) 一样.
返回值 | 被移除的值, 如果有的话; 否则为空字符串.
Object.Remove(IntKey, "")

[AHK_L 61+]: 移除一个整数键并返回其值, 但不影响其他整数键.

MinIndex / MaxIndex [AHK_L 31+]

MinIndex := Object.MinIndex()
MaxIndex := Object.MaxIndex()

如果存在整数键, MinIndex 返回最小的那个而 MaxIndex 返回最大的那个. 否则返回空字符串.

SetCapacity [AHK_L 31+]

调整对象或其一个区域占用的内存空间.

Object.SetCapacity(MaxItems)
Object.SetCapacity(Key, ByteSize)
MaxItems | 对象在必须自动扩展前它可以包含的键值对的最大数目. 如果小于当前键值对的数目, 则缩小对象以匹配.
Key | 任何有效键.
ByteSize | 为目标区域字符串缓存设置的新大小, 单位为字节, 不包括空终止符. 如果区域不存在, 则创建它. 如果 ByteSize 为零, 则清空缓存但不移除空区域. 如果 ByteSize 小于当前大小, 则额外的数据被截除; 否则保留所有现有的数据.
返回值 | 功时返回新设置的内存空间, 否则为空字符串.

GetCapacity [AHK_L 31+]

MaxItems := Object.GetCapacity()
ByteSize := Object.GetCapacity(Key)

返回对象或其一个区域当前占用的内存空间.

GetAddress [AHK_L 31+]

Ptr := Object.GetAddress(Key)

返回区域字符串的缓存的当前地址, 如果其含有.

NewEnum [AHK_L 49+]

Enum := Object._NewEnum()

返回枚举此对象的键值对的新的 枚举数.

Clone [AHK_L 60+]

Clone := Object.Clone()

返回对象的一个阴影副本.


Enumerator

枚举数对象 [AHK_L 49+]

可以枚举容器中的项目.

Next

检索下一个项目或枚举中的项目.

Enum.Next(OutputVar1 [, OutputVar2, ...])
OutputVar1, OutputVar2 | 接收一个特定于实现的值.
... | 附加参数, 如果支持的话.
返回值 | 成功时返回非零整数, 如果没有剩余项目则返回零, 而参数不正确则返回空字符串.

对象

由 ObjNewEnum() 返回的计数器为每个键值对调用一次, 最多允许两个参数:

OutputVar1 | 接收键值对中的 键.
OutputVar2 | 接收与 OutputVar1 关联的 值.

现有的键值对可以在枚举时修改, 但插入或移除键可能使得一些项目被多次枚举或一次都不枚举.

替代语法

为了方便, Enum[k,v] 可以等同于 Enum.Next(k,v). 因为较短的语法可能难以处理脚本枚举数含混不清的情况, 所以它应该仅在已知 Enum 为内置的枚举数对象时使用.

相关

For-loop, Object.NewEnum()

示例

; Create some sample data.
obj := Object("red", 0xFF0000, "blue", 0x0000FF, "green", 0x00FF00)

; Enumerate!
enum := obj._NewEnum() While enum[k, v] t .= k "=" v "`n" MsgBox % t

; AHK_L 59+
For k, v in obj s .= k "=" v "`n" MsgBox % s


File Object

文件对象 [AHK_L 42+]

为文件流输入/输出提供接口. FileOpen 返回文件类型的对象.

Read

从文件读取字符串并使文件指针向前移动.

String := File.Read([Characters])
Characters | 需要读取的字符的最大数目. 如果省略, 则读取文件的剩余部分并作为单个字符串返回.
返回值 | 一个字符串.

Write

写入字符串到文件并使文件指针向前移动.

File.Write(String)
String | 一个字符串.
返回值 | 写入的字节数 (不是字符数).

ReadLine

从文件中读取一行文本并使文件指针向前移动.

Line := File.ReadLine()
返回值 一行文本. 其中可能包括 `n, `r`n 或 `r , 取决于文件和打开文件时使用的 EOL 标志.

WriteLine

写入字符串后面跟着 `n 或 `r`n 根据打开文件时使用的标志. 使文件指针向前移动.

File.WriteLine([String])
String | 可选的字符串.
返回值 | 写入的字节数 (不是字符数).

ReadNum

从文件中读取一个数字并使文件指针向前移动.

Num := File.ReadNumType()
NumType | 指定下列各项的其中一个直接作为函数名称的一部分: UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float.
返回值 | 数字.

WriteNum

写入数字到文件并使文件指针向前移动.

File.WriteNumType(Num)
NumType | 指定下列各项的其中一个直接作为函数名称的一部分: UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float.
Num | 一个数字.
返回值 | 写入的字节数. 例如, 成功时 WriteUInt 返回 4.

RawRead

从文件读取原始的二进制数据到内存. 如果指定了变量, 必要时会自动扩展.

File.RawRead(VarOrAddress, Bytes)
VarOrAddress | 将要从中复制数据的变量或内存地址. 用法类似于 NumGet.
Bytes | 需读取的最大字节数.
返回值 | 读取的字节数.

RawWrite

写入原始的二进制数据到文件.

File.RawWrite(VarOrAddress, Bytes)
VarOrAddress | 包含数据的变量或内存中的数据地址. 用法类似于 NumPut.
Bytes | 需写入的字节数.
返回值 | 写入的字节数.

Seek

移动文件指针.

File.Seek(Distance [, Origin = 0])
File.Position := Distance
File.Pos := Distance
Distance | 需移动的距离, 单位为字节. 较小的值更接近文件的开始处.
Origin 文件指针开始移动的起点. 必须为下列值的其中一个:
  • 0 (SEEK_SET): 文件的开始处. Distance 必须为零或更大.
  • 1 (SEEK_CUR): 文件指针的当前位置.
  • 2 (SEEK_END): 文件的末尾. Distance 通常应该为负数.
如果省略, 当 Distance 为负数时 Origin 为 SEEK_END 而其他情况为 SEEK_SET.
返回值 | 成功时为非零值, 否则为零.

Tell

Pos := File.Tell()
Pos := File.Position
Pos := File.Pos
返回值 文件指针的当前位置, 文件的开始处为 0.

Length

获取或设置文件的大小.

FileSize := File.Length
File.Length := NewSize
NewSize | 文件的新大小, 单位为字节.
返回值 | 文件的大小, 单位为字节.

AtEOF

IsAtEOF := File.AtEOF
返回值 如果文件指针到达文件的末尾时为非零值, 否则为零.

Close

关闭文件, 把缓冲区的数据写入磁盘并释放共享锁定. 尽管当对象释放时文件自动关闭, 但建议尽快关闭文件.

File.Close()

没有参数或返回值.

编码

获取或设置此文件对象使用的编码. 为了得到可靠结果调用者在设置此属性后可能需要 Seek.

Encoding := File.Encoding
File.Encoding := Encoding
返回值 一个 FileEncoding 接受的格式的字符串.

__Handle

File.__Handle
返回值 与 DllCall 一起使用的系统文件句柄. 参见 CreateFile.


ComObjActive()

ComObjActive() [AHK_L 53+]

检索已注册到 OLE 的正在运行的对象.

ComObject := ComObjActive(CLSID)

创建表示作为参数或返回值传递的类型化值的对象.

ParamObj := ComObjParameter(VarType, Value [, Flags])

创建在调用 COM 对象的方法时可以用来代替可选参数默认值的对象.

ParamObj := ComObjMissing()

高级

包装或解开可用对象中的原始 IDispatch 指针.

ComObject := ComObjEnwrap(DispPtr)
DispPtr := ComObjUnwrap(ComObject)

参数

CLSID | 要检索的 COM 对象的 CLSID 或可读 Prog ID.
ComObject | 可以使用 对象语法 的 COM 对象.
VarType | 表示值类型的整数. 请参阅 ComObjType() 了解类型列表.
Value | 要包装的值. 当前仅支持整数值和指针值.
Flags | 影响此函数和包装器对象行为的标志; 参见后面.
DispPtr | 原始的 IDispatch 指针.

Flags

0 | 默认行为. 为 IUnknown 和 IDispatch 指针自动调用 AddRef, 所以调用者应该在适当时使用 ObjRelease 释放这些指针副本.
1 | 取得 IUnknown, IDispatch 或 SAFEARRAY 指针的所有权. 不调用 AddRef. 如果包装器对象包含 SAFEARRAY (VT_BYREF 除外), 那么当包装器对象被释放时会自动调用 SafeArrayDestroy.

一般说明

ComObjActive 是 多态的; 即任何名称以 "ComObj" 开始且不匹配其他某个 COM 函数的函数调用实际在调用 ComObjActive. 例如, ComObj(9, DispPtr) 和 ComObjActive(DispPtr) 都等同于 ComObjEnwrap(DispPtr). 然而, 在未来的版本中此特性可能发生变化 (或实现了新的函数), 所以最好仅显示此页面中演示的形式, 此外 "ComObject" 可以用来代替 ComObjEnwrap 或 ComObjParameter.

当使用此函数包装或检索 IDispatch 或 IUnknown 接口指针时, 默认的行为会增加 COM 对象的引用数. 一般而言, 脚本中指针的原始副本被视为独立的引用, 当不再需要时必须在脚本中对其进行 手动释放. 释放包装器对象时, 也会同时释放其到 COM 对象的引用.

已知限制: 每次包装 COM 对象时, 都会创建新的包装器对象. 比较和赋值运算中, 例如 obj1 == obj2 和 array[obj1] := value, 会把两个包装器对象视为唯一的, 即使它们包含相同的 COM 对象.

相关

ComObjCreate, ComObjGet, ComObjConnect, ComObjError, ComObjFlags, ObjAddRef/ObjRelease, GetActiveObject (MSDN)

示例

ComObjUnwrap: 请参阅 ComObjConnect.

; 示例: 传递 VARIANT ByRef 到 COM 函数.

code =
(
Sub Example(Var)
    MsgBox Var
    Var = "out value!"
End Sub
)
sc := ComObjCreate("ScriptControl"), sc.Language := "VBScript", sc.AddCode(code)

var := ComVar()
var[] := "in value"
sc.Run("Example", var.ref)
MsgBox % var[]

; ComVar: 创建用来传递 ByRef 值的对象.
;   ComVar[] 检索值.
;   ComVar[] := Val 设置值.
;   ComVar.ref 检索 ByRef 对象用于传递到 COM 函数.
ComVar(Type=0xC)
{
    static base := { __Get: "ComVarGet", __Set: "ComVarSet", __Delete: "ComVarDel" }
    ; 创建含 1 个 VARIANT 类型变量的数组.  此方法可以让内部代码处理
    ; 在 VARIANT 和 AutoHotkey 内部类型之间的所有转换.
    arr := ComObjArray(Type, 1)
    ; 锁定数组并检索到 VARIANT 的指针.
    DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(arr), "ptr*", arr_data)
    ; 保存可用于传递 VARIANT ByRef 的数组和对象.
    return { ref: ComObjParameter(0x4000|Type, arr_data), _: arr, base: base }
}
ComVarGet(cv, p*) { ; 当脚本访问未知字段时调用.
    if p.MaxIndex() = "" ; 没有名称/参数, 即 cv[]
        return cv._[0]
}
ComVarSet(cv, v, p*) { ; 当脚本设置未知字段时调用.
    if p.MaxIndex() = "" ; 没有名称/参数, 即 cv[]:=v
        return cv._[0] := v
}
ComVarDel(cv) { ; 当对象被释放时调用.
    ; 必须进行这样的处理以释放内部数组.
    DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(cv._))
}


ComObjArray()

ComObjArray() [v1.0.91+]

使用 COM 创建 SafeArray.

ArrayObj := ComObjArray(VarType, Count1 [, Count2, ... Count8])

参数

VarType | 数组的基类型 (数组的每个元素的 VARTYPE).VARTYPE 被限制为变量类型的子集.不能设置为 VT_ARRAY 和 VT_BYREF.对于数组的基类型 VT_EMPTY 和 VT_NULL 都是无效的.所有其他类型都是合法的. 参见 ComObjType 了解允许值的列表.
CountN | 每个维数的大小.最多可以含有 8 维的数组.
ArrayObj | 包含 SafeArray 的包装器对象.

方法

数组包装器对象支持下列方法:

Array.MaxIndex(n):返回第 n 维的上界.如果省略, 默认为 1.

Array.MinIndex(n):返回第 n 维的下界.如果省略, 默认为 1.

Array.Clone() [v1.0.96.00+]:返回数组的副本.

Array._NewEnum() [v1.0.96.00+]:通常不是由脚本调用; 允许 for 循环 和 SafeArray 一起使用.

一般说明

COM 方法和 ComObjActive 也可以返回数组包装器对象.脚本中可以使用如下方法判断一个值是否为数组:

if ComObjType(obj) & 0x2000
    MsgBox % "Array subtype: " . ComObjType(obj) & 0xfff
else
    MsgBox Not an array.

可以支持多达 8 维的数组.

[v1.0.96.00+]: 由于 SafeArray 没有设计支持多种引用, 当一个 SafeArray 被赋值为另一个 SafeArray 的元素时, 会创建一个独立的副本.不过, 只有当包装器对象含有 F_OWNVALUE 标志时才会发生这样的情况, 这个标志表示它负责销毁此数组.可以使用 ComObjFlags 移除此标志.

相关

ComObjType, ComObjValue, ComObjActive, ComObjFlags, 数组操作函数 (MSDN)

示例

; 示例 #1:简单用法.

arr := ComObjArray(VT_VARIANT:=12, 3)
arr[0] := "Auto"
arr[1] := "Hot"
arr[2] := "key"
Loop % arr.MaxIndex() + 1
   t .= arr[A_Index-1]
MsgBox % t

; 示例 #2:多维数组.

arr := ComObjArray(VT_VARIANT:=12, 3, 4)

; 获取数组的维数个数:
dim := DllCall("oleaut32\SafeArrayGetDim", "ptr", ComObjValue(arr))

; 获取每个维数的边界:
Loop %dim%
    dims .= arr.MinIndex(A_Index) " .. " arr.MaxIndex(A_Index) "`n"
MsgBox %dims%

; 简单用法:
Loop 3 {
    x := A_Index-1
    Loop 4 {
        y := A_Index-1
        arr[x, y] := x * y
    }
}
MsgBox % arr[2, 3]


ComObjConnect()

ComObjConnect() [AHK_L 53+]

连接对象的事件源到带有指定前缀的函数.

ComObjConnect(ComObject [, Prefix])

参数

ComObject | 产生事件的对象.
Prefix | 用于判断当事件发生时应调用哪个函数的事件名称前缀的字符串. 如果完全省略, 则对象为 "未连接的"; 即脚本将不再接收其事件通告.

用法

为了让 ComObjConnect 有意义, 首先您必须在脚本中编写处理任何感兴趣事件的函数.这类函数, 或称为 "事件处理程序," 具有下列结构:

PrefixEventName([Params..., ComObject])
{
    ... event-handling code ...
    return returnValue
}

Prefix 为您选择的前缀, 而 EventName 为函数需要处理的每种事件的名称.

Params 对应于事件包含的任何参数.如果事件不含有参数, Params 应该完全省略.ComObject 是可选的, 并且可以仅在定义的 Params 数目正确时使用; 它包含了传递给 ComObjConnect 的原始包装器对象的引用."ComObject" 应该替换为与您脚本上下文相关的更有意义的名称.

注意事件处理程序可以产生返回值.要返回特定 COM 类型的值, 请使用 ComObjParameter, 它也可以写成 ComObjRetVal(type, value) 或简化为 ComObj(type, value).

调用 ComObjConnect(yourObject, "Prefix") 来启用事件处理.

调用 ComObjConnect(yourObject) 来断开到对象的连接 (停止处理事件).

如果参数的数目未知, 可以使用 可变参数函数.

相关

ComObjCreate, ComObjGet, ComObjActive, ComObjConnect, ComObjError, WScript.ConnectObject (MSDN)

示例

ie := ComObjCreate("InternetExplorer.Application")

; 连接事件到带有 "IE_" 前缀的相应脚本函数.
ComObjConnect(ie, "IE_")

ie.Visible := true  ; 这个语句在 IE7 中无法正常执行.
ie.Navigate("http://www.autohotkey.net/~Lexikos/AutoHotkey_L/")
#Persistent

IE_DocumentComplete(ieEventParam, url, ieFinalParam) {
    global ie
    if (ie != ieEventParam)
        s .= "First parameter is a new wrapper object.`n"
    if (ie == ieFinalParam)
        s .= "Final parameter is the original wrapper object.`n"
    if ((disp1:=ComObjUnwrap(ieEventParam)) == (disp2:=ComObjUnwrap(ieFinalParam)))
        s .= "Both wrapper objects refer to the same IDispatch instance.`n"
    ObjRelease(disp1), ObjRelease(disp2)
    MsgBox % s . "Finished loading " ie.Document.title " @ " url
    ie.Quit()
    ExitApp
}


ComObjCreate()

ComObjCreate() [AHK_L 53+]

创建 COM 对象.

ComObject := ComObjCreate(CLSID [, IID])

参数

CLSID | 要创建的 COM 对象的 CLSID 或可读 Prog ID.
IID | [v1.0.96.00+]: 对象支持的接口标识符.

返回值

如果产生了错误, 则返回空字符串.

如果指定了 IID, 则返回接口指针.使用指针结束时脚本通常必须调用 ObjRelease.

否则返回可以在脚本中使用的包装器对象.参见 调用对象.

相关

ComObjGet, ComObjActive, ComObjConnect, ComObjArray, ComObjError, CreateObject (MSDN)

示例

参见后面的论坛主题, 可以看到不断增长的示例列表:http://www.autohotkey.com/forum/topic61509.html.

ie := ComObjCreate("InternetExplorer.Application")
ie.Visible := true  ; 这个语句在 IE7 中无法正常执行.
ie.Navigate("http://www.autohotkey.net/~Lexikos/AutoHotkey_L/")


ComObjGet()

ComObjGet() [AHK_L 53+]

返回到由 COM 组件提供的对象的引用.

ComObject := ComObjGet(Name)

参数

Name 需要获取的对象的显示名称.参见 MkParseDisplayName (MSDN) 了解更多信息.

相关

ComObjCreate, ComObjActive, ComObjConnect, ComObjError, CoGetObject (MSDN)

示例

; 示例:按下 Shift+Escape 来显示用于运行
;   活动窗口进程的命令行.需要 XP 或更高版本.
+Esc::
    WinGet pid, PID, A
    ; 获取 WMI 服务对象.
    wmi := ComObjGet("winmgmts:")
    ; 执行查询以获取匹配进程.
    queryEnum := wmi.ExecQuery(""
        . "Select * from Win32_Process where ProcessId=" . pid)
        ._NewEnum()
    ; 获取首个匹配进程.
    if queryEnum[process]
        MsgBox 0, Command line, % process.CommandLine
    else
        MsgBox Process not found!
    ; 释放所有全局对象 (使用局部变量时这个操作不是必须的).
    wmi := queryEnum := process := ""
return
; Win32_Process:http://msdn.microsoft.com/en-us/library/aa394372.aspx


ComObjError()

ComObjError() [AHK_L 53+]

启用或禁用 COM 错误通告.

Enabled := ComObjError(Enable)

参数

Enable | 布尔值 (真或假).此参数是可选的.
Enabled | [v1.0.91+]: 保存调用函数前的实际设置.

一般说明

使用 COM 对象后, A_LastError 包含了由 COM 对象的 IDispatch::Invoke 函数返回的 HRESULT 码.通过调用 ComObjError(false) 来禁用错误通告并检查 A_LastError 的值, 脚本可以实现自身的错误处理.

相关

ComObjCreate, ComObjGet, ComObjActive, ComObjConnect


ComObjFlags()

ComObjFlags() [v1.0.96.00+]

获取或改变控制 COM 包装器对象行为的标志.

Flags := ComObjFlags(ComObject [, NewFlags, Mask])

参数

ComObject | COM 包装器对象.
NewFlags | 由 Mark 标识的新标志值, 或要添加或移除的标志.
Mask | 需要改变的标志位掩码.
Flags | ComObject 的所有标志 (如果指定了 NewFlags, 则为应用后的新标志).

标志

F_OWNVALUE
1 		当前仅对 SafeArray 有效.如果设置了此标志, 则当包装器对象释放时销毁 SafeArray.由于 SafeArray 没有引用计数结构, 如果含有此标志的 SafeArray 被赋值为另一个 SafeArray 的元素时, 会创建一个独立的副本.

一般说明

如果省略 Mark, NewFlags 指定需要添加 (为正数时) 或移除 (为负数时) 的标志.例如, ComObjFlags(obj, -1) 移除 F_OWNVALUE 标志.不要在 Mark 中指定除 0 或 1 外的其他值, 所有其他位保留供将来使用.

相关

ComObjActive, ComObjArray

示例

; 示例:检查 F_OWNVALUE 标志是否存在.

arr := ComObjArray(0xC, 1)
if ComObjFlags(arr) & 1
    MsgBox arr will be automatically destroyed.
else
    MsgBox arr will not be automatically destroyed.

; 示例:改变内嵌在其他数组中的数组的行为.

arr1 := ComObjArray(0xC, 3)
arr2 := ComObjArray(0xC, 1)
arr2[0] := "original value"
arr1[0] := arr2         ; 赋值隐式副本.
ComObjFlags(arr2, -1)   ; 移除 F_OWNVALUE.
arr1[1] := arr2         ; 赋值为原始数组.
arr1[2] := arr2.Clone() ; 赋值显式副本.
arr2[0] := "new value"
for arr in arr1
    MsgBox % arr[0]

arr1 := ""
; 由于 arr2 == arr1[1] 所以后面这句无效, 它已经被销毁了:
;  arr2[0] := "foo"


ComObjQuery()

ComObjQuery() [v1.0.96.00+]

查询接口或服务的 COM 对象.

InterfacePointer := ComObjQuery(ComObject, [SID,] IID)

参数

ComObject | COM 包装器对象或原始接口指针.
IID | 格式为 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" 的接口标识符 (GUID).
SID | 与 IID 格式相同的服务标识符.此参数忽略时, 必须同时忽略后面的逗号.

一般说明

此函数的第一种形式相当于 IUnknown::QueryInterface.第二种形式内部查询 IServiceProvider 接口, 然后调用 IServiceProvider::QueryService.在两种形式中, 返回值为零或到被请求接口的指针.通常当脚本结束时必须 释放 这种指针.

相关

ObjRelease, ComObjCreate, ComObjGet, ComObjActive, ComObjError

示例

; 示例:确定一个对象的类名.

obj := ComObjCreate("Scripting.Dictionary")

MsgBox % "Interface name: " ComObjType(obj, "name")

IID_IProvideClassInfo := "{B196B283-BAB4-101A-B69C-00AA00341D07}"

; 请求到对象 IProvideClassInfo 接口的指针.
if !(pci := ComObjQuery(obj, IID_IProvideClassInfo))
{
    MsgBox IProvideClassInfo interface not supported.
    return
}

; 调用 GetClassInfo 以获取到 ITypeInfo 接口的指针.
DllCall(vtable(pci, 3), "ptr", pci, "ptr*", ti)

; 调用 GetDocumentation 以获取对象的完整类型名称.
DllCall(vtable(ti, 12), "ptr", ti, "int", -1, "ptr*", name, "ptr", 0, "ptr", 0, "ptr", 0)

; 转换 BSTR 指针为可用的字符串.
name := StrGet(name, "UTF-16")

; 释放原始接口指针.
ObjRelease(ti)
ObjRelease(pci)

; 显示类型名称!
MsgBox % "Class name: " name

vtable(ptr, n) {
    ; NumGet(ptr+0) 返回对象的虚拟函数
    ; 表 (vtable for short) 的地址.表达式的其余部分从 vtable
    ; 获取第 n 个函数的地址.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}

; 示例:自动化现有的 Internet Explorer 窗口.

sURL := "http://www.autohotkey.com/forum/"
if webBrowser := GetWebBrowser()
   webBrowser.Navigate(sURL)
return

GetWebBrowser()
{
    ; 获取到顶级 IE 窗口文档对象的原始指针.
    static msg := DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT")
    SendMessage msg, 0, 0, Internet Explorer_Server1, ahk_class IEFrame
    if ErrorLevel = FAIL
        return  ; IE not found.
    lResult := ErrorLevel
    DllCall("oleacc\ObjectFromLresult", "ptr", lResult
        , "ptr", GUID(IID_IHTMLDocument2,"{332C4425-26CB-11D0-B483-00C04FD90119}")
        , "ptr", 0, "ptr*", pdoc)

    ; 查询 WebBrowserApp 服务.在这种特殊情况中,
    ; SID 和 IID 相同, 但不总是如此.
    static IID_IWebBrowserApp := "{0002DF05-0000-0000-C000-000000000046}"
    static SID_SWebBrowserApp := IID_IWebBrowserApp
    pweb := ComObjQuery(pdoc, SID_SWebBrowserApp, IID_IWebBrowserApp)

    ; 释放文档对象指针.
    ObjRelease(pdoc)

    ; 返回包装过的可用 WebBrowser 对象:
    static VT_DISPATCH := 9, F_OWNVALUE := 1
    return ComObject(VT_DISPATCH, pweb, F_OWNVALUE)
}

GUID(ByRef GUID, sGUID) ; 转换一个字符串为二进制的 GUID 并返回其地址.
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
}


ComObjType()

ComObjType() [v1.0.91+]

从 COM 对象获取类型信息.

VarType := ComObjType(ComObject)
Name    := ComObjType(ComObject, "Name")
IID     := ComObjType(ComObject, "IID")

参数

ComObject | 包含 COM 对象或 typed value 的包装器对象.
VarType | 表示值类型的整数.参见下面.
Name | 接口类型名.
IID | 表示接口类型的全局唯一标识符 (GUID).

返回值

如果省略第二个参数, 则返回包装器对象包含的值的变量类型.

如果第二个参数为 "Name" 或 "IID" 并且包装器对象包含 COM 对象 (变量类型 VT_DISPATCH), 则返回 COM 对象的类型名或其主接口的标识符.

如果参数都无效或发生了错误, 则返回空字符串.

变量类型的常量

VT_EMPTY     =      0  ; 没有值
VT_NULL      =      1  ; SQL 风格的空值
VT_I2        =      2  ; 16 位有符号整数
VT_I4        =      3  ; 32 位有符号整数
VT_R4        =      4  ; 32 位浮点数
VT_R8        =      5  ; 64 位浮点数
VT_CY        =      6  ; 通用
VT_DATE      =      7  ; 日期
VT_BSTR      =      8  ; COM 字符串 (带有长度前缀的 Unicode)
VT_DISPATCH  =      9  ; COM 对象
VT_ERROR     =    0xA  ; 错误码 (32 位整数)
VT_BOOL      =    0xB  ; 布尔值真 (-1) 或假 (0)
VT_VARIANT   =    0xC  ; VARIANT (必须与 VT_ARRAY 或 VT_BYREF 组合使用)
VT_UNKNOWN   =    0xD  ; IUnknown 接口指针
VT_DECIMAL   =    0xE  ; (不支持)
VT_I1        =   0x10  ; 8 位有符号整数
VT_UI1       =   0x11  ; 8 位无符号整数
VT_UI2       =   0x12  ; 16 位无符号整数
VT_UI4       =   0x13  ; 32 位无符号整数
VT_I8        =   0x14  ; 64 位有符号整数
VT_UI8       =   0x15  ; 64 位无符号整数
VT_INT       =   0x16  ; 有符号机器整数
VT_UINT      =   0x17  ; 无符号机器整数
VT_RECORD    =   0x24  ; 用户定义类型
VT_ARRAY     = 0x2000  ; SAFEARRAY
VT_BYREF     = 0x4000  ; 到另一种值类型的指针
/*
 VT_ARRAY 和 VT_BYREF 与另一个值组合在一起 (使用按位 OR)
 以指定准确的类型.例如, 0x2003 标识 32 位有符号整数的 SAFEARRAY
 而 0x400C 标识到 VARIANT 的指针.*/

一般说明

在通常情况下, COM 对象的方法或属性的返回值会被转换成 AutoHotkey 支持的适合的数据类型.没有明确处理的类型通过 VariantChangeType 强制转换成字符串; 如果转换失败或变量类型包含 VT_ARRAY 或 VT_BYREF 标志, 则返回同时包含值和其类型的对象代替.

对于任意变量 x, 如果 ComObjType(x) 返回整数, 则 x 包含 COM 对象包装器.

相关

ComObjValue, ComObjCreate, ComObjGet, ComObjActive

示例

d := ComObjCreate("Scripting.Dictionary")
VarType := ComObjType(d)          ; 对于可脚本化对象总为 9.
Name    := ComObjType(d, "Name")  ; 仅对于可脚本化对象有效.
IID     := ComObjType(d, "IID")   ; 同上.
MsgBox Variant type:`t%VarType%`nType name:`t%Name%`nInterface ID:`t%IID%


ComObjValue()

ComObjValue() [v1.0.91+]

获取存储在 COM 包装器对象中的值或指针.

Value := ComObjValue(ComObject)

参数

Value | 64 位有符号整数.
ComObject | 包含 COM 对象或 typed value 的包装器对象.

一般说明

此函数并非计划用于一般用途.

调用 ComObjValue 等价于 variant.llVal, 这里 ComObject 被视为 VARIANT 结构.使用此函数的脚本必须注意到包装器对象包含的 值类型 以及它应该如何处理.例如, 如果返回接口指针, 则不应该调用 Release, 不过根据脚本对指针进行的操作可能需要 AddRef.

相关

ComObjType, ComObjCreate, ComObjGet, ComObjActive


ClipWait

等待, 一直到 剪贴板 包含数据.

ClipWait [, SecondsToWait, 1]

参数

SecondsToWait | 如果省略, 此命令将无限期等待. 否则, 它将等待不超过这个秒数的时间 (可以包含小数点或为 表达式). 指定 0 等同于指定 0.5.
1 | 如果省略此参数, 此命令会更有选择性, 明确地等待剪贴板中出现文本或文件 ("文本" 包含任何当您粘贴到记事本时会产生文本的内容). 如果此参数为 1 (可以为 表达式), 此命令会等待剪贴板中出现任何类型的数据.

ErrorLevel

如果到达等待期限, ErrorLevel 将被置为 1. 否则 (即剪贴板包含数据), ErrorLevel 被置为 0.

备注

使用此命令比您在一个循环中检查剪贴板是否为空要好. 这是由于此命令从不打开剪贴板, 因此执行地更好并且避免了对可能使用剪贴板的其他程序的干扰.

此命令把任何可转换成文本的内容 (例如 HTML) 视为文本. 它也把文件, 例如从资源管理器窗口中通过 Control-C 复制的那些, 视为文本. 每当在脚本中引用剪贴板变量 (%clipboard%) 时, 这些文件被自动转换成它们的文件名 (包含完整路径). 详情见 剪贴板.

当最后一个参数为 1 时, 剪贴板中出现任何数据都将符合此命令. 这种特性可以和 ClipboardAll 结合使用来保存像图片这样的非文本数据.

当此命令处于等待状态时, 可以通过 热键, 自定义菜单项 或 计时器 运行新的 线程.

相关

Clipboard, WinWait, KeyWait

示例

clipboard = ; 清空剪贴板
Send, ^c
ClipWait, 2
if ErrorLevel
{
    MsgBox, The attempt to copy text onto the clipboard failed.
    return
}
MsgBox, clipboard = %clipboard%
return


EnvGet

EnvGet [v1.0.43.08+]

获取环境变量的内容.

EnvGet, OutputVar, EnvVarName

参数

OutputVar | 用来存储字符串的变量名.
EnvVarName | 要获取的 环境变量 的名称. 例如: EnvGet, OutputVar, Path

备注

如果指定的环境变量为空或不存在, 那么 OutputVar 被置空.

操作系统限制每个环境变量的文本最多为 32 KB.

相关

EnvSet, #NoEnv, 环境变量, EnvUpdate, SetEnv, Run, RunWait

示例

EnvGet, OutputVar, LogonServer


EnvSet

向系统环境中的 变量 写入值.

EnvSet, EnvVar, Value

参数

EnvVar | 要使用的 环境变量 的名称, 例如 "COMSPEC" 或 "PATH".
Value | 要设置到目标 环境变量 的值.

ErrorLevel

如果遇到问题则 ErrorLevel 被置为 1, 否则为 0.

备注

操作系统限制每个环境变量的文本最多为 32 KB.

此命令创建或改变的环境变量只有由此脚本通过 Run 或 RunWait 运行的程序才可以读取. 参见 环境变量 了解更多细节.

此命令与 SetEnv 分别存在, 因为 普通脚本变量 没有存储在系统环境中. 这是由于性能会变差且操作系统限制环境变量大小在 32 KB 之内.

相关

EnvGet, #NoEnv, 环境变量, EnvUpdate, SetEnv, Run, RunWait

示例

EnvSet, AutGUI, Some text to put in the variable.


EnvUpdate

通知操作系统和所有正在运行的程序 环境变量 已经改变.

EnvUpdate

ErrorLevel

如果遇到问题则 ErrorLevel 被置为 1, 否则为 0.

备注

刷新操作系统环境. 效果类似于注销系统后再登录.

例如, 在 Windows NT/2000/XP 或更高版本, 修改了后面的注册表键后, 可以用 EnvUpdate 广播这个变化: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session
Manager\Environment

相关

EnvSet, RegWrite

示例

EnvUpdate


Drive

驱动器

弹出/收回 CD 或 DVD 驱动器的托盘，或者设定驱动器的卷标。

Drive, Sub-command [, Drive , Value]

如下所述，sub-command、drive，和参数value之间相互依赖。

Label, Drive [, NewLabel]: 将 Drive (驱动器)的卷标改为 NewLabel (如果省略 NewLabel，驱动器卷标为空)。Drive 是字母后跟一个冒号和可选的反斜杠(可能是UNCs和驱动器映射)。例如：Drive, Label, C:, Seagate200

按照以下例子，取得当前驱动器的卷标：DriveGet, OutputVar, Label, C:

Lock, Drive: 锁定驱动器，防止其正在工作的时候被弹出。例如："Drive, Lock, D:"。大多数的驱动器不能 "locked open"(锁定之后被打开)。然而，在驱动器打开时锁定它，将会使驱动器在关闭后进入锁定状态。对于不支持锁定的驱动器(像大多数的仅读驱动器)，此命令将不起作用。该命令同样不支持 Windows 95/98/Me 下非 IDE 驱动器。如果脚本在结束前锁定了某个驱动器，则该驱动器将一直保持锁定状态，直到其它的脚本或程序将其解锁，或系统重启。如果指定的驱动器不存在或者不支持锁定特性，ErrorLevel (警告级别)将被设为1，否则为0。

Unlock, Drive: 功能同上述命令相反。在 Window NT/2000/XP 及以后版本，如果驱动器锁定了多次，则需要多次执行 Unlock 命令。例如，如果 "Drive, Lock, D:" 执行了三次，需要执行三次 "Drive, Unlock, D:" 来解锁。事实上，因为不能确定驱动器是否处于锁定状态，因此，经常需要一个变量来记录锁定的状态。

Eject [, Drive, 1]: 弹出或收回 CD 或 DVD 驱动器的托盘(弹出其它类型的影音设备或驱动器，请参见本页结尾使用的 DllCall )。

如果省略 Drive ，则使用默认的 CD / DVD 驱动器。省略最后一个参数将则弹出托盘，将其设为 1 则该命令收回或关闭托盘。例如：Drive, Eject, D:, 1

Drive Eject 命令在托盘弹出或收回完成后返回。如果托盘成功到达指定状态(打开或关闭)，ErrorLevel 将被设为0(就是"没有错误")。

对于网络驱动器或者非 CD / DVD 驱动器，Drive Eject 命令很可能无法正常工作。因为这些或其它原因导致的错误，ErrorLevel 将被设为1。

通过检测执行命令所花费的时间，可以有效地确定托盘以前的状态。例如：下面的热键将触发托盘到相反状态(打开或关闭)：

#c::
Drive, Eject
; 如果很短时间内完成了这条命令，托盘很可能已经弹出了。
; 那样的话，收回托盘。
if A_TimeSinceThisHotkey < 1000  ; 调整到合适的时间。
    Drive, Eject,, 1
return

如果想测定 CD 或 DVD 的影音播放状态(比如正在播放，暂停，打开等)，请参见 DriveGet 命令。

ErrorLevel

出现错误时，ErrorLevel 将被设为1，否则为0。

注意

下面的例子对弹出方法进行了改动，使之不仅能用于 CD 或 DVD 驱动器，还能用于media/devices(影音设备)：

; 根据需要更新第二行的驱动器标号(不用考虑其它行)。
Driveletter = I:  ; 设定为你想弹出的驱动器的标号。

hVolume := DllCall("CreateFile"
    , Str, "\\.\" . Driveletter
    , UInt, 0x80000000 | 0x40000000  ; GENERIC_READ | GENERIC_WRITE
    , UInt, 0x1 | 0x2  ; FILE_SHARE_READ | FILE_SHARE_WRITE
    , UInt, 0
    , UInt, 0x3  ; OPEN_EXISTING
    , UInt, 0, UInt, 0)
if hVolume <> -1
{
    DllCall("DeviceIoControl"
        , UInt, hVolume
        , UInt, 0x2D4808   ; IOCTL_STORAGE_EJECT_MEDIA
        , UInt, 0, UInt, 0, UInt, 0, UInt, 0
        , UIntP, dwBytesReturned  ; Unused.
        , UInt, 0)
    DllCall("CloseHandle", UInt, hVolume)
}

相关命令

DriveGet, DriveSpaceFree

示例

Drive, Label, D:, BackupDrive
Drive, Eject,, 1 ; 收回(关闭)默认 CD 或 DVD 驱动器的托盘。


DriveGet

获得关于计算机驱动器各种类型的信息。

DriveGet, OutputVar, Cmd [, Value]

参数

OutputVar | 要存储 Cmd 结果的变量名称。
Cmd, Value | 见下表。

Cmd, Value

参数 Cmd 和 Value 相互依赖，其用法描述如下。 如果遇到问题 OutputVar 会被置空并且 ErrorLevel 被设为 1 。

List [, Type]: 设置 OutputVar 为一串字母，其中每个字母代表系统中的一个驱动器号。例如: ACDEZ 。如果省略参数 Type ，将获取所有类型的驱动器。否则，参数 Type 应该设定为 CDROM, REMOVABLE, FIXED, NETWORK, RAMDISK, UNKNOWN 其中之一以获取该特定类型的驱动器。

Capacity (或 Cap), Path: 以兆字节为单位取得参数 Path (例如：C:\) 的总容量。用 DriveSpaceFree 命令来确定可用空间。

Filesystem (或 FS), Drive: 获取参数 Drive 的文件系统类型，这里参数 Drive 由驱动器字母后接一个冒号和一个可选的反斜线组成，或者是一个 UNC(通用命名规则) 名称如 \\server1\share1 。OutputVar 将被设为以下单词中的一个：FAT, FAT32, NTFS, CDFS (一般指 CD), UDF (一般指 DVD)。如果驱动器不包含格式化的存储介质，OutputVar 会被置空并且 ErrorLevel 被设为 1 。

Label, Drive: 获取参数 Drive 的卷标，这里参数 Drive 由驱动器字母后接一个冒号和一个可选的反斜线组成，或者是一个 UNC 名称如 \\server1\share1 。要更改卷标，参照此例：Drive, Label, C:, MyLabel

Serial, Drive: 获取参数 Drive 的卷序列号以十进制整数表示，这里参数 Drive 由驱动器字母后接一个冒号和一个可选的反斜线组成，或者是一个 UNC 名称如 \\server1\share1 。如何转换成十六进制请看 SetFormat 命令。

Type, Path: 获取参数 Path 的驱动器类型，它是后面单词中的一个：Unknown, Removable, Fixed, Network, CDROM, RAMDisk 。

Status, Path: 获取参数 Path 的状态，它是后面单词中的一个：Unknown (可能表示未格式化/RAW), Ready, NotReady (通常表示不含存储介质的可移动驱动器), Invalid (参数 Path 不存在或者是一个当前无法访问的网络驱动器等)

StatusCD [, Drive]: 获取 CD 或 DVD 驱动器中存储介质的状态，这里参数 Drive 由驱动器字母后接一个冒号组成 (如果省略参数 Drive, 将使用默认的 CD/DVD 驱动器)。如果状态无法确定 OutputVar 将被置空。否则，它将设定为下列字符串之一：

not ready | 驱动器未准备好被访问，也许是因为正忙于写操作。已知的限制：当驱动器里是一个 DVD 而不是 CD 时，也会出现"not ready" 的情况。
open | 驱动器里没有光盘，或者托盘已弹出。
playing | 驱动器正在播放光盘。
paused | 先前播放的声频或视频目前已暂停。
seeking | 驱动器正在查找。
stopped | 驱动器里有 CD 但是当前没有在访问。

此命令很可能对网络驱动器或者非 CD/DVD 驱动器不起作用；如果由此或者其他原因而失败，OutputVar 将被置空并且 ErrorLevel 设为 1 。

如果托盘刚被关闭, 命令完成之前会有一定延迟。

要弹出或者缩回托盘，请看 Drive 命令。

ErrorLevel

出错时 ErrorLevel 被设为 1 ，否则为 0 。

注意

其中某些命令能接受网络共享名称作为参数 Path, 例如 \\MyServer\MyShare\

相关命令

Drive, DriveSpaceFree

示例

; 这是一个可用的示例脚本。
FileSelectFolder, folder, , 3, 选一个驱动器来分析：
if folder =
return
DriveGet, list, list
DriveGet, cap, capacity, %folder%
DrivespaceFree, free, %folder%
DriveGet, fs, fs, %folder%
DriveGet, label, label, %folder%
DriveGet, serial, serial, %folder%
DriveGet, type, type, %folder%
DriveGet, status, status, %folder%
MsgBox 所有的驱动器：%list%`n选中的驱动器：%folder%`n驱动器类型：%type%`n状态：%status%`n容量：%cap% M`n可用空间：%free% M`n文件系统：%fs%`n卷标：%label%`n序列号：%serial%


DriveSpaceFree

获得一个驱动器的剩余磁盘空间信息，以 Megabytes(兆字节) 表示。

DriveSpaceFree, OutputVar, Path

参数

OutputVar | 用来存储结果的变量，四舍五入到最接近整数。
path | 需要获得信息的驱动器路径。由于 NTFS 支持 mounted volumes(挂载卷) 和 directory junctions(目录联结)，有时候相同“驱动器”下 的不同文件夹可能有不同的剩余空间总量。

注意

OutputVar 被设置为以兆字节显示的剩余磁盘空间总量(四舍五入到最接近兆字节)。

相关命令

Drive, DriveGet

示例

DriveSpaceFree, FreeSpace, c:\


FileAppend

在文件末尾处追加文本 (如果有必要, 首先创建文本).

FileAppend [, Text, Filename, Encoding]

参数

Text

要追加到文件的文本. 此文本可以包含换行符 (`n) 来开始新行. 此外，可以使用 字串分段 的方法把单一的长行分成较短的几行.

如果 Text 为空, 则创建一个文件名为 Filename 的空白文件 (但如果文件已经存在, 则更新其修改时间).

如果 Text 为 %ClipboardAll% 或之前赋值了 ClipboardAll 内容的变量, 则 Filename 将被剪贴板的全部内容无条件覆盖 (即 不需要使用 FileDelete).
Filename

需追加内容的文件的名称, 如果没有指定绝对路径则假定在 A_WorkingDir 中.

二进制模式: 要以二进制模式而不是文本模式追加, 在文件名前面加上星号. 这使得每个换行符 (`n) 作为单个换行符 (LF) 而不是 Windows 标准的 CR+LF 写入. 例如: *C:\My Unix File.txt

如果文件还没有打开 (因为在 文件读取循环 中), 如果 Text 包含任一回车和换行符对 (`r`n) 时文件被自动以二进制模式打开. 换句话说, 前面段落描述的星号选项自动生效. 不过, 当 Text 包含 `r`n 时如果指定星号可以改善性能因为程序不需要扫描 Text 检查其中是否包含 `r`n.

标准输出 (stdout): 在 Filename 参数中指定星号 (*) 可以把 Text 发送到标准输出 (stdout). 这样的文本可以重定向到文件, 指向另一个 EXE 的管道或被 高级文本编辑器 捕获. 例如, 在命令提示符中输入后面的例子将是有效的:
"%ProgramFiles%\AutoHotkey\AutoHotkey.exe" "My Script.ahk" >"Error Log.txt"

然而, 发送到标准输出的文本将不会出现在运行它的命令提示符中. 解决此问题的方法是把脚本的输出通过管道传递给另一个命令或程序. 例如:
1) "%ProgramFiles%\AutoHotkey\AutoHotkey.exe" "My Script.ahk" |more
2) For /F "tokens=*" %L in ('""%ProgramFiles%\AutoHotkey\AutoHotkey.exe" "My Script .ahk""') do @Echo %L

编码 [AHK_L 42+]: 覆盖 FileEncoding 包含的默认设置, 其中 Encoding 遵循相同的格式.

返回值

如果出现错误 ErrorLevel 被设置为 1 否则为 0.

A_LastError 被设置为操作系统 GetLastError() 函数返回的结果.

备注

要覆盖现有的文件, 在使用 FileAppend 前用 FileDelete 删除它.

追加文本后目标文件自动关闭 (除非在 文件读取/写入循环 中以单参数模式使用 FileAppend 时).

[AHK_L 42+]: 追加模式的 FileOpen() 比 FileAppend 提供了更多的控制性并且允许文件保持打开而不是每次打开关闭文件. 一旦文件打开后, 可以使用 file.Write(string) 来追加字符串. 通过 RawWrite/RawRead 文件对象也支持二进制 I/O, 然而 FileAppend 仅支持文本.

相关

FileOpen/文件对象, FileRead, 文件读取循环, FileReadLine, IniWrite, FileDelete, OutputDebug, 字串分段

示例

FileAppend, Another line.`n, C:\My Documents\Test.txt

; The following example uses a continuation section to enhance readability and maintainability:
FileAppend, ( A line of text. By default, the hard carriage return (Enter) between the previous line and this one will be written to the file. This line is indented with a tab; by default, that tab will also be written to the file. Variable references such as %Var% are expanded by default. ), C:\My File.txt

; The following example demonstrates how to automate FTP uploading using the operating ; system's built-in FTP command. This script has been tested on Windows XP and 98se.

FTPCommandFile = %A_ScriptDir%\FTPCommands.txt FTPLogFile = %A_ScriptDir%\FTPLog.txt FileDelete %FTPCommandFile% ; In case previous run was terminated prematurely.

FileAppend, ; The comma is required in this case.
( open host.domain.com username password binary cd htdocs put %VarContainingNameOfTargetFile% delete SomeOtherFile.htm rename OldFileName.htm NewFileName.htm ls -l quit ), %FTPCommandFile% RunWait %comspec% /c ftp.exe -s:"%FTPCommandFile%" >"%FTPLogFile%" FileDelete %FTPCommandFile% ; Delete for security reasons.
Run %FTPLogFile% ; Display the log for review.


FileCopy

复制一个或多个文件。

FileCopy, SourcePattern, DestPattern [, Flag]

参数

SourcePattern | 一个单独文件或文件夹的名称, 或是通配符样式，如 C:\Temp\*.tmp 。如果没有定义绝对路径，则假定 SourcePattern 是在 %A_WorkingDir% 。
DestPattern | 目标的名称或通配符样式，如果没有定义绝对路径，则假定 SourcePattern 是在 %A_WorkingDir%。 执行一个简单的复制 -- 保留已存在文件名称 -- 仅指定文件夹名称像那些功能相同的例子显示的那样： FileCopy, C:\*.txt, C:\My Folder FileCopy, C:\*.txt, C:\My Folder\*.*
Flag | (可选参数) 此 flag(标志) 决定是否覆盖已存在的文件： 0 = (默认) 不覆盖已存在的文件 1 = 覆盖已存在的文件 此参数可为 expression(表 达式)，甚至可以取值为 true 或 false (因为在内部 true 和 false 以 1 和 0 表示)。

ErrorLevel

ErrorLevel 将设置为由于错误而无法复制的文件数，或相反为 0 。如果无法复制任何文件，则 AutoIt v2 (.aut) 脚本会将 ErrorLevel 设为 1。

另外一种情况，如果源文件是一个单独的文件(无通配符)并且文件不存在，ErrorLevel 将设为 0 。要侦测这种情况，在复制源文件前对它使用 IfExist 或 FileExist() 。

与 FileMove 不同的是，复制文件覆盖自己通常会导致错误，即使打开了覆盖模式。

注意

FileCopy 只能复制文件。而要复制文件夹中的所有内容(所有文件和子文件夹)，参看下面的示例。要复制一个单独的文件夹(包括它的子文件夹)，使用 FileCopyDir 。

即使错误发生，操作也会继续。

相关命令

FileMove, FileCopyDir, FileMoveDir, FileDelete

示例

FileCopy, C:\My Documents\List1.txt, D:\Main Backup\ ; 复制且保留原始文件名。
FileCopy, C:\My File.txt, C:\My File New.txt ; 通过提供一个新的名字来复制文件到同个文件夹中。
FileCopy, C:\Folder1\*.txt, D:\New Folder\*.bkp ; 复制到新的位置并改变扩展名。

; 下面的例子复制一个文件夹下的所有文件和文件夹到一个不同的文件夹中：
ErrorCount := CopyFilesAndFolders("C:\My Folder\*.*", "D:\Folder to receive all files & folders")
if ErrorCount <> 0
MsgBox %ErrorCount% 个文件/文件夹不能被复制。
CopyFilesAndFolders(SourcePattern, DestinationFolder, DoOverwrite = false)
; 复制匹配 SourcePattern 的所有文件和文件夹到名为 DestinationFolder 的文件夹
; 并返回不能被复制的文件/文件夹的数量。
{
; 首先复制所有的文件(非文件夹)：
FileCopy, %SourcePattern%, %DestinationFolder%, %DoOverwrite%
ErrorCount := ErrorLevel
; 现在复制所有的文件夹：
Loop, %SourcePattern%, 2 ; 2 表示“只获取文件夹”。
{
FileCopyDir, %A_LoopFileFullPath%, %DestinationFolder%\%A_LoopFileName%, %DoOverwrite%
ErrorCount += ErrorLevel
if ErrorLevel ; 报告每一个有问题的文件夹名称.
MsgBox 不能复制 %A_LoopFileFullPath% 到 %DestinationFolder%.
}
return ErrorCount
}


FileCopyDir

复制一个文件夹连同它的所有文件和子文件夹(和 xcopy 相似)。

FileCopyDir, Source, Dest [, Flag]

参数

Source | 源目录的名称(末尾不带反斜线)，如果绝对路径未指定将被假设在 %A_WorkingDir% 。例如：C:\My Folder
Dest | 目标目录的名称(末尾不带反斜线)，如果绝对路径未指定将被假设在 %A_WorkingDir% 。 例如：C:\Copy of My Folder
Flag | (可选)此 flag(标记) 决定是否覆盖已经存在的文件： 0 (默认): 不覆盖存在的文件。如果 Dest 有一个文件或目录存在，复制操作将不生效并失败。 1: 覆盖存在的文件。不过，任何 Dest 中的文件或子文件夹没在 Source 有对应的将不会被删除。 此参数可以是一个 expression(表 达式) 甚至是一个算得的 true(真) 或 false(假) (因为真或假在内部被存为 1 和 0 )。

ErrorLevel

如果发生了一个问题 ErrorLevel 会被设为 1 ，此外为 0 。
但是，如果源目录包含网页组成的 PageName.htm 和相应的 PageName_files 目录时，即使成功，也会返回 1。

注意

如果目标目录结构不存在，可能的话它将被创建。

由于操作将 recursively(递归地) 复制一个文件夹连同它的所有文件和子文件夹，所以复制一个文件夹到它自身内部的某处目 的地的结果未被定义。要绕弯解决这种情况，先复制它到它自身外部的一个目的地，然后使用 FileMoveDir 来移动复制的文件夹到需要的位置。

FileCopyDir 复制单个文件夹。要代替它复制一个文件夹的内容(它的所有文件和子文件夹)，请看 FileCopy 的示例部分。

相关命令

FileMoveDir, FileCopy, FileMove, FileDelete, file-loops, FileSelectFolder, SplitPath

示例

FileCopyDir, C:\My Folder, C:\Copy of My Folder

; 例子 #2: 一个运行的脚本提示你去复制一个文件夹。
FileSelectFolder, SourceFolder, , 3, Select the folder to copy
if SourceFolder =
return
; 否则，继续。
FileSelectFolder, TargetFolder, , 3, Select the folder IN WHICH to create the duplicate folder.
if TargetFolder =
return
; 否则，继续。
MsgBox, 4, , A copy of the folder "%SourceFolder%" will be put into "%TargetFolder%". Continue?
IfMsgBox, No
return
SplitPath, SourceFolder, SourceFolderName ; 仅从它的完全路径提取文件夹名称。
FileCopyDir, %SourceFolder%, %TargetFolder%\%SourceFolderName%
if ErrorLevel
MsgBox 文件夹没能复制，也许因为在 "%TargetFolder%" 里已经存在同名文件夹。
return


FileCreateDir

创建一个目录/文件夹。

FileCreateDir, DirName

参数

DirName 要创建的目录名，如果绝对路径未指定将被假设在 %A_WorkingDir% 。

ErrorLevel

如果发生了一个问题 ErrorLevel 会 被设为 1 ，此外为 0 。

注意

如果在 DirName 中给出的所有父目录不存在，此命令也将创建它们。

相关命令

FileRemoveDir

示例

FileCreateDir, C:\Test1\My Images\Folder2


FileCreateShortcut

创建快捷方式文件(.lnk)。

FileCreateShortcut, Target, LinkFile [, WorkingDir, Args, Description, IconFile, ShortcutKey, IconNumber, RunState]

参数

Target | 快捷方式所指向的文件名，该参数应包含绝对路径，除非该文件被集成到系统中(如 Notepad.exe)。在快捷方式被创建时，所指向的文件不一定要存在；换言之，指向无效目标的快捷方式可以被创建。
LinkFile | 要创建的快捷方式文件名，如果未指定绝对路径则假设在 %A_WorkingDir% 目录下。确保该参数包含 .lnk 扩展名。如果该文件已存在，它将被覆盖。
WorkingDir | 启动快捷方式时 Target 的当前工作目录。如果留空或省略此参数，快捷方式的“开始位置”为空，当运行该快捷方式时，系统将指定默认的工作目录。
Args | 启动快捷方式时，传递给 Target 的参数。使用空格分隔多个参数。如果一个参数包含空格，使用双引号将这参数括住。
Description | 对快捷方式的描述(操作系统用来显示一个提示信息，等等)。
IconFile | 被 LinkFile 显示的图标的完整路径及文件名。该参数必须是一个 ico 文件或者是 EXE 或 DLL 文件的第一个图标。
ShortcutKey | 单个字母、数字或者 按键列表 中的单个按键名称(可能不支持鼠标按键和其它不标准的按键)。不要使用修饰键符号。目前，所有的快捷键被创建为 CTRL+ALT 快捷方式。例如，如果给该参数指定字母 B，快捷键会是 CTRL-ALT-B 。 对于 Windows 9x: 需要重启才能使快捷键生效。或者你可以打开快捷方式的属性对话框，重新设定快捷键来使它立即生效。
IconNumber | 要使用 IconFile 里除了首个图标外的其他图标，在这里指定编号(可以是表达式)。例如，2 表示第二个图标。
RunState | 要最大化或最小化启动 Target ，指定下面的一个数字： 1 - 正常(默认) 3 - 最大化 7 - 最小化

ErrorLevel

出错则将 ErrorLevel 设为 1，否则为 0 。

注意

如果目标文件位于系统的 PATH 环境变量所列出的某个文件夹里，参数 Target 可能不需要包含路径。

最近创建的快捷方式的只有在桌面上或者在开始菜单的某处，ShortcutKey 才会生效。如果你选择的ShortcutKey 已在使用，那么你新建的快捷方式有优先权。

下面的例子是一个可选用的方法来创建指向某个 URL 的快捷方式，它创建了一个特殊的 URL 快捷方式。改变前两个参数来满足你的偏好：
IniWrite, http://www.google.com, C:\My Shortcut.url, InternetShortcut, URL

下面的命令可随意地添加进来给上面的快捷方式指定一个图标：
IniWrite, <IconFile>, C:\My Shortcut.url, InternetShortcut, IconFile
IniWrite, 0, C:\My Shortcut.url, InternetShortcut, IconIndex

上面的命令中，使用图标编号替换 0 (0 用来指定首个图标)并使用 URL、EXE、DLL 或者 ICO 文件替换 <IconFile> 。例如：C:\Icons.dll, C:\App.exe, http://www.somedomain.com/ShortcutIcon.ico

操作系统会把上面创建的 .URL 文件看作一个真的快捷方式，即使它是一个纯文本文件而不是 .LNK 文件。

相关命令

FileGetShortcut, FileAppend

示例

; 最后一个参数中的字母 "i" 将快捷键设成 Ctrl-Alt-I ：
FileCreateShortcut, Notepad.exe, %A_Desktop%\My Shortcut.lnk, C:\, "%A_ScriptFullPath%", My Description, C:\My Icon.ico, i


FileDelete

删除一个或多个文件.

FileDelete, FilePattern

参数

FilePattern

单个文件名称或通配符例如 C:\Temp\*.tmp. 如果未指定绝对路径则假定 FilePattern 在 %A_WorkingDir% 中.

要移除整个文件夹, 及其所有子文件夹和文件, 使用 FileRemoveDir.

返回值

ErrorLevel 被设置为删除失败的文件数目 (如果有的话) 否则为 0. 删除如 *.tmp 这样的通配符被当成是成功的即使它不匹配任何文件; 因此 ErrorLevel 被设置为 0.

如果找到了文件, A_LastError 被设置为 0 (零) 或在最后一次删除失败时操作系统 GetLastError() 函数返回的结果. 否则 A_LastError 包含一个表明没有找到文件的原因的错误码.

备注

要删除一个只读文件, 首先移除其只读属性. 例如: FileSetAttrib, -R, C:\My File.txt

相关

FileRecycle, FileRemoveDir, FileCopy, FileMove

示例

FileDelete, C:\temp files\*.tmp


FileEncoding

FileEncoding [AHK_L 42+]

为 FileRead, FileReadLine, Loop Read, FileAppend, 和 FileOpen 设置默认编码.

FileEncoding [, Encoding]

编码可以为下列值的其中一个:

  • UTF-8: Unicode UTF-8, 相当于 CP65001.
  • UTF-16: Unicode UTF-16, 小端字节顺序. 相当于 CP1200.
  • UTF-8-RAW 或 UTF-16-RAW: 像上面一样, 但创建新文件时不写入字节顺序标记.
  • CPnnn: 带有数值标识符 nnn 的代码页. 参见 代码页标识符.
  • 为空或省略: 系统默认的 ANSI 代码页, 这也是默认设置.

备注

A_FileEncoding 包含当前设置.

相关

FileOpen, StrPut/StrGet, 脚本兼容性


FileGetAttrib

报告一个文件或文件夹是否为只读、隐藏等等。

FileGetAttrib, OutputVar [, Filename]
AttributeString := FileExist(FilePattern)

参数

OutputVar | 储存获取的文本的变量名称。
Filename | 目标文件的名称，如果绝对路径未指定将被假设在 %A_WorkingDir% 。如果省略，装在 File-Loop 最内层的当前文件将被代为使用。

ErrorLevel

如果发生了一个问题 ErrorLevel 会被设为 1 ，此外为 0 。

注意

返回的字串将包含一个在字符串
"RASHNDOCT" 中的字母子集：

R = READONLY (只读)
A = ARCHIVE (存档)
S = SYSTEM (系统)
H = HIDDEN (隐藏)
N = NORMAL (普通)
D = DIRECTORY (目录)
O = OFFLINE (离线)
C = COMPRESSED (压缩)
T = TEMPORARY (临时)

要检查特定的属性是否在获得的字串里存在，参照此例：

FileGetAttrib, Attributes, C:\My File.txt
IfInString, Attributes, H
 MsgBox 文件是隐藏的。

相关提示，要获取一个文件的 8.3 短名格式，参照此例：

Loop, C:\My Documents\Address List.txt
 ShortPathName = %A_LoopFileShortPath% ; 将产生一些路径类似于 C:\MYDOCU~1\ADDRES~1.txt

一个相似的手法能用来得到 8.3 短名格式的长文件名。

相关命令

FileExist(), FileSetAttrib, FileGetTime, FileSetTime, FileGetSize, FileGetVersion, File-loop

示例

FileGetAttrib, OutputVar, C:\New Folder


FileGetShortcut

获取某个快捷方式(.lnk)文件的信息，比如它的目标文件。

FileGetShortcut, LinkFile [, OutTarget, OutDir, OutArgs, OutDescription, OutIcon, OutIconNum, OutRunState]

参数

LinkFile | 待分析的快捷方式文件名，如果未指定绝对路径，则假定文件在 %A_WorkingDir% 目录下。须确认文件包括 .lnk 扩展名。
OutTarget | 用于保存快捷方式的目标的变量名(不包括任何可能带有的参数)。比如: C:\WINDOWS\system32\notepad.exe
OutDir | 用于保存快捷方式工作目录的变量名。比如: C:\My Documents。如果字符串中存在环境变量（如 %WinDir%），一种解决方法是用 StringReplace。比如: StringReplace, OutDir, OutDir, `%WinDir`%, %A_WinDir%
OutArgs | 用于保存快捷方式参数的变量名（若无则为空）。
OutDescription | 用于保存快捷方式说明的变量名（若无则为空）。
OutIcon | 用于保存快捷方式图标文件名的变量名（若无则为空）。
OutIconNum | 用于保存快捷方式的图标在图标文件中的序号的变量名（若无则为空）。该值通常为 1，表示第一个图标。
OutRunState | 用于保存快捷方式启动时的初始状态的变量名，其值为以下数字之一: 1: 标准 3: 最大化 7: 最小化

ErrorLevel

如果有问题，比如 LinkFile 不存在，则所有输出变量被置为空，同时 ErrorLevel 被置为 1。否则 ErrorLevel 为 0。

注意

如果不需要输出变量提供的相应信息，可将其省略。

相关命令

FileCreateShortcut, SplitPath

示例

FileSelectFile, file, 32,, 选择待分析的快捷方式。, 快捷方式 (*.lnk)
if file =
    return
FileGetShortcut, %file%, OutTarget, OutDir, OutArgs, OutDesc, OutIcon, OutIconNum, OutRunState
MsgBox %OutTarget%`n%OutDir%`n%OutArgs%`n%OutDesc%`n%OutIcon%`n%OutIconNum%`n%OutRunState%


FileGetSize

返回文件的大小。

FileGetSize, OutputVar [, Filename, Units]

参数

OutputVar | 存储返回值(该文件的大小)的变量名(其结果进行四舍五入)。
Filename | 目标文件的文件名，如果绝对路径没有指定的话假定在 %A_WorkingDir%(工作目录) 中。如果忽略不写，当前 File-Loop中 最深处的文件将被替代使用。
Units | 如果这个参数出现，那么它将使得最终返回的结果遵循以下的方案(否则将以字节的形式显示)： K = 千字节 M = 兆字节

ErrorLevel

如果有问题的话 ErrorLevel 被设置为1，否则设置为0。

注意

支持大于4G字节的文件(甚至就算参数Units是字节也可以)。

如果目标文件是一个目录的话，不论操作系统把它当作什么(可能是0)都会返回它的大小。

如果要计算文件夹的大小，像下面这个例子一样计算里面所有的文件：

SetBatchLines, -1  ; 使得操作以最大的速度运行。
FolderSize = 0
FileSelectFolder, WhichFolder  ; 让用户选择一个目录。
Loop, %WhichFolder%\*.*, , 1
    FolderSize += %A_LoopFileSize%
MsgBox Size of %WhichFolder% is %FolderSize% bytes.

相关命令

FileGetAttrib, FileSetAttrib, FileGetTime, FileSetTime, FileGetVersion , File-loop

示例

FileGetSize, size, C:\My Documents\test.doc  ; 以字节的形式返回Test.doc文件的大小
FileGetSize, size, C:\My Documents\test.doc, K  ; 以千字节的形式返回Test.doc文件的大小


FileGetTime

返回指定文件或文件夹的时间戳(时间和日期)信息。

FileGetTime, OutputVar [, Filename, WhichTime]

参数

OutputVar | 以 YYYYMMDDHH24MISS 格式存储返回的时间日期的变量名。时间就是本地时间，不是UTC/GMT(格林尼治标准时间)。
Filename | [可选参数]目标文件或文件夹的名字，如果绝对路径没有指定，就假设在 %A_WorkingDir%(工作目录) 中。如果忽略不写，当前 File-Loop 中最深的文件将被代替使用。
WhichTime | [可选参数]指定时间戳的返回类型： M =修改时间(参数被省略时的默认值)。 C = 创建时间。 A = 访问时间。

ErrorLevel

如果有问题的话 ErrorLevel 被设置为1，否则设置为0。

注意

在操作系统上，一个文件的访问时间在NT上要比在WIN9x上更加精确。

参见 YYYYMMDDHH24MISS 来获取日期和时间的解释。

相关命令

FileSetTime, FormatTime, If var is [not] type, FileGetAttrib, FileSetAttrib, FileGetSize, FileGetVersion , File-loop, EnvAdd, EnvSub

示例

FileGetTime, OutputVar, C:\My Documents\test.doc  ; 默认地返回修改时间。
FileGetTime, OutputVar, C:\My Documents\test.doc, C  ; 返回创建时间。


FileGetVersion

返回指定“文件”（通常是指可执行文件）的版本信息。

FileGetVersion, OutputVar [, Filename]

参数

OutputVar | 存储返回值(数字或字符串)的变量名。
Filename | [可选参数]目标文件或文件夹的名字，如果绝对路径没有指定，就假设在 %A_WorkingDir% 中。如果忽略不写，当前 File-Loop 中最深的文件将被代替使用。

ErrorLevel

如果有问题的话 ErrorLevel 被设置为1，否则设置为0。

注意

大部分不可执行的文件(甚至有些EXE文件)没有版本信息，所以参数OutputVar在这些例子中便成了空值。

相关命令

FileGetAttrib, FileSetAttrib, FileGetTime, FileSetTime, FileGetSize , File-loop

示例

FileGetVersion, version, C:\My Application.exe
FileGetVersion, version, %A_ProgramFiles%\AutoHotkey\AutoHotkey.exe


FileInstall

包含并装入指定文件到 compiled version 的脚本程序中。

FileInstall, Source, Dest [, Flag]

参数

Source | 要装入到编译程序中的文件的路径。如果没有指定绝对路径，文件被假定为在脚本自己的路径里。 文件名不能包含双引号，变量引用(比如%A_ProgramFiles%)，或者通配符。任何特殊字符比如原义百分比符号和逗号都必须为 escaped (就如所有命令中的参数一样)。最终，这个参数必须在 FileInstall 命令的右边被列出来(不能有 continuation line 在它下面)。
Dest | 当 Source 从 EXE 中提取出来时，这参数就是要被创建的文件名称。如果绝对路径没有指定，就假设在 %A_WorkingDir% 中。目标目录必须已存在。与参数Source不一样的是，变量引用可以被使用。
Flag | [可选参数] 此标志参数用以决定是否覆盖已存在的文件： 0 = （默认）不覆盖已存在的文件 1 = 覆盖已存在的文件 这个参数可以成为一个 expression(表达式) ，甚至能当作true或者False来使用(因为True和false其实是以1和0的形式存储的)。

ErrorLevel

如果有问题的话 ErrorLevel 被设置为1，否则设置为0。

注意

这个命令是为 Ahk2Exe compiler 而设置的允许你添加额外文件到最终的编译脚本的。随后，当编译脚本运行的时候，这些文件被提取到磁盘里。

文件是在脚本编译中被添加的。当编译脚本执行，并且执行到相同的"FileInstall"命令时，文件随后被提取到目标(Dest)里。

被添加的文件一般都会被压缩和加密。

如果这个命令出现在一段普通脚本(不是编译脚本)里，一个文件备份将代替出现，这将能帮助我们测试那些最终会被编译的脚本。

相关命令

FileCopy, #Include

示例

FileInstall, C:\My Documents\My File.txt, %A_ProgramFiles%\My Application\Readme.txt, 1


FileMove

移动或重命名一个或者多个文件。

FileMove, SourcePattern, DestPattern [, Flag]

参数

SourcePattern | 单个文件的名称或一个通配符类型例如 C:\Temp\*.tmp 。如果未指定绝对路径，SourcePattern 将假设在 %A_WorkingDir% 。
DestPattern | 目标文件的名称或通配符类型，如果绝对路径未指定将假设在 %A_WorkingDir% 。要执行一个简单的移动 -- 保留已存在的文件名 -- 仅指定文件夹名称像那些功能相同的例子显示的那样： FileMove, C:\*.txt, C:\My Folder FileMove, C:\*.txt, C:\My Folder\*.*
Flag | (可选参数) 此 flag(标识) 决定是否覆盖已存在的文件： 0 = (默认) 不覆盖存在的文件 1 = 覆盖存在的文件 此参数可以是一个 expression(表 达式) 甚至是一个算得的 true(真) 或 false(假) (因为真或假在内部被存为 1 和 0 )。

ErrorLevel

ErrorLevel 被设为由于出错而不能被移动的文件数量，或相反是 0 。不过，如果源文件是单个文件(无通配符)并且文件不存在，ErrorLevel 将设为 0 。要侦测这种情况，在移动源文件前对它使用 IfExist 或 FileExist() 。

与 FileCopy 不同的是，移动一个文件覆盖它自己总是视为成功的，即使覆盖模式没有启用。

注意

FileMove 仅移动文件。要代替它移动一个文件夹的内容(它的所有文件和子文件夹)，请看下面的示例部分。要移动或重命名单个文件夹，使用 FileMoveDir 。

即使错误发生，操作也将继续。

尽管此命令能够移动文件到一个不同的 volume(卷)，但此操作将比在同一个卷上移动花更长的时间。这是因为同一个卷移动类似于重命名，因此更加迅速。

相关命令

FileCopy, FileCopyDir, FileMoveDir, FileDelete

示例

FileMove, C:\My Documents\List1.txt, D:\Main Backup\ ; 不重命名地移动文件。
FileMove, C:\File Before.txt, C:\File After.txt ; 重命名单个文件。
FileMove, C:\Folder1\*.txt, D:\New Folder\*.bkp ; 移动并重命名文件为一个新的扩展名。

; 下面的例子移动一个文件夹内的所有文件和文件夹到一个不同的文件夹：
ErrorCount := MoveFilesAndFolders("C:\My Folder\*.*", "D:\Folder to receive all files & folders")
if ErrorCount <> 0
MsgBox %ErrorCount% 个文件/文件夹不能被移动。
MoveFilesAndFolders(SourcePattern, DestinationFolder, DoOverwrite = false)
; 移动所有匹配 SourcePattern 的文件和文件夹到名为 DestinationFolder 的文件夹
; 并返回不能被移动的文件/文件夹的数量。此函数需要 v1.0.38+
; 因为它使用了 FileMoveDir 的模式 2 。
{
if DoOverwrite = 1
DoOverwrite = 2 ; 请看 FileMoveDir 关于模式 2 对模式 1 的描述。
; 首先移动所有文件(而不是文件夹):
FileMove, %SourcePattern%, %DestinationFolder%, %DoOverwrite%
ErrorCount := ErrorLevel
; 现在移动所有的文件夹:
Loop, %SourcePattern%, 2 ; 2 表示 "仅获取文件夹" 。
{
FileMoveDir, %A_LoopFileFullPath%, %DestinationFolder%\%A_LoopFileName%, %DoOverwrite%
ErrorCount += ErrorLevel
if ErrorLevel ; 报告每一个有问题的文件夹名称。
MsgBox 不能移动 %A_LoopFileFullPath% 到 %DestinationFolder% 。
}
return ErrorCount
}


FileMoveDir

移动一个文件夹连同它的所有文件和子文件夹。也能重命名一个文件夹。

FileMoveDir, Source, Dest [, Flag]

参数

Source | 源目录的名称(末尾不带反斜线)，如果绝对路径未指定将被假设在 %A_WorkingDir% 。例如：C:\My Folder
Dest | 目录的新路径和名称(末尾不带反斜线)，如果绝对路径未指定将被假设在 %A_WorkingDir% 。例如：D:\My Folder。注意：Dest 是目录移动后的实际路径和名称；它不是 Source 移入的目录(除了下面提到的已知限制)。
Flag

(可选参数) 指定下列单个字符中的一个：

0 (默认): 不覆盖存在的文件。如果 Dest 已经作为一个文件或目录存在，移动操作将失败。

1: 覆盖存在的文件。不过，Dest 中任何不存在于 Source 的文件或子文件夹将不会被删除。已知限制：如果 Dest 已经作为一个文件夹存在并且和 Source 在同一个 volume(卷) 上，Source 将被移入 Dest 而不是覆盖它。要避免这种情况，请看下一个选项。

2: 和上面的模式 1 相同，除了不存在那个限制。

R: 重命名目录而不是移动它。虽然重命名目录通常和移动的效果一样，但如果你想要 "all or none" 的表现时，它会很有用；就是说，当 Source 或它的部分文件被锁定时(在使用)你不想移动操作仅部分成功。尽管这种方法不能把 Source 移动到另一个卷，但能把它移到它所在卷的其他任何目录。如果 Dest 已经作为一个文件或目录存在，移动操作将失败。

ErrorLevel

如果发生了一个问题 ErrorLevel 会被设为 1，此外为 0。

注意

FileMoveDir 移动单个文件夹到一个新的位置。要替代它移动一个文件夹的内容(它的所有文件和子文件夹)，请看 FileMove 的示例部分。

如果 source 和 destination 在不同的卷或 UNC(通用命名规则) 路径，一个复制/删除操作将被执行而不是移动。

相关命令

FileCopyDir, FileCopy, FileMove, FileDelete, File-loops, FileSelectFolder, SplitPath

示例

FileMoveDir, C:\My Folder, D:\My Folder  ; 移动到一个新的驱动器。
FileMoveDir, C:\My Folder, C:\My Folder (renamed), R  ; 简单的重命名.
FileMoveDir, C:\My Folder, C:\New Location\My Folder, R  ; 文件夹可以 "重命名至" 另一个目录，只要都在同一盘符下。


FileOpen

FileOpen [AHK_L 42+]

打开文件.

file := FileOpen(Filename, Flags [, Encoding])

参数

Filename | 需打开文件的路径, 如果没有指定绝对路径则假定为 A_WorkingDir.
Flags | [in AHK_L 54+] 表示期望访问模式的字符串, 后面跟着其他选项 (中间可以含有空格或 Tab); 或 [in AHK_L 42+] 数值标志的组合 (总和). 在下面的表中描述了支持的值.
Encoding | 如果文件不包含 UTF-8 或 UTF-16 字节顺序标记 时文本 I/O 使用的代码页. 如果省略, 则使用 A_FileEncoding 的当前值.

标志

 |  | 访问模式 (互斥的)
r | 0 | 读取: 当文件不存在时失败.
w | 1 | 写入: 创建新文件, 覆盖任何现有的文件.
a | 2 | 附加: 如果文件不存在则创建新文件.
rw | 3 | 读取/写入: 如果文件不存在则创建新文件.
h |  | 表示 文件名 是包装在对象中的文件句柄. 忽略共享模式标志. 当文件对象销毁时文件句柄 不会 自动关闭并且调用 Close 没有效果. 注意当 文件名 是到非搜寻设备例如管道或通信设备的句柄时不应该使用 Seek, Tell 和 Length.
 |  | 共享模式标志
-rwd |  | 为读取, 写入和/或删除访问进行文件锁定. 可以使用 r, w 和 d 的任意组合. 指定 - 相当于指定 -rwd. 如果完全省略, 默认为共享所有访问.
 | 0 | 如果 Flags 是数值的, 缺少共享模式标志会使得文件被锁定.
 | 0x100 | 共享 读取 访问.
 | 0x200 | 共享 写入 访问.
 | 0x400 | 共享 删除 访问.
 |  | 行结束符 (EOL) 选项
`n | 4 | 当读取时使用 `n 代替 `r`n 而写入时使用 `r`n 代替 `n .
`r | 8 | 读取时使用 `n 替换单独的 `r .

返回值

如果成功打开文件, 返回值为 文件对象.

如果函数失败, 返回值为 0 并且 [in AHK_L 54+] A_LastError 包含错误代码.

使用 if file 或 IsObject(file) 可以检查函数是否成功执行.

备注

当创建 UTF-8 或 UTF-16 文件时, 会写入字节顺序标记到文件中 除非 Encoding (或 A_FileEncoding, 当 Encoding 省略时) 包含 "UTF-8-RAW" 或 "UTF-16-RAW".

相关

FileEncoding, 文件对象, FileRead

示例

; Open the script in read-only mode and read its first line:
file := FileOpen(A_ScriptFullPath, "r") MsgBox % file.ReadLine()

; Open the application's stdin/stdout handles in newline-translated mode. ; This can be tested by typing into the output pane of SciTE4AutoHotkey.
stdin := FileOpen(DllCall("GetStdHandle", "int", -10, "ptr"), "h `n") stdout := FileOpen(DllCall("GetStdHandle", "int", -11, "ptr"), "h `n") stdout.Write("Enter your query.`n\> ") query := RTrim(stdin.ReadLine(), "`n") stdout.WriteLine("Your query was '" query "'. Have a nice day.")


FileReadLine

读取文件指定行的文本并保存到 变量 中.

FileReadLine, OutputVar, Filename, LineNum

参数

OutputVar | 用于保存获取的数据的 变量 名称.
Filename | 需访问的文件的名称, 如果没有指定绝对路径则假定在 A_WorkingDir 中. 支持 Windows 和 Unix 格式; 即文件的行结束符可以是回车和换行符 (`r`n) 或只是单独的 (`n).
LineNum | 需读取的行号 (首行为 1, 第二行为 2, 等等). 可以为 表达式. 如果指定的行号大于文件的行数, ErrorLevel 被设置为 1 并且 OutputVar 不会发生变化. 当指定的行号为文件的最后一行同时此行为空并且不是以新行/CRLF 结束时也可能发生这种情况.

返回值

成功时 ErrorLevel 被设置为 0. 否则它被设置为 1 并且 OutputVar 的原始内容不会发生变化.

A_LastError 被设置为操作系统 GetLastError() 函数返回的结果.

备注

强烈建议仅对于小文件或只需要单行文本的情况时使用此命令. 要扫描并处理大量行的文本 (一行接一行), 使用 文件读取循环 性能更好. 要读取整个文件到变量中, 使用 FileRead.

虽然任何出现在行开始或末尾的 Tab 或空格都会写入到 OutputVar 中, 但换行符 (`n) 是个例外. 当 AutoTrim 设置打开 (默认值) 时, 任何变量都可以通过赋值给自己来截除变量两端的 Tab 和空格. 例如: MyLine = %MyLine%

最大可以读取包含 65,534 字符的长行. 如果行的长度超过这个极限, 此命令无法读取剩余的字符 (此时应使用 FileRead 或 文件读取循环 代替).

相关

FileOpen/File.ReadLine(), FileRead, FileAppend, 文件读取循环, IniRead

示例

Loop
{
    FileReadLine, line, C:\My Documents\ContactList.txt, %A_Index%
    if ErrorLevel
        break
    MsgBox, 4, , Line #%A_Index% is "%line%".  Continue?
    IfMsgBox, No
        return
}
MsgBox, The end of the file has been reached or there was a problem.
return


FileRead

读取文件的内容到 变量 中.

FileRead, OutputVar, Filename

参数

OutputVar 用于保存获取的数据的 变量 名称. 如果遇到问题例如文件 "在使用中" 或不存在则 OutputVar 被置空 (此时 ErrorLevel 被设置为 1). 如果 Filename 是个空文件输出变量也被置空 (此时 ErrorLevel 被设置为 0).
Filename

需读取的文件的名称, 如果没有指定绝对路径则假定在 A_WorkingDir 中.

选项: 零个或多个下列字符串还可以直接放在文件名的前面. 在选项间使用单个空格或 Tab 分隔. 例如: *t *m5000 C:\Log Files\200601.txt

*c: 读取保存了 ClipboardAll 内容的文件. 使用了 *c 选项时其他所有选项被忽略.

*m1024 [v1.0.43.03+]: 如果省略此选项, 则读取整个文件除非它大于 1 GB, 此时根本不读取文件. 否则, 使用 1 到 1073741824 (1 GB) 字节的十进制或十六进制数代替 1024. 如果文件大于此字节数, 那么只读取其前面部分. 注意: 此选项可能导致最后一行以单独的回车符 (`r) 而不是 `r`n 结束.

*t: 用换行符 (`n) 替换所有的回车换行符 (`r`n). 不过, 这种转换降低性能而且往往不必要. 例如, 包含 `r`n 的文本已经是添加到 Gui 编辑控件 的正确格式. 同样地, FileAppend 打开新文件时会检测是否含有 `r`n; 它知道按现在的样子写入每对 `r`n 而不是把它转换成 `r`r`n. 最后, 不论每行的结束符是 `r`n 或只是 `n, 后面的 解析循环 都可以正确执行: Loop, parse, MyFileContents, `n, `r

*Pnnn: [AHK_L 42+]: 覆盖 FileEncoding 包含的默认编码设置, 这里 nnn 必须是数值的 代码页标识符.

返回值

如果读取成功 ErrorLevel 被设置为 0. 如果遇到问题它被设置为 1, 例如: 1) 文件不存在; 2) 文件被锁定或无法访问; 3) 系统没有足够的内存加载文件.

A_LastError 被设置为操作系统 GetLastError() 函数返回的结果.

读取二进制数据 [AHK_L 42+]

根据文件, 参数和默认设置, FileRead 可能把文件数据解释为文本并且把它转换成脚本使用的 原生编码. 如果文件包含二进制数据这样操作很可能引起问题, 除非在下列情况下:

  • 如果存在 *C 选项, 所有代码页和行结束符的转换都无条件忽略.
  • 如果存在 *Pnnn 选项并且 nnn 符合原生字符串编码, 不会进行代码页转换.
  • 如果当前 文件编码 设置符合原生字符串编码, 不会进行代码页转换.

此外, 可以使用 FileOpen() 和 File.RawRead() 读取二进制数据.

备注

当需要读取文件的全部或大部分内容到内存时, 使用 FileRead 比 文件读取循环 执行的更好.

大于 1 GB 的文件将导致 ErrorLevel 被设置为 1 并且 OutputVar 被置空除非使用了 *m 选项, 此时读取文件的前面部分.

FileRead 不服从 #MaxMem 的设置. 如果担心使用太多内存, 预先用 FileGetSize 检查文件的大小.

如果指定的文件包含二进制零 (它决不可能出现在正确的文本文件中), 那么仅仅在首个二进制零前面的文本会被 AutoHotkey 命令和函数 "看到". 但是, 整个文件的内容仍会保存到 OutputVar 中并且可以通过高级的方法例如 NumGet() 和 地址运算符 (&) 访问; 例如: *(&OutputVar + 1000)

与 文件读取循环 和 FileReadLine 不同, FileRead 不会把 控制字符 Control-Z (0x1A) 作为文件结束的标记. 因此任何的 Control-Z, 即使出现在文件的最后, 也会被照常读取.

使用 FileRead 可以快速对文件的内容进行排序, 如下所示:

FileRead, Contents, C:\Address List.txt
if not ErrorLevel  ; 成功读取.
{
    Sort, Contents
    FileDelete, C:\Address List (alphabetical).txt
    FileAppend, %Contents%, C:\Address List (alphabetical).txt
    Contents =  ; 清空占用的内存.
}

[AHK_L 42+]: FileOpen() 比 FileRead 提供了更高级的功能, 例如在文件中指定的位置读取或写入数据而不需要读取整个文件到内存中. 参见 文件对象 了解函数列表.

相关

FileOpen/文件对象, 文件读取循环, FileReadLine, FileGetSize, FileAppend, IniRead, Sort, UrlDownloadToFile

示例

FileRead, OutputVar, C:\My Documents\My File.txt


FileRecycle

把指定的文件或目录放入回收站(如果可行的话)。

FileRecycle, FilePattern

参数

FilePattern

一个单独的文件名，或者有通配符的模式，比如 C:\Temp\*.tmp. 如果没有指定绝对路径参数FilePattern 被假定为在 %A_WorkingDir% 中。

为了回收整个目录，可以以名字后面不加反斜线符号方式来达到。

ErrorLevel

如果有问题的话 ErrorLevel 被设置为1，否则设置为0。

注意

无

相关命令

FileRecycleEmpty, FileDelete, FileCopy, FileMove

示例

FileRecycle, C:\temp files\*.tmp


FileRecycleEmpty

清空回收站。

FileRecycleEmpty [, DriveLetter]

参数

DriveLetter [可选参数]若留空，将清空所有驱动器中的回收站。否则，指定一个驱动器，比如C:\

ErrorLevel

如果有问题的话 ErrorLevel 被设置为1，否则设置为0。

注意

这个命令需要微软的IE4.0或者更高的版本。

相关命令

FileRecycle, FileDelete, FileCopy, FileMove

示例

FileRecycleEmpty, C:\


FileRemoveDir

删除一个文件夹。

FileRemoveDir, DirName [, Recurse?]

参数

DirName | 要删除的目录名称，如果绝对路径未指定将被假设在 %A_WorkingDir%。
Recurse? | 0 (默认): 不移除包含在 DirName 中的文件和子目录。既然如此，如果 DirName 内不是空的，删除将不会执行并且 ErrorLevel 将被设为 1。 1: 移除所有文件和子目录(像 Windows 命令行的 "rmdir /S")。 此参数可以是一个表达式甚至是一个算得的 true 或 false (因为 true 和 false 在内部被存为 1 和 0)。

ErrorLevel

如果发生了一个问题 ErrorLevel 会被设为 1，此外为 0。

注意

无:-)

相关命令

FileCreateDir, FileDelete

示例

FileRemoveDir, C:\Download Temp
FileRemoveDir, C:\Download Temp, 1


FileSelectFile

显示一个允许用户来打开或保存文件的标准对话框。

FileSelectFile,OutputVar[,Options,RootDir\Filename,Prompt,Filter]

参数

OutputVar | 用来保存用户选择的文件名的变量名称。如果用户取消了对话框(即不想选择一个文件)，该变量为空。
Options

如果省略此项，默认值为 0，意味着以下选项都不生效。

M: 多选。指定字母 M 表示允许用户通过按住 Shift、Control 键或者其它方式来选择多个文件。M 后面可以跟一个下面提到的数字(例如，M 和 M1 都是有效的)。要提取单个文件，请看本页底部的例子。

S: 保存按钮。指定字母 S 使对话框上总是包含保存按钮而不是打开按钮。S 后面可以跟一个下面提到的数字(或几个数的和。例如，S 和 S24 都是有效的)。

即使没有 M 和 S，下列数字也可以被使用。要同时使多个选项生效，只要把数字加起来。例如，要使用 8 和 16，指定数字 24。

1：文件必须存在
2：路径必须存在
8：提示创建新文件
16：提示覆盖文件
32 [v1.0.43.09+]：选择的快捷方式(.lnk 文件)是它本身而不是它所指向的目标。此选项也防止了选择一个文件夹快捷方式会跳转到那个文件夹。

如果用“提示覆盖文件”选项并且不用“提示创建新文件”选项的话，对话框将包含保存按钮而不是打开按钮。这个问题是 Windows 的毛病。
RootDir\Filename

如果存在，此参数可包含下列的一项或全部：

RootDir：根(起始)目录，如果没有使用完全路径的话，假设为 %A_WorkingDir% 里的子文件夹。如果省略此参数或留空，起始目录会是默认值，而且随操作系统版本而有所不同(在 WinNT/2k/XP 及之后的版本中，它通常是用户上一次使用 FileSelectFile 时选择的目录)。在 v1.0.43.10 及之后的版本中，支持使用 CLSID(Windows 类标识符)比如 ::{20d04fe0-3aea-1069-a2d8-08002b30309d}(即我的电脑)，这时在 CLSID 后面的任何子目录路径都必须以反斜线结尾(否则，最后一个反斜杠之后的字符串将被认为是默认的文件名，请看下面)。

Filename：一开始显示在对话框里的编辑框中的默认文件名。只有单独的文件名(不带路径)才会被显示。要确保对话框正确地显示，请不要提交非法的字符(比如 /<|:")。

示例：

C:\My Pictures\Default Image Name.gif ; RootDir 和 Filename 都提供了。
C:\My Pictures ;只提供了 RootDir。
My Pictures ;只提供了 RootDir，它相对于当前的工作目录。
My File ;只提供了 Filename(但如果存在“My File”文件夹，则会被认为是 RootDir)。
Prompt | 显示在窗口标题栏指示用户做什么的文本。如果省略或留空，它将默认为"Select File - %A_SCRIPTNAME%" (即当前脚本的名称)。
Filter

指示哪些类型的文件会被对话框显示。

例如：Documents (*.txt)
例如：Audio (*.wav; *.mp2; *.mp3)

如果省略，过滤器默认是 All Files (*.*)。另外在对话框的“文件类型”下拉列表中的 Text Documents (*.txt) 选项也是可用的。

否则，过滤器将使用此参数指示的字符串，不过在对话框的“文件类型”下拉列表中仍然提供 All Files (*.*) 的选项。要在过滤器中包含多个文件扩展名，像上面的例子中那样用分号将它们隔开。

ErrorLevel

如果用户没有选择文件(比如按了取消按钮)就关掉了对话框，ErrorLevel 设为 1。如果系统拒绝显示对话框时(罕见)也将设为 1。之外设为 0。

注意

如果用户什么也没选(例如按了取消)，OutputVar 为空。

如果没有使用多选，OutputVar 的值将设为用户选择的单个文件的完整路径和名称。

如果使用了 M 选项(多选)，OutputVar 的值将设为一个列表，其中除了最后一个外，每个后面都跟了一个换行符(`n)。列表中的第一行是所有被选择的文件的路径(只有在此路径是根目录比如 C:\ 时才以反斜线结尾)。其它的条目是被选择的文件名(不带路径)。例如：
C:\My Documents\New Folder [这是下面所有文件所在的路径]
test1.txt [这些是单独的文件名：没有路径]
test2.txt
……等。
(本页底部的例子示范了如何一个个提取文件。)

在使用多选时，被选择的文件名的总长度被限制在 64 KB。不过通常这足以容纳几千个文件了，如果超出此限制的话，OutputVar 将为空。

GUI 窗口可以用 Gui +OwnDialogs 来显示一个 modal(模态)文件选择对话框。模态对话框可以阻止用户在关掉对话框之前与 GUI 窗口的交互。

已知限制：在文件选择对话框显示期间运行的定时器会延迟用户在对话框中点击的效果直到定时器结束。要绕弯解决此限制，应避免使用那些子程序会运行很长时间才结束的定时器，或者在使用对话框时禁用所有的定时器：

Thread，NoTimers
FileSelectFile，OutputVar
Thread，NoTimers，false

作废的选项：在 v1.0.25.06 及之后的版本中，多选选项“4”已作废。可是为了与以前的脚本兼容，这个选项仍然可用。具体是，如果用户只选择了一个文件，OutputVar 会包括它的完整路径和文件名再加上一个换行符(`n)。如果用户选择了多个文件，除了最后一行还是以换行符(`n)结尾外，其它的格式都和上面描述的 M 选项一样。

相关命令

FileSelectFolder, MsgBox, InputBox, ToolTip, GUI, CLSID List, parsing loop, SplitPath

操作系统也提供了标准的对话框来提示用户选择字体、颜色或图标。这些对话框可以通过 DllCall() 命令来显示，请看 www.autohotkey.com/forum/topic17230.html。

示例

FileSelectFile, SelectedFile, 3, , 打开一个文件 (*.txt; *.doc)
if SelectedFile =
    MsgBox, 用户什么也没有选择。
else
    MsgBox, 用户选了下列文件:`n%SelectedFile%

CLSID 示例:
FileSelectFile, OutputVar,, ::{645ff040-5081-101b-9f08-00aa002f954e}  ;回收站。

;多选示例:
FileSelectFile, files, M3  ; M3 = 选择多个存在的文件。
if files =
{
    MsgBox, 用户按了取消。
    return
}
Loop, parse, files, `n
{
    if a_index = 1
        MsgBox, 选择的文件都包含在 %A_LoopField%。
    else
    {
        MsgBox, 4, , 下一个文件是 %A_LoopField%。继续？
        IfMsgBox, No, break
    }
}
return


FileSelectFolder

显示允许用户选择文件夹的标准对话框。

FileSelectFolder, OutputVar [, StartingFolder, Options, Prompt]

参数

OutputVar

用来保存用户所选择的文件夹的变量名。如果用户取消了对话框，则该变量将被置为空（比如不想选择文件夹）。若用户选择了根目录（如 C:\），OutputVar 会以反斜杠结尾。如果不需要这个反斜杠，可用下面的方法去掉它：

FileSelectFolder, Folder
Folder := RegExReplace(Folder, "\\$")  ; 若以反斜杠结尾，则去掉它。
StartingFolder

若为空或省略，对话框选择的起始目录为用户的我的文档文件夹（或者可能是我的电脑）。 CLSID 文件夹，比如 ::{20d04fe0-3aea-1069-a2d8-08002b30309d} （也就是我的电脑）可以作为特殊文件被指定为起始目录。

另外，该参数最常见的用法是一个星号通配符后紧跟着作为起始位置的驱动器或文件夹的绝对路径。比如 *C:\ 将把C盘作为起始选择位置。与此类似，*C:\My Folder 将把该文件夹作为起始选择位置。

星号表示允许用户从起始目录向上导航（接近根目录）。如果没有星号，用户只能选择 StartingFolder 中的文件夹（或者 StartingFolder 本身）。省略星号的一个好处是用户不必点击目录前的加号，StartingFolder 一开始即以树状目录形式显示出来。

若存在星呈，向上导航可被限制到除桌面外的某个文件夹。在星号前加上最上级文件夹的绝对路径和一个空格或制表符，即可达到此目的。 在下面的例子中，不允许用户导航到高于 C:\My Folder 的目录（但起始目录为 C:\My Folder\Projects）：
C:\My Folder *C:\My Folder\Projects
Options

以下数字之一：

0: 以下所有选项无效（Windows 2000 除外，它可能始终显示“新建文件夹”按钮）。

1 （默认）：提供允许用户新建文件夹的按钮。然而，该按钮在 Windows 95/98/NT 中不会出现。

上述数字加 2 提供允许用户输入文件夹名的编辑框。比如该参数为数值 3，则同时提供一个编辑框和一个“新建文件夹”按钮。

上述数字加 4 可以忽略 BIF_NEWDIALOGSTYLE 属性。加4确保了 FileSelectFolder 可以在诸如 WinPE 或者 BartPE 之类的预安装环境中也能正常工作。然而，这可能会妨碍 "新建文件夹" 按钮的出现，至少在 Windows XP 中是这样。["4" 需要 1.0.48+ 版本]

如果用户在编辑框中输入非法文件夹名， OutputVar 将会被置为在导航树中选择的文件夹名，而不是用户输入的名称，至少在 Windows XP 中是这样。

该参数可以是个表达式。
Prompt 显示在窗口中，告诉用户该做什么的文字。如果省略或空白，则默认为“选择文件夹 - %A_SCRIPTNAME%"（也就是当前脚本的名称）。

ErrorLevel

如果用户关闭对话框而未选择文件，则 ErrorLevel 被置为 1 （比如按了取消按钮）。如果系统拒绝显示对话框（罕见），该变量也会被置为 1。否则其值为 0。

注意

在 GUI 窗口中，可以用 Gui +OwnDialogs 来显示一个选择文件夹的模式对话框。在模式对话框关闭之前，禁止用户与 GUI 窗口进行交互操作。

已知的限制：在显示 FileSelectFolder 对话框时启动的定时器，将会使用户在对话框中的点击延迟生效，直到该定时器程序执行完毕。为避免这一问题，应避免使用子程序耗时很长的定时器，或者在显示对话框时禁止所有的定时器：

Thread, NoTimers
FileSelectFolder, OutputVar,, 3
Thread, NoTimers, false

相关命令

FileSelectFile, MsgBox, InputBox, ToolTip, GUI, CLSID List, FileCopyDir, FileMoveDir, SplitPath

操作系统还提供提示用户选择字体、颜色或图标的标准对话框。这些对话框可以通过 DllCall() 来显示，示例见 www.autohotkey.com/forum/topic17230.html。

示例

FileSelectFolder, OutputVar, , 3
if OutputVar =
    MsgBox, 您未选择文件夹。
else
    MsgBox, 您选择了文件夹 “%OutputVar%”。

CLSID 示例：
FileSelectFolder, OutputVar, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}  ; 我的电脑。


FileSetAttrib

改变一个或多个文件或文件夹的属性. 支持通配符.

FileSetAttrib, Attributes [, FilePattern, OperateOnFolders?, Recurse?]

参数

Attributes | 需要改变的属性 (参见备注).
FilePattern | 单个文件或文件夹的名称, 或通配符例如 C:\Temp\*.tmp. 如果未指定绝对路径则假定 FilePattern 在 %A_WorkingDir% 中. 如果省略, 则使用最内层 文件循环 的当前文件代替.
OperateOnFolders? | 0 (默认值) 不对文件夹进行操作 (仅文件). 1 对匹配通配符的所有文件和文件夹进行操作. 2 仅对文件夹进行操作 (不操作文件). 注意: 如果 FilePattern 是单个文件夹而不是一个通配符, 那么此设置总是被忽略. 此参数可以为 表达式.
Recurse? | 0 (默认值) 不遍历子文件夹. 1 遍历所有子文件夹以便对包含在其中的匹配 FilePattern 的所有文件和文件夹都进行操作. 将遍历所有子文件夹, 而不仅仅名称与 FilePattern 匹配的那些. 然而, 完整路径名称超过 259 个字符的文件和文件夹会被跳过, 就像不存在一样. 这样的文件极少, 因为一般操作系统不会允许创建它们. 此参数可以为 表达式.

返回值

ErrorLevel 被设置为改变属性 失败 的文件数目, 否则为 0.

如果找到了文件, A_LastError 被设置为 0 (零) 或在最后一次设置属性失败时操作系统 GetLastError() 函数返回的结果. 否则 A_LastError 包含一个表明没有找到文件的原因的错误码.

备注

Attributes 参数由运算符和属性字母组成.

运算符:

+ | 启用属性
- | 取消属性
^ | 切换属性 (设置为与现在相反的值)

属性字母:
R = 只读
A = 存档
S = 系统
H = 隐藏
N = 普通 (仅当单独使用时此属性才有效)
O = 离线
T = 临时

注意: 当前, 文件的压缩状态无法使用此命令改变.

相关

FileGetAttrib, FileGetTime, FileSetTime, FileGetSize, FileGetVersion, File-loop

示例

FileSetAttrib, +RH, C:\MyFiles\*.*, 1 ; +RH is identical to +R+H
FileSetAttrib, ^H, C:\MyFiles ; Toggle the folder's "hidden" attribute.
FileSetAttrib, -R+A, C:\New Text File.txt FileSetAttrib, +A, C:\*.ini, , 1 ; Recurse through all .ini files on the C drive.


FileSetTime

改变一个或多个文件或文件夹的时间戳. 支持通配符.

FileSetTime [, YYYYMMDDHH24MISS, FilePattern, WhichTime, OperateOnFolders?, Recurse?]

参数

YYYYMMDDHH24MISS | 如果为空或省略, 默认使用当前时间. 否则, 指定操作使用的时间 (参见备注了解时间的格式). 不支持 1601 以前的年份. 此参数可以为 表达式. 因此, 如果需要组合多个变量来形成单个时间戳, 应该使用 点运算符 代替百分号. 例如: FileSetTime, Year . Month . Day, C:\My File.txt
FilePattern | 单个文件或文件夹的名称, 或通配符例如 C:\Temp\*.tmp. 如果未指定绝对路径则假定 FilePattern 在 %A_WorkingDir% 中. 如果省略, 则使用最内层 文件循环 的当前文件代替.
WhichTime | 需设置的时间戳: M = 修改时间 (如果此参数为空或省略, 这是默认值) C = 创建时间 A = 访问时间
OperateOnFolders? | 0 (默认值) 不对文件夹进行操作 (仅文件). 1 对匹配通配符的所有文件和文件夹进行操作. 2 仅对文件夹进行操作 (不操作文件). 注意: 如果 FilePattern 是单个文件夹而不是一个通配符, 那么此设置总是被忽略. 此参数可以为 表达式.
Recurse? | 0 (默认值) 不遍历子文件夹. 1 遍历所有子文件夹以便对包含在其中的匹配 FilePattern 的所有文件和文件夹都进行操作. 将遍历所有子文件夹, 而不仅仅名称与 FilePattern 匹配的那些. 然而, 完整路径名称超过 259 个字符的文件和文件夹会被跳过, 就像不存在一样. 这样的文件极少, 因为一般操作系统不会允许创建它们. 此参数可以为 表达式.

返回值

ErrorLevel 被设置为改变时间戳 失败 的文件数目, 否则为 0. 如果指定的时间戳无效或 FilePattern 解析为空值, ErrorLevel 被设置为 1.

如果找到了文件, A_LastError 被设置为 0 (零) 或在最后一次设置时间戳失败时操作系统 GetLastError() 函数返回的结果. 否则 A_LastError 包含一个表明没有找到文件的原因的错误码.

备注

在 Windows 95/98/ME 系统中, 不支持改变文件夹的时间戳. 这样的尝试被忽略.

文件在 FAT16 & FAT32 分区上的最近一次访问时间可能不如在 NTFS 分区上那么精确.

YYYYMMDDHH24MISS 格式中元素表示的含义分别为:

YYYY | 4 位数的年份
MM | 2 位数的月份 (01-12)
DD | 月的 2 位数的天数 (01-31)
HH24 | 24 小时格式的 2 位小时数 (00-23). 例如, 09 是 9am 而 21 是 9pm.
MI | 2 位的分钟数 (00-59)
SS | 2 位的秒数 (00-59)

如果只给出了 YYYYMMDDHH24MISS 中的部分字符串 (例如 200403), 任何省略的元素值将以后面的默认值填充:

MM: Month 01
DD: Day 01
HH24: Hour 00
MI: Minute 00
SS: Second 00

内置变量 A_Now 包含了上述格式的当前本地区域时间. 同样地, A_NowUTC 包含了当前协调的通用时间.

注意: 通过 EnvAdd 和 EnvSub, 日期时间值可以进行比较和加减. 同样, 最好不要使用大于或小于来比较时间除非它们的字符串长度相同. 这是因为它们被作为数字进行比较; 例如, 20040201 数值上总是小于 (但时间顺序上较后) 200401010533. 所以应该使用 EnvSub 来计算出它们之间的时间差是正还是负.

相关

FileGetTime, FileGetAttrib, FileSetAttrib, FileGetSize, FileGetVersion, FormatTime, 文件循环, EnvAdd, EnvSub

示例

; Set the modification time to the current time for all matching files:
FileSetTime, , C:\temp\*.txt

; Set the modification date (time will be midnight):
FileSetTime, 20040122, C:\My Documents\test.doc

; Set the creation date. The time will be set to 4:55pm:
FileSetTime, 200401221655, C:\My Documents\test.doc, C

; Change the mod-date of all files that match a pattern. ; Any matching folders will also be changed due to the last parameter:
FileSetTime, 20040122165500, C:\Temp\*.*, M, 1


IfExist / IfNotExist

检查文件或文件夹是否存在.

IfExist, FilePattern
IfNotExist, FilePattern
AttributeString := FileExist(FilePattern)

参数

FilePattern 需检查的路径, 文件名或文件模式. 如果未指定绝对路径则假定 FilePattern 在 %A_WorkingDir% 中.

相关

FileExist(), 区块, Else, 文件循环

示例

IfExist, D:\
    MsgBox, The drive exists.
IfExist, D:\Docs\*.txt
    MsgBox, At least one .txt file exists.
IfNotExist, C:\Temp\FlagFile.txt
    MsgBox, The target file does not exist.


IniDelete

删除标准格式的 .ini 文件中的值.

IniDelete, Filename, Section [, Key]

参数

Filename | .ini 文件名, 如果未指定绝对路径则假定在 %A_WorkingDir% 中.
Section | .ini 文件中的段名, 它是包含在方括号中的标题短语 (在此参数中不需要加方括号).
Key | .ini 文件中的键名. 如果省略, 将删除整个 Section.

ErrorLevel

如果遇到问题则 ErrorLevel 被置为 1, 否则为 0. 然而, 如果脚本为 .aut (AutoIt v2) 类型, 那么 ErrorLevel 不会发生变化 (由于兼容性的原因).

备注

标准的 ini 文件看起来类似下面这样:

[SectionName]
Key=Value

相关

IniRead, IniWrite, RegDelete

示例

IniDelete, C:\Temp\myfile.ini, section2, key


IniRead

读取标准格式的 .ini 文件中的值.

IniRead, OutputVar, Filename [, Section, Key, Default]

参数

OutputVar | 用来存储获取值的变量名. 如果无法获取到这个值, 此变量会被设置为由 Default 参数提供的值 (如下所述). [AHK_L 57+]: 如果省略 Key 参数, 那么会获取去除任何注释的指定 Section 的内容. 如果也省略 Section 参数, 那么 OutputVar 中会存储段名列表, 其中每个名称都用换行符 (`n) 隔开.
Filename | .ini 文件名, 如果未指定绝对路径则假定在 %A_WorkingDir% 中.
Section | .ini 文件中的段名, 它是包含在方括号中的标题短语 (在此参数中不需要加方括号).
Key | .ini 文件中的键名.
Default | 当没有找到请求的键时保存到 OutputVar 中的值. 如果省略, 此参数默认为单词 ERROR. 要存储空值 (空字符串), 请指定 %A_Space%. [AHK_L 57+]: 省略 Key 时不使用此参数. 对于 AutoIt (.aut) 脚本: 出于兼容方面的考虑, 不支持此参数; 在读取值遇到问题时, OutputVar 中将总是存储字符串 ERROR.

ErrorLevel

此命令 不会 改变 ErrorLevel. 如果遇到问题, OutputVar 将被设置为如上所述的 Default 值.

备注

操作系统会自动忽略获取字符串中前导和尾随空格/tab.

标准的 ini 文件看起来类似下面这样:

[SectionName]
Key=Value

相关

IniDelete, IniWrite, RegRead, 文件读取循环, FileRead

示例

IniRead, OutputVar, C:\Temp\myfile.ini, section2, key
MsgBox, The value is %OutputVar%.


IniWrite

写入值到标准格式的 .ini 文件.

IniWrite, Value, Filename, Section [, Key]

参数

Value | 将被写入到 Key 的等号 (=) 右边的字符串或数字. 如果文本较长, 可以通过 延续片段 的方法将其分解成较短的几行, 这样可以增加可读性和可维护性. [AHK_L 57+]: 如果省略 Key, 那么此参数应该包含要写入到 .ini 文件的全部的段内容, 不包括 [SectionName] 标题.
Filename | .ini 文件名, 如果未指定绝对路径则假定在 %A_WorkingDir% 中.
Section | .ini 文件中的段名, 它是包含在方括号中的标题短语 (在此参数中不需要加方括号).
Key | .ini 文件中的键名.

ErrorLevel

如果遇到问题则 ErrorLevel 被置为 1, 否则为 0. 然而, 如果脚本为 .aut (AutoIt v2) 类型, 那么 ErrorLevel 不会发生变化 (由于兼容性的原因).

备注

标准的 ini 文件看起来类似下面这样:

[SectionName]
Key=Value

Unicode: IniRead 和 IniWrite 依靠外部函数 GetPrivateProfileString 和 WritePrivateProfileString 来读取和写入值. 这些函数仅支持 UTF-16 编码的 Unicode 文件; 其他所有文件都被认为使用系统默认 ANSI 代码页. 在 Unicode 脚本 中, IniWrite 为每个新文件使用 UTF-16 编码. 如果不希望这样, 那么请确保在执行 IniWrite 前目标文件已经存在. 例如:

FileAppend,, NonUnicode.ini, CP0 ; 在大多数情况下最后一个参数是可选的.

相关

IniDelete, IniRead, RegWrite

示例

IniWrite, this is a new value, C:\Temp\myfile.ini, section2, key


Loop (文件和文件夹)

获取指定的文件或文件夹, 每次一个.

Loop, FilePattern [, IncludeFolders?, Recurse?]

参数

FilePattern | 单个文件或文件夹的名称, 或通配符模式, 例如 C:\Temp\*.tmp. 如果未指定绝对路径则假定 FilePattern 在 %A_WorkingDir% 中. 支持星号和问号作为通配符使用. 当模式出现在文件的长/普通名称或其 8.3 短名称 时出现匹配. 如果此参数为单个文件或文件夹 (即不含通配符) 且 Recurse 为 1, 同时指定的文件名出现在多个被搜索的文件夹中, 那么将找到多个匹配.
IncludeFolders? | 使用下列的其中一个数字, 或留空以使用默认值: 0 (默认) 不获取文件夹 (仅文件). 1获取所有匹配通配符模式的文件和文件夹. 2仅获取文件夹 (不获取文件).
Recurse? | 使用下列的其中一个数字, 或留空以使用默认值: 0 (默认) 不对子文件夹进行递归搜索. 1递归搜索子文件夹, 以便获取包含在其中的匹配 FilePattern 的文件和文件夹. 将递归搜索所有子文件夹, 而不仅是名称匹配 FilePattern 的那些.

可在文件循环中使用的特殊变量

下列变量存在于任何文件循环中. 如果一个内层文件循环包含在一个外层文件循环中, 那么最内层循环的文件将具有优先权:

A_LoopFileName | 当前获取的文件或文件夹的名称 (不含路径).
A_LoopFileExt | 当前文件的扩展名 (例如 TXT, DOC 或 EXE). 不含句点 (.).
A_LoopFileFullPath | 当前获取的文件/文件夹的完整路径和名称. 不过, 如果 FilePattern 包含相对路径而不是绝对路径, 那么这里的路径也将是相对路径. 此外, FilePattern 中的任何短 (8.3) 文件夹名称仍将为短名称 (参见下一项来获取长名称).
A_LoopFileLongPath | 此变量与 A_LoopFileFullPath 有以下不同之处: 1) 不论 FilePattern 包含的是否为相对路径, 它总是包含文件的绝对/完整路径; 2) 在 FilePattern 中的任何短 (8.3) 文件夹名称被转换成它们的长名称; 3) 在 FilePattern 中的字符被转换成与文件系统中存储的名称一致的大小写形式. 把文件名转换为资源管理器中显示的准确路径名称时这很有用, 例如作为命令行参数传递给脚本的那些.
A_LoopFileShortPath

当前获取的文件/文件夹的 8.3 短路径和名称. 例如: C:\MYDOCU~1\ADDRES~1.txt. 不过, 如果 FilePattern 包含相对路径而不是绝对路径, 那么这里的路径也将是相对路径.

要获取单个文件或文件夹的完整的 8.3 路径和名称, 像这个例子那样在 FilePattern 中指定其名称:

Loop, C:\My Documents\Address List.txt
    ShortPathName = %A_LoopFileShortPath%

注意: 如果文件没有短名称, 那么此变量将为 空, 这种情况会发生在注册表中设置了 NtfsDisable8dot3NameCreation 的系统上. 如果 FilePattern 包含相对路径且循环体中使用 SetWorkingDir 从当前循环的有效的工作目录中切换出来, 那么它也将为空.
A_LoopFileShortName | 8.3 短名称或文件的备用名称. 如果文件没有此名称 (由于长名称比 8.3 形式更短或也许因为在 NTFS 文件系统上禁止生成短名称), 将获取 A_LoopFileName 作为代替.
A_LoopFileDir | A_LoopFileName 所在目录的完整路径. 不过, 如果 FilePattern 包含相对路径而不是绝对路径, 那么这里的路径也将是相对路径. 根目录将不包含末尾的反斜线. 例如: C:
A_LoopFileTimeModified | 文件的上次修改时间. 格式为 YYYYMMDDHH24MISS.
A_LoopFileTimeCreated | 文件的创建时间. 格式为 YYYYMMDDHH24MISS.
A_LoopFileTimeAccessed | 文件的上次访问时间. 格式为 YYYYMMDDHH24MISS.
A_LoopFileAttrib | 当前获取的文件的 属性.
A_LoopFileSize | 以字节为单位的当前获取的文件的大小. 同样支持大于 4 GB 的文件.
A_LoopFileSizeKB | 以 KB 为单位的当前获取的文件的大小, 向下取整到最近的整数.
A_LoopFileSizeMB | 以 MB 为单位的当前获取的文件的大小, 向下取整到最近的整数.

备注

当您想对文件和/或文件夹集合中的项逐个进行操作时, 文件循环很有用.

所有匹配的文件都被获取, 包括隐藏文件. 相比之下, 诸如 DIR 命令的 OS 特性默认忽略隐藏文件. 要避免处理隐藏, 系统和/或只读文件, 在循环中使用类似下面的方法:

if A_LoopFileAttrib contains H,R,S  ; 跳过具有 H (隐藏), R (只读) 或 S (系统) 属性的任何文件. 注意: 在 "H,R,S" 中不含空格.
    continue  ; 跳过这个文件并前进到下一个.

要在递归搜索中获取文件的相对路径而不是绝对路径, 在循环之前使用 SetWorkingDir 来改变工作目录为基文件夹, 且在接着的 Loop 中省略路径 (例如 Loop, *.*, 0, 1). 这样将使得 A_LoopFileFullPath 包含相对于基文件夹的文件路径.

如果文件循环在其范围中创建或重命名文件或文件夹, 那么会扰乱它自己. 例如, 如果它通过 FileMove 或其他方法重命名文件, 每个这样的文件可能被找到两次: 一次是作为其旧名称, 再一次则作为其新名称. 要变通解决此问题, 创建需重命名文件的列表后才重命名这些文件. 例如:

FileList =
Loop *.jpg
   FileList = %FileList%%A_LoopFileName%`n
Loop, parse, FileList, `n
   FileMove, %A_LoopField%, renamed_%A_LoopField%

在 NTFS 文件系统中的文件可能总是按字母顺序来获取. 在其他文件系统中的文件则没有特殊的获取顺序. 要使用特殊的获取顺序, 使用 Sort 命令, 如同下文示例部分演示的那样.

文件和文件夹的完整路径和名称超过 259 个字符时, 这些文件和文件夹会被跳过, 就像它们不存在一样. 这样的文件很罕见, 因为操作系统一般不允许创建它们.

参见 Loop 了解关于 区块, Break, Continue, 和 A_Index 变量 (其存在于各种类型的循环中) 的相关信息.

相关

Loop, Break, Continue, 区块, SplitPath, FileSetAttrib, FileSetTime

示例

; 示例 #1:
Loop, %A_ProgramFiles%\*.txt, , 1  ; 递归搜索子文件夹.
{
    MsgBox, 4, , Filename = %A_LoopFileFullPath%`n`nContinue?
    IfMsgBox, No
        break
}

; 示例 #2: 计算文件夹的大小, 包括其所有子文件夹中的文件:
SetBatchLines, -1  ; 让操作以最快速度进行.
FolderSizeKB = 0
FileSelectFolder, WhichFolder  ; 让用户选取文件夹.
Loop, %WhichFolder%\*.*, , 1
    FolderSizeKB += %A_LoopFileSizeKB%
MsgBox Size of %WhichFolder% is %FolderSizeKB% KB.

; 示例 #3: 获取根据名称排序的文件名 (要以日期排序请参见后一个例子):
FileList =  ; 初始为空.
Loop, C:\*.*
    FileList = %FileList%%A_LoopFileName%`n
Sort, FileList, R  ; R 选项使得以逆序排列. 参见 Sort 了解其他选项.
Loop, parse, FileList, `n
{
    if A_LoopField =  ; 忽略列表末尾的空项.
        continue
    MsgBox, 4,, File number %A_Index% is %A_LoopField%.  Continue?
    IfMsgBox, No
        break
}

; 示例 #4: 获取根据修改日期排序的文件名:
FileList =
Loop, %A_MyDocuments%\Photos\*.*, 1
    FileList = %FileList%%A_LoopFileTimeModified%`t%A_LoopFileName%`n
Sort, FileList  ; 根据日期排序.
Loop, parse, FileList, `n
{
    if A_LoopField =  ; 忽略列表末尾的最后一个换行符 (空项).
        continue
    StringSplit, FileItem, A_LoopField, %A_Tab%  ; 用 tab 作为分隔符将其分为两部分.
    MsgBox, 4,, The next file (modified at %FileItem1%) is:`n%FileItem2%`n`nContinue?
    IfMsgBox, No
        break
}

; 示例 #5: 仅复制比目标位置中
; 它们的副本更新的源文件:
CopyIfNewer:
; 调用者已经为我们赋值了变量 CopySourcePattern 和 CopyDest.
Loop, %CopySourcePattern%
{
    copy_it = n
    IfNotExist, %CopyDest%\%A_LoopFileName%  ; 如果目标文件还不存在, 那么总是复制.
        copy_it = y
    else
    {
        FileGetTime, time, %CopyDest%\%A_LoopFileName%
        EnvSub, time, %A_LoopFileTimeModified%, seconds  ; 从目的时间中减去源文件的时间.
        if time < 0  ; 源文件比目的文件更新.
            copy_it = y
    }
    if copy_it = y
    {
        FileCopy, %A_LoopFileFullPath%, %CopyDest%\%A_LoopFileName%, 1   ; 以覆盖形式复制
        if ErrorLevel
            MsgBox, Could not copy "%A_LoopFileFullPath%" to "%CopyDest%\%A_LoopFileName%".
    }
}
Return

; 示例 #6: 把通过命令行参数传递的文件名转换为长名称,
; 完整路径和在文件系统中存储的正确的大写/小写字符形式.
Loop %0%  ; 对于拖放到脚本上 (或作为参数传递) 的每个文件.
{
    GivenPath := %A_Index%  ; 获取下一个命令行参数.
    Loop %GivenPath%, 1
        LongPath = %A_LoopFileLongPath%
    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%
}


Loop (读取文件内容)

逐行读取文本文件的内容, 每次一行 (比 FileReadLine 执行的更好).

Loop, Read, InputFile [, OutputFile]

参数

Read | 此参数必须为单词 READ.
InputFile | 需要在循环中读取内容的文本文件的名称, 如果未指定绝对路径则假定在 %A_WorkingDir% 中. 支持 Windows 和 Unix 格式; 即文件的行结束符可以是回车和换行符 (`r`n) 或只是换行符 (`n).
OutputFile

(可选的) 在循环期间保持打开的文件的名称, 如果未指定绝对路径则假定在 %A_WorkingDir% 中.

在循环体内, 使用仅带一个参数 (写入的文本) 的 FileAppend 命令来追加文本到此指定的文件. 以这种方式追加文本到文件比使用 2 个参数模式的 FileAppend 执行地更好, 因为每次操作时不需要关闭文件再重新打开. 如果需要, 记得在写入的文本后加上换行符 (`n).

如果没有写入内容到此文件, 那么它不会被打开. 当 Loop 的循环次数为零或其循环体中没有使用 FileAppend 命令时会发生这种情况.

二进制模式: 要以二进制模式而不是文本模式追加数据, 在文件名前面加上星号. 这使得每个换行符 (`n) 作为单个换行符 (LF) 而不是 Windows 标准的 CR+LF 写入. 例如: *C:\My Unix File.txt. 即使没有星号, 如果 Loop 中 首次 使用 FileAppend 时写入任何回车和换行符对 (`r`n), 这时二进制模式也会自动生效.

标准输出 (stdout): 指定 OutputFile 为星号 (*) 可以把 FileAppend 写入的任何文本发送到标准输出 (stdout). 尽管这样的输出可以重定向到文件, 指向另一个 EXE 的管道或被 高级文本编辑器 捕获, 然而它不会出现在运行它的命令提示符中. 参见 FileAppend 了解详细信息.

逗号转义: 与其他大多数命令的最后一个参数不同, 在 OutputFile 中的逗号必须进行转义 (`,).

备注

当您想对包含在文本文件中的内容逐行进行操作时, 文件读取循环很有用. 它比 FileReadLine 执行的更好, 因为: 1) 在整个操作过程中文件一直保持打开状态; 2) 不需要每次都重新扫描文件来查找请求的行内容.

内置变量 A_LoopReadLine 存在于任何文件读取循环中. 它包含了已去除行尾的回车换行符 (`r`n) 的当前行内容. 如果一个内层文件读取循环包含在一个外层文件读取循环中, 则最内层循环的文件行将具有优先权.

最大可以读取包含 65,534 字符的长行. 如果某行超出这个长度, 此行的剩余字符将在下一次循环中读取.

经常在文件读取循环中使用 StringSplit 或 解析循环 解析从 InputFile 读取的每行内容. 例如, 如果 InputFile 文件中的各行是由 tab 分隔的片段, 那么可以单独获取这些片段, 例如:

Loop, read, C:\Database Export.txt
{
    Loop, parse, A_LoopReadLine, %A_Tab%
    {
        MsgBox, Field number %A_Index% is %A_LoopField%.
    }
}

要加载整个文件内容到变量中, 使用 FileRead, 因为它比循环执行的更好 (尤其对于大文件).

要同时打开多个文件, 请参考 此例 使用 DllCall().

参见 Loop 了解关于 区块, Break, Continue, 和 A_Index 变量 (其存在于各种类型的循环中) 的相关信息.

在不存在字节顺序标记时要控制如何解码文件, 使用 FileEncoding.

相关

FileEncoding, FileOpen/文件对象, FileRead, FileReadLine, FileAppend, Sort, Loop, Break, Continue, 区块, FileSetAttrib, FileSetTime

示例

; 示例 #1: 在首个文件中只有包含单词 FAMILY 的那些行才会写入第二个文件中.
; 取消注释首行可以覆盖而不追加到任何现有的文件.
;FileDelete, C:\Docs\Family Addresses.txt

Loop, read, C:\Docs\Address List.txt, C:\Docs\Family Addresses.txt
{
    IfInString, A_LoopReadLine, family, FileAppend, %A_LoopReadLine%`n
}

; 示例 #2: 获取文本文件的最后一行.
Loop, read, C:\Log File.txt
    last_line := A_LoopReadLine  ; 当循环结束时, 这里会保持最后一行的内容.

; 示例 #3: 尝试从文本或 HTML 文件中提取
; 所有 FTP 和 HTTP URL 的有效脚本:
FileSelectFile, SourceFile, 3,, Pick a text or HTML file to analyze.
if SourceFile =
    return  ; 此时将退出.

SplitPath, SourceFile,, SourceFilePath,, SourceFileNoExt
DestFile = %SourceFilePath%\%SourceFileNoExt% Extracted Links.txt

IfExist, %DestFile%
{
    MsgBox, 4,, Overwrite the existing links file? Press No to append to it.`n`nFILE: %DestFile%
    IfMsgBox, Yes
        FileDelete, %DestFile%
}

LinkCount = 0
Loop, read, %SourceFile%, %DestFile%
{
    URLSearchString = %A_LoopReadLine%
    Gosub, URLSearch
}
MsgBox %LinkCount% links were found and written to "%DestFile%".
return

URLSearch:
; 由于在一些 URL 中内嵌有其他的 URL, 所以用这种特殊的方法进行处理:
StringGetPos, URLStart1, URLSearchString, http://
StringGetPos, URLStart2, URLSearchString, ftp://
StringGetPos, URLStart3, URLSearchString, www.

; 查找最左边的起始位置:
URLStart = %URLStart1%  ; 设置默认的起始处.
Loop
{
    ; 仅解析 "URLStart%A_Index%" 一次有助于
    ; 改善性能 (尤其在含有许多变量的脚本中):
    ArrayElement := URLStart%A_Index%
    if ArrayElement =  ; 到达数组的末尾.
        break
    if ArrayElement = -1  ; 此元素无效.
        continue
    if URLStart = -1
        URLStart = %ArrayElement%
    else ; URLStart 中含有有效位置, 所以把它与 ArrayElement 进行比较.
    {
        if ArrayElement <> -1
            if ArrayElement < %URLStart%
                URLStart = %ArrayElement%
    }
}

if URLStart = -1  ; 在 URLSearchString 中不存在 URL.
    return

; 否则, 提取此 URL:
StringTrimLeft, URL, URLSearchString, %URLStart%  ; 忽略开始/无关的部分.
Loop, parse, URL, %A_Tab%%A_Space%<>  ; 找到首个空格, tab 或尖括号 (如果有).
{
    URL = %A_LoopField%
    break  ; 即仅执行一次循环来获取首个 "片段".
}
; 如果没有找到结束字符而在上面的循环中没有执行循环体,
; 那么保持 URL 变量的内容不变.

; 如果 URL 以双引号结束, 那么移除它.  暂时使用 StringReplace, 不过注意
; 双引号似乎可以合法存在于 URL 中, 所以这样做
; 可能破坏它们:
StringReplace, URLCleansed, URL, ",, All
FileAppend, %URLCleansed%`n
LinkCount += 1

; 看看当前行中是否含有其他 URL:
StringLen, CharactersToOmit, URL
CharactersToOmit += %URLStart%
StringTrimLeft, URLSearchString, URLSearchString, %CharactersToOmit%
Gosub, URLSearch  ; 到自己的递归调用.
return


SetWorkingDir

更改脚本当前工作目录。

SetWorkingDir, DirName

参数

DirName 工作目录名。如果不使用绝对路径，则被认为是当前工作目录 %A_WorkingDir% 的子目录。

ErrorLevel

如果遇到问题，ErrorLevel/错误级别 被设置为 1 ，否则为 0 。

注意

脚本的工作目录是脚本存取文件和目录时候使用的默认路径。如果存取文件或目录的时候未指定绝对路径，则使用默认路径。例如下面的例子中，文件 My Filename.txt 被存储在 %A_WorkingDir% 指定的目录中：FileAppend, A Line of Text, My Filename.txt

一个脚本的初始工作路径取决于它的启动方式。例如，通过“开始”菜单的快捷方式运行一个脚本的话，它的初始工作目录就是快捷方式属性中“起始位置”所显示的目录。

要让脚本无条件使用它所在的目录为工作目录的话，在脚本第一行写上：
SetWorkingDir %A_ScriptDir%

一旦更改了工作目录，它将立即生效并且影响所有的脚本。对所有的中断，暂停 ，以及新运行的 线程 都有效，包括 定时器 。

相关命令

%A_WorkingDir%, %A_ScriptDir%, FileSelectFolder

示例

SetWorkingDir, D:\My Folder\Temp


SplitPath

将一个文件名或 URL (统一资源定位符)分解成它的名称、目录、扩展名和驱动器。

SplitPath, InputVar [, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive]

参数

InputVar | 包含用来被分析的文件名的变量名称。
OutFileName | 储存不带路径的文件名的变量名称。文件的扩展名包括在内。
OutDir | 储存文件的目录，包括驱动器字母或共享名称(如果有的话)的变量名称。最后的反斜线不被包括在内，即使文件定位在一个驱动器的根目录。
OutExtension | 储存文件的扩展名(例如TXT、DOC 或 EXE)的变量名称。圆点不被包括在内。
OutNameNoExt | 储存不带路径、圆点和扩展名的文件名的变量名称。
OutDrive | 储存文件的驱动器字母或服务器名称的变量名称。如果文件在一个本地或映射驱动器，变量将被设为驱动器字母跟一个冒号(无反斜线)。如果文件在一个网络路径(UNC 通用命名规则)，变量将被设为共享名，例如 \\Workstation01

说明

如果相应的信息不需要，任何一个输出变量可被省略。

如果 InputVar 包含一个缺少驱动器字母的文件名(即它不含路径或仅有一个相对路径)，OutDrive 将为空，但所有其他输出变量将设置正确。同样地，如果不存在路径，OutDir 将为空；如果有一个路径但不存在文件名， OutFileName 和 OutNameNoExt 将为空。

在文件系统里实际的文件和目录不通过此命令核查。它简单地分析在 InputVar 里给出的字串。

在文件名里不合法的通配符(* 和 ?) 以及其他字符将与合法字符一样来对待，除了冒号、反斜线和句号(圆点)，是根据它们在划分驱动器字母、目录和文件扩展名的界限性质来处理的。

对 URLs 的支持: 如果 InputVar 包含一个双斜线，例如 http://domain.com 或 ftp://domain.com，OutDir 将设为协议前缀 + 域名 + 目录 (例如 http://domain.com/images)，OutDrive 将设为协议前缀 + 域名 (例如 http://domain.com)。所有其他变量将根据它们上面的定义来设置。

相关命令

A_LoopFileExt, StringSplit, StringGetPos, StringMid, StringTrimLeft, StringLeft, FileSelectFile, FileSelectFolder

范例

FullFileName = C:\My Documents\Address List.txt

;仅从上面取出单单文件名：
SplitPath, FullFileName, name

; 仅取出它的目录：
SplitPath, FullFileName,, dir

; 取出所有信息：
SplitPath, FullFileName, name, dir, ext, name_no_ext, drive

; 上面这行会将变量如下设置：
; name = Address List.txt
; dir = C:\My Documents
; ext = txt
; name_no_ext = Address List
; drive = C:


#Include

#Include / #IncludeAgain

使得脚本认为指定文件的内容会出现在这个准确的位置.

#Include FileOrDirName
#Include <LibName>
#IncludeAgain FileOrDirName

参数

FileOrDirName

File: 要包含的文件名, 如果未指定绝对路径则假定在启动/工作目录 (除了 ahk2exe, 它会假定文件在脚本自身目录). 文件名 不能 包含变量名称 (除了 %A_ScriptDir%, %A_AppData% 和 %A_AppDataCommon%), 双引号或通配符. 转义序列 除了分号 (`;) 外都不能使用, 它们也不需要, 因为字符如百分号被当成原义处理. 注意: SetWorkingDir 对 #Include 没有效果因为在脚本开始执行前 #Include 就已经处理了.

Directory: 指定一个目录而不是文件从而改变后面所有出现的 #Include 和 FileInstall 使用的工作目录. 目录名不能包含除了 %A_ScriptDir%, %A_AppData% 和 %A_AppDataCommon% 以外的变量. 注意: 以这种方式改变工作目录不会改变脚本开始运行时的初始工作目录 (A_WorkingDir). 要改变初始工作目录, 请在脚本的顶部使用 SetWorkingDir.
LibName [AHK_L 57+]: 库文件或函数名. 例如, #include <lib> 和 #include <lib_func> 都可以包含来自某个 函数库文件夹 的 lib.ahk.

备注

脚本认为包含的文件的内容实际会出现在 #Include 指令的准确位置 (就好像从包含的文件复制粘贴过来一样). 因此, 它通常不能把两个孤立的脚本合并成一个可运行的脚本 (要实现这样的效果, 参见 www.autohotkey.com/forum/topic18545.html).

#Include 确保 FileName 仅被包含一次, 即使它遇到多次重复的包含. 与之相比, #IncludeAgain 则允许多次包含同个文件, 而在所有其他方面于 #Include 一样.

可以在 FileName 参数前加上 *i 和单个空格, 这样会使程序忽略加载包含的文件时产生的任何故障. 例如: #Include *i SpecialOptions.ahk. 此选项应该仅在包含的文件的内容对主脚本的操作可有可无的情况下才使用.

通过 ListLines 或菜单 View->Lines 显示在主窗口的那些行总是按照它们在文件内部的物理顺序编号的. 换句话说, 包含一个新的文件将仅仅改变主脚本文件的一行编号, 即 #Include 所在行 (除了在 已编译脚本, 它会在编译时把它们包含的文件合并成一个大的脚本).

#Include 也常用来加载在外部文件中定义的 函数. 和子程序标签不同, 函数 可以在脚本的顶部包含而不影响 自动执行段.

和其他 # 开头的指令一样, #Include 不能根据条件执行. 换句话说, 这个例子不起作用:

if x = 1
    #Include SomeFile.ahk  ; 不论 x 的值是什么此行都会执行.
    y = 2  ; 而此行属于上面的 IF 语句, 因为 # 指令不属于 IF 语句.

通过调用 库函数 中的函数名称可以自动将文件包含进来 (即不需要使用 #Include).

相关

函数库, 函数, FileInstall

示例

#Include C:\My Documents\Scripts\Utility Subroutines.ahk #Include %A_ScriptDir% ; Changes the working directory for subsequent #Includes and FileInstalls.
#Include C:\My Scripts ; Same as above but for an explicitly named directory.


{...} (区块)

一对大括号组成的区域表示一个区块. 区块通常与 函数, Else, Loop, While 循环 和 IF 命令一起使用.

{
零或多行命令
}

备注

使用区块可以绑定两行或多行命令. 还可以用它改变 IF 与 ELSE 从属关系, 例如在此例中, 区块强制 ELSE 从属于首个 IF 而不是第二个:

if var1 = 1
{
    if var2 = abc
        sleep, 1
}
else
    return

尽管区块可以用在脚本中的任何位置, 不过目前它们仅在与 函数, Else, Loop 或 IF 类型的命令例如 IfEqual 或 IfWinExist 一起使用时才有意义.

如果 IF, ELSE, Loop 或 While 循环 中仅含单行命令, 那么此命令可以不需要括在区块中. 不过, 这样做也许可以提高脚本的可读性和可维护性.

区块中可以为空 (不含任何命令), 当您想注释区块中的内容而不移除区块时这很有用.

One True Brace (OTB, K&R 风格): 在后面的这些位置中可以使用 OTB 风格: 包含表达式的 if 语句, "else" 关键字, while 循环, 普通循环 和 函数定义. 这种风格中区块的开括号与区块的控制语句在同一行, 而不是在其下一行. 例如:

if (x < y) {
    ...
} else {
    ...
}
While x < y {
    ...
}
Loop %RepeatCount% {
    ...
}
MyFunction(x, y) {
    ...
}

同样地, 命令或其他操作可以放在大括号的后面 (但不包括 One True Brace 风格的开括号). 例如:

if x = 1
{ MsgBox This line appears to the right of an opening brace. It executes whenever the IF-statement is true.
    MsgBox This is the next line.
} MsgBox This line appears to the right of a closing brace. It executes unconditionally.

相关

函数, While 循环, Loop, Else, If, If(Expression)

示例

if x = 1
{
    MsgBox, test1
    Sleep, 5
}
else
    MsgBox, test2


Break

退出 (终止) 循环. 在各种 循环 中都是有效的.

Break [, LoopLabel]

[AHK_L 59+]: 如果指定了 LoopLabel, 它确定了此语句应该应用于哪层循环; 通过标签名或嵌套层级的数值. 如果省略或为 1, 此语句应用于它所在的最内层循环. LoopLabel 必须是一个常量; 即不支持变量和表达式.

鼓励使用 Break 和 Continue 代替 goto 因为它们通常让脚本更容易阅读和维护.

相关

Continue, Loop, While 循环, For 循环, 区块

示例

Loop
{
    ...
    if var > 25
        break
    ...
    if var <= 5
        continue
}
; 从内嵌循环内部退出到外层循环.
outer:
Loop 3
{
    x := A_Index
    Loop 3
    {
        if (x*A_Index = 6)
            break outer  ; 等同于 break 2 或 goto break_outer.
        MsgBox %x%,%A_Index%
    }
}
break_outer: ; 用于 goto 命令.


Continue

跳过当前 循环 的剩余部分并继续下一次循环. 在各种 循环 中都是有效的.

Continue [, LoopLabel]

[AHK_L 59+]: 如果指定了 LoopLabel, 它确定了此语句应该应用于哪层循环; 通过标签名或嵌套层级的数值. 如果省略或为 1, 此语句应用于它所在的最内层循环. LoopLabel 必须是一个常量; 即不支持变量和表达式.

Continue 的行为如同直接到达了循环的闭括号:

  1. 它让 A_Index 加 1.
  2. 它跳过了循环体的剩余部分.
  3. 检查循环条件 (如果有的话) 判断是否满足. 如果满足, 开始新的循环; 否则循环结束.

鼓励使用 Break 和 Continue 代替 goto 因为它们通常让脚本更容易阅读和维护.

相关

Break, Loop, Until, While 循环, For 循环, 区块

示例

; 此例显示 5 此MsgBox 消息框, 为从 6 到 10 的每个数字显示一次.
; 注意 Loop 的前 5 次循环, "continue" 命令
; 会使得循环在到达 MsgBox 前重新开始.
Loop, 10
{
    if A_Index <= 5
        continue
    MsgBox %A_Index%
}
; 从内嵌循环内部直接继续新的外层循环.
outer:
Loop 3
{
    x := A_Index
    Loop 3
    {
        if (x*A_Index = 4)
            continue outer  ; 等同于 continue 2 或 goto continue_outer.
        MsgBox %x%,%A_Index%
    }
    continue_outer: ; 用于 goto 命令.
    ErrorLevel:=ErrorLevel ; 在修订号 57 之前, 标签不能指向区块的末尾.
}


Else

假如一个 IF 语句得出 FALSE，则执行指定的命令。当出现多个命令时，将它们括入一个区块(大括号)。

Else

说明

每次使用 ELSE 都要附属于(相关联)它上面的一个 IF 语句。一个 ELSE 总是附属于上面那个距离它最近的未认领的 IF 语句，除非使用了一个区块来改变这种关联。

一个 ELSE 后面能立即被在同一行的其他单个命令跟着。其最常被"else if"梯形结构所使用(详见下面的范例)。

当一个 IF 或一个 ELSE 命令拥有多行，那些行必须被括入大括号。但是如果只有一行属于一个 IF 或一个 ELSE 命令，那么大括号是可选的。例如：

if count > 0  ;不需要在下一行周围使用大括号，因为它只有一行。
    MsgBox 按下确定开始此进程。
else  ;一定要在下面这部分的周围使用大括号，因为它由多行组成。
{
    WinClose 无标题 - 记事本
    MsgBox 当前没有内容。
}

单个正确的大括号(OTB)类型可以选择性地被使用在一个"else"周围。例如：

if IsDone {
    ...
} else if (x < y) {
    ...
} else {
    ...
}

相关命令

详见区块。而且每个 IF 语句都能使用 ELSE，包括 IfWinActive, IfWinExist, IfMsgBox, IfInString, IfBetween, IfIn, IF 和 IF (expression)。

范例

IfWinExist, 无标题 - 记事本
{
    WinActivate
    Send This is a test.{Enter}
}
else
{
    WinActivate, Some Other Window
    MouseClick, left, 100, 200
}

if x = 1
    Gosub, a1
else if x = 2 ; "else if" 类型
    Gosub, a2
else IfEqual, x, 3 ;交替的类型
{
    Gosub, a3
    Sleep, 1
}
else Gosub, a4  ;也就是说任何单个命令都能和一个 ELSE 命令在同一行。

;也可以这样：
IfEqual, y, 1, Gosub, b1
else {
    Sleep, 1
    Gosub, b2
}


Exit

退出 current thread(当 前线程) 或(如果脚本非 persistent 且未包含热键)整个脚本。

Exit [, ExitCode]

参数

ExitCode 一个 integer(整数) (也就是负数、正数、零或者 expression(表达式) ) 在脚本退出时被返回给它的调用者。此退出代码可被任何调用脚本的程序使用，例如另一个脚本(通过 RunWait) 或一个 batch (.bat) file(批处理文件)。如果省略，ExitCode 默认为 0 。0 通常被用来表示成功。注意：Windows 95 可能限制 ExitCode 的大小。

注意

如果脚本没有热键，也不是 persistent， 并且没有要求 Num/Scroll/CapsLock 键保持一直开启或一直关闭，那么当遇到 Exit 时它会立即终止(除非它有一个 OnExit 子程序)。

否则，Exit 命令只终止 current thread(当前线程) 。换句话说，通过 menu 、timer 或热键子程序来直接或间接地调用 stack of subroutines (子程序堆栈)，将好像各自直接地遇上一个 Return 那样全部被返回。如果直接在这样的子程序内部使用 Exit -- 而不是在子程序内间接地被脚本调用 -- Exit 等同于 Return 。

使用 ExitApp 来完全终止一个 persistent 或包含热键的脚本。

相关命令

ExitApp, OnExit, Functions, Gosub, Return, Threads, #Persistent

示例

#z::
Gosub, Sub2
MsgBox, 由于 EXIT，这个消息框将不会弹出。
return

Sub2:
Exit ; 终止子程序，也终止了来调用的热键子程序。


ExitApp

无条件地终止脚本。

ExitApp [, ExitCode]

参数

ExitCode 当脚本退出时返回一个整数(相当于负数、正数或者是零)给它的调用程序。此代码能被任何生成脚本的程序运用，例如另一个脚本(通过 RunWait)或者一个批处理(.bat)文件。如果省略，ExitCode 默认为零。零通常用来表示成功。注意：Windows 95 可能限制了 ExitCode 的大小。

说明

脚本将立即被终止，除非它有一个 OnExit 子程序。这相当于从脚本的托盘菜单或主菜单选择"Exit"。

当脚本没有包含热键，不是持续的，并且没有要求 Num/Scroll/Capslock 键保持一直打开或者一直关闭时，Exit 和 ExitApp 作用相同。

如果脚本有一个 OnExit 子程序，它将响应 ExitApp 而运行。

相关命令

Exit, OnExit, #Persistent

范例

#x::ExitApp  ;指定一个热键来终止此脚本。


For-loop

For-loop [AHK_L 59+]

为对象中的每个键值对重复执行一组命令.

For Key [, Value] in Expression

参数

Key | 保存每次重复开始时的键的变量名称.
 | 保存与当前键关联的值的变量名称.
Expression | 一个结果为对象的 表达式 或包含对象的变量.

备注

表达式 只在循环开始前计算一次. 如果其结果不是对象, 立即跳转到循环体后面的语句执行; 否则, 对象的 _NewEnum() 方法被调用来获取 枚举数 对象. 每次重复开始时, 使用枚举数的 Next() 方法获取下一个键值对. 如果 Next() 返回零或空字符串, 循环终止.

现有的键值对可以在循环中修改, 但插入或移除键可能导致一些项目被跳过或枚举多次. 一种解决方法是建立待移除的键列表, 在首个循环结束后使用第二个循环移除这些键. 请注意 Object.Remove(first, last) 可以不需要循环来移除键的范围.

在修订版本 59 之前的版本中, 可以在 for-loop 的位置使用下列语句:

_enum := (Expression)._NewEnum()
while _enum.Next(Key, Value)
{
    ...
}

for-loop 后通常跟着一个 区块, 这是构成循环 体 的语句的集合. 但是, 只含有单语句的循环不要求使用区块 (为此一个 "if" 和与其匹配的 "else" 计算为单语句). 可以随意的使用 One True Brace (OTB) 风格, 这允许开括号和语句在同一行而不是在下面. 例如: for x, y in z {

和所有的循环一样, 循环中可以使用 Break, Continue 和 A_Index.

COM 对象

因为 Key 和 Value 直接传递给枚举数的 Next() 方法, 它们的值完全取决于枚举数的完成. 对于 COM 对象, Key 包含由 IEnumVARIANT::Next() 返回的值而 Value 包含了表示其 变量类型 的数字. 例如, 用于 Scripting.Dictionary 对象时, 每个 Key 包含了字典中的一个键而 Value 总为 8 (这是 VT_BSTR, 标准的 COM 字符串类型).

相关

枚举数对象, Object.NewEnum(), While-loop, Loop, Until, Break, Continue, Blocks

示例

; List the key-value pairs of an object:
colours := Object("red", 0xFF0000, "blue", 0x0000FF, "green", 0x00FF00)
; The above expression could be used directly in place of "colours" below:
For k, v in colours s .= k "=" v "`n" MsgBox % s

; List all open Explorer and Internet Explorer windows:
for window in ComObjCreate("Shell.Application").Windows windows .= window.LocationName " :: " window.LocationURL "`n" MsgBox % windows


Gosub

跳到指定的标签并且继续执行，直到碰到 Return。

Gosub, Label

参数

Label 跳转的标签名称，热键标签或者热字串标签，它执行 Label 下面的命令，直到碰到一个返回或退出。"Return" 让脚本跳回到 Gosub 下面的首个命令并且在那继续执行。"Exit" 终止当前的线程。

说明

和几乎所有其他命令的参数一样，Label 可以是一个变量引用，例如 %MyLabel%，这时储存在变量中的名称被用来作为目标。然而，性能有略微地损失，因为目标 Label 每次都要“查找”，而不是仅在脚本首次运行时查找一次。

当使用一个动态 Label，例如 %MyLabel%，如果 Label 不存在，将显示一个错误对话框。要避免这种情况，可提前调用 IsLabel()。例如：

if IsLabel(VarContainingLabelName)
    Gosub %VarContainingLabelName%

虽然 Gosub 可用于简单、多用途的子程序，但考虑为更复杂的用途而使用函数。

相关命令

Return, Functions, IsLabel(), Blocks, Loop, Goto

范例

Gosub, Label1
MsgBox, Label1 子程序已经返回（它已结束）。
return

Label1:
MsgBox, Label1 子程序正在运行。
return


Goto

跳转到指定的标签并继续执行。

Goto, Label

参数

Label 要跳转到的标签名称。

注意

当使用一个动态标签比如 %MyLabel% 时，如果标签不存在，将会显示一个错误对话框。要避免这种情况，可事先调用 IsLabel()。例如：

if IsLabel(VarContainingLabelName)
    Goto %VarContainingLabelName%

不鼓励使用 Goto，因为它通常使脚本不太易读并且难以维护。可以考虑使用 Else, Blocks, Break 和 Continue 来代替 Goto。

相关命令

Gosub, Return, IsLabel(), Else, Blocks, Break, Continue

示例

Goto, MyLabel
...
MyLabel:
Sleep, 100
...


If/IfEqual/IfNotEqual/IfLess/IfLessOrEqual/IfGreater/IfGreaterOrEqual

指定在 变量 与值比较结果为 TRUE 时执行的命令. 包含多个命令时, 需要把它们括在 区块 (大括号) 中.

IfEqual, var, value (等同于: if var = value)
IfNotEqual, var, value (等同于: if var <> value) (可以使用 != 代替 <>)
IfGreater, var, value (等同于: if var > value)
IfGreaterOrEqual, var, value (等同于: if var >= value)
IfLess, var, value (等同于: if var < value)
IfLessOrEqual, var, value (等同于: if var <= value)
If var ; 如果变量的内容为空或 0 时, 它被视为 false. 否则它被视为 true.

请参阅: IfInString

参数

var | 变量 名.
value | 文字字符串, 数字或变量引用 (例如 %var2%). 如果您希望将 var 与空字符串 (空白) 进行比较, 那么可以省略 Value.

备注

如果 var 和 value 都为纯数值, 那么它们将被作为数字而不是字符串进行比较. 其他情况下, 它们将被作为字符串按字母顺序进行比较 (即字母次序将决定 var 是大于, 等于或小于 value).

当 IF 或 ELSE 结构中含有多行命令时, 这些命令必须括在大括号中. 例如:

if count <= 0
{
    WinClose Untitled - Notepad
    MsgBox There are no items present.
}

不过, 如果只有一行命令从属于 IF 或 ELSE, 那么可以不用大括号.

如果您使用命令名称风格, 那么另一个命令只能与 IF 语句在同一行. 换句话说, 这些语句都是有效的:

IfEqual, x, 1, Sleep, 1
IfGreater, x, 1, EnvAdd, x, 2

但这些是无效的:

if x = 1 Sleep 1
IfGreater, x, 1, x += 2

One True Brace (OTB) 风格 不 能用在 if 语句的这些类型中. 它只能和表达式类型的 if 语句一起使用.

相关提示, "if var [not] between LowerBound and UpperBound" 命令判断变量是否在两个值之间, 而 "if var [not] in value1,value2" 可以用来判断变量内容是否存在于值列表中.

相关

IF (表达式), StringCaseSense, 赋值表达式 (:=), if var in/contains MatchList, if var between, IfInString, 区块, Else

示例

if counter >= 1
    Sleep, 10

if counter >=1   ; 如果 IF 结构中含有多行命令, 那么这些命令必须括在大括号中:
{
    WinClose, Untitled - Notepad
    Sleep 10
}

if MyVar = %MyVar2%
    MsgBox The contents of MyVar and MyVar2 are identical.
else if MyVar =
{
    MsgBox, 4,, MyVar is empty/blank. Continue?
    IfMsgBox, No
        Return
}
else if MyVar <> ,
    MsgBox The value in MyVar is not a comma.
else
    MsgBox The value in MyVar is a comma.

if Done
    MsgBox The variable Done is neither empty nor zero.


if (表达式)

指定在 表达式 计算结果为 TRUE 时执行的命令.

if (expression)

备注

包含表达式的 if 语句与像 If FoundColor <> Blue 这样的 传统 if 语句 的区别是, 它在单词 "if" 后的字符为左大括号. 尽管这通常是通过把整个表达式括在大括号中实现的, 不过也可以用类似 if (x > 0) and (y > 0) 这样的形式. 此外, 如果单词 "if" 后是 函数调用 或者类似 "not" 或 "!" 的运算符, 那么左大括号可以完全省略.

如果 if 语句中表达式的计算结果为 true (即除空字符串和数值 0 以外的任何结果), 那么执行 if 语句下的行或 区块. 否则如果有相应的 ELSE, 则会跳到 else 下的行或区块执行.

当 IF 或 ELSE 结构中含有多行命令时, 这些命令必须括在 大括号 中. 不过, 如果只有一行命令从属于 IF 或 ELSE, 那么可以不用大括号. 参见此页面底部的例子.

One True Brace (OTB) 风格可用于表达式形式的 if 语句中 (但不能用于 传统的 if 语句). 例如:

if (x < y) {
    ...
}
if WinExist("Untitled - Notepad") {
    WinActivate
}
if IsDone {
    ...
} else {
    ...
}

与 "else" 语句支持任何类型的语句紧跟在其右边不同, if 语句仅支持 "{" 在其右边.

相关提示, "if var [not] between LowerBound and UpperBound" 命令判断变量是否在两个值之间, 而 "if var [not] in value1,value2" 可以用来判断变量内容是否存在于值列表中.

相关

表达式, 赋值表达式 (:=), if var in/contains MatchList, if var between, IfInString, 区块, Else, While 循环

示例

if (A_Index > 100 or Done)
    return

if (A_TickCount - StartTime > 2*MaxTime + 100)
{
    MsgBox Too much time has passed.
    ExitApp
}

if (Color = "Blue" or Color = "White")
{
    MsgBox The color is one of the allowed values.
    ExitApp
}
else if (Color = "Silver")
{
    MsgBox Silver is not an allowed color.
    return
}
else
{
    MsgBox This color is not recognized.
    ExitApp
}


Loop

Loop (普通)

重复执行一系列命令: 可以指定表示重复次数的数字或直到遇到 break.

Loop [, Count]

参数

Count

执行循环体 (重复) 的次数. 如果省略, Loop 会无期限继续, 直到遇到 break 或 return.

如果 Count 是一个变量引用例如 %ItemCount%, 每当此变量为空或包含小于 1 的数字时, 循环会被完全跳过.

由于必须支持 文件模式循环, Count 不可以为表达式. 不过, 和所有的非表达式参数一样, 通过在表达式之前加上 % 和空格可以强制使用它. 例如: Loop % Count + 1. 此时, 表达式仅在循环开始之前被求值一次.

备注

循环命令后通常跟着 区块, 这是组成循环 体 的语句的集合. 不过, 在单语句的循环中可以不使用区块 (用于此目的时 "if" 与其相匹配的 "else" 一起被视为单语句).

此命令的常见用途是无限循环, 在循环 体 中某个地方使用 break 命令来决定何时停止循环.

在循环中鼓励使用 break 和 continue 代替 goto, 因为它们通常可以让脚本更容易理解和维护. 要创建 "Do...While" 循环, 在循环 体 的最后一个语句中使用 IF 语句, 在其中根据条件执行 break 命令. 可以使用相同的方法创建 "While" 循环, 但是应该使用 While 命令代替.

内置变量 A_Index 包含当前循环重复的次数. 首次执行循环 体 时其值为 1. 第二次时其值为 2; 依此类推. 如果一个内层循环包含在一个外层循环中, 那么内层循环具有优先权. A_Index 在所有类型的循环中都有效, 包括 文件循环 和 注册表循环; 但是在循环外部时 A_Index 值为 0.

在普通循环中可以使用 One True Brace (OTB) 风格 (但不适用于专用循环例如 文件模式 和 解析). 例如:

Loop {
    ...
}
Loop %RepeatCount% {
    ...
}

专用循环: 循环可以用来自动获取文件, 文件夹或注册表项 (每次一个). 参见 文件循环 和 注册表循环 了解详细信息. 此外, 文件读取循环 可以对整个文件的内容进行操作, 每次一行. 最后, 解析循环 可以对包含在可分隔的字符串中的单独片段进行操作.

相关

Until, While 循环, For 循环, 文件和文件夹循环, 注册表循环, 文件读取循环, 解析循环, Break, Continue, 区块

示例

Loop, 3
{
    MsgBox, Iteration number is %A_Index%.  ; A_Index 将为 1, 2, 接着 3
    Sleep, 100
}

Loop
{
    if a_index > 25
        break  ; 终止循环
    if a_index < 20
        continue ; 跳过后面并开始下一次重复
    MsgBox, a_index = %a_index% ; 这里将仅显示数字 20 到 25
}


Loop (解析字符串)

从一个字符串中获取子字符串 (片段), 每次一个.

Loop, Parse, InputVar [, Delimiters, OmitChars]

参数

Parse 此参数必须为单词 PARSE, 且与其他循环类型不同, 它不能为包含单词 PARSE 的变量引用.
InputVar

需要被解析的变量名称. 不要把名称括在百分号中, 除非您希望使用变量的 内容 作为被解析的变量名.
Delimiters

如果此参数为空或省略, 那么将把 InputVar 中的每个字符解析为单独的子字符串.

如果此参数为 CSV, 那么将把 InputVar 按逗号分隔值格式标准进行解析. 这是一个由 MS Excel 生成的 CSV 格式行的示例: "first field",SecondField,"the word ""special"" is quoted literally",,"last field, has literal comma"

其他情况下, Delimiters 中可以包含一个或多个字符 (区分大小写), 其中的每个都被用来确定 InputVar 中子字符串之间的边界.

分隔符不会被视为子字符串自身的一部分. 此外, 在 InputVar 中如果一对分隔符之间没有任何字符, 那么相应的子字符串将为空.

例如: `, (转义的逗号) 将根据逗号每次出现的位置分割字符串. 同样地, 使用 %A_Tab%%A_Space% 作为分隔符将在 InputVar 中每次遇到空格或 tab 时开始一个新的子字符串.

要使用字符串而不是字符作为分隔符, 首先使用 StringReplace 把这个字符串在所有出现的地方替换为文本中从未使用的单个字符, 例如这些特殊字符的其中一个: ¢¤¥¦§©ª«®µ¶. 参考这个例子, 其中使用字符串 <br> 作为分隔符:

StringReplace, NewHTML, HTMLString, <br>, ¢, All
Loop, parse, NewHTML, ¢ ; 使用 ¢ 解析字符串.
{
...
}
OmitChars

可选的字符列表 (区分大小写), 用于从每个子字符串的开始和结尾部分移除这些字符. 例如, 如果使用 OmitChars is %A_Space%%A_Tab%, 每个解析出来的子字符串中开始和结尾部分 (但中间的不会) 的空格和 tab 将被移除.

如果 Delimiters 为空, 那么 OmitChars 表示应该考虑移除哪些字符 (它们将不会出现在循环中).

与其他大多数命令的最后一个参数不同, 在 OmitChars 中的逗号必须进行转义 (`,).

备注

当您想对包含在字符串中的片段逐个进行操作时, 字符串解析循环很有用. 解析循环比 StringSplit 使用更少的内存 (因为 StringSplit 创建了持久的数组) 且在大多数情况下更容易使用.

内置变量 A_LoopField 存在于任何解析循环中. 它包含了 InputVar 中当前子字符串 (片段) 的内容. 如果一个内层解析循环包含在一个外层解析循环中, 则最内层循环的片段将具有优先权.

尽管不存在内置变量 "A_LoopDelimiter", 不过在此页面最底部的例子演示了如何检测在分割每个片段时是由于遇到哪个分隔符.

InputVar 或其片段没有大小限制. 此外, 如果 InputVar 的内容在循环执行期间改变了, 循环将 "无视" 这些变化, 因为它正在操作的是原始内容的临时副本.

要在解析前按不同的顺序排列字段, 使用 Sort 命令.

参见 Loop 了解关于 区块, Break, Continue, 和 A_Index 变量 (其存在于各种类型的循环中) 的相关信息.

相关

StringSplit, 文件读取循环, Loop, Break, Continue, 区块, Sort, FileSetAttrib, FileSetTime

示例

; 示例 #1:
Colors = red,green,blue
Loop, parse, Colors, `,
{
    MsgBox, Color number %A_Index% is %A_LoopField%.
}

; 示例 #2: 按行读取变量的内容, 一行接一行 (类似于 文件读取 循环).
; 通过 FileRead 可以把文件加载到变量中:
Loop, parse, FileContents, `n, `r  ; 在 `r 之前指定 `n, 这样可以同时支持对 Windows 和 Unix 文件的解析.
{
    MsgBox, 4, , Line number %A_Index% is %A_LoopField%.`n`nContinue?
    IfMsgBox, No, break
}

; 示例 #3: 除了用于剪贴板外, 这个例子和上一个一样.
; 每当剪贴板包含文件时这个例子很有用, 例如从打开的资源管理器窗口
; 复制的那些 (程序自动把这些文件转换为它们的文件名):
Loop, parse, clipboard, `n, `r
{
    MsgBox, 4, , File number %A_Index% is %A_LoopField%.`n`nContinue?
    IfMsgBox, No, break
}

; 示例 #4: 解析逗号分隔值 (CSV) 文件:
Loop, read, C:\Database Export.csv
{
    LineNumber = %A_Index%
    Loop, parse, A_LoopReadLine, CSV
    {
        MsgBox, 4, , Field %LineNumber%-%A_Index% is:`n%A_LoopField%`n`nContinue?
        IfMsgBox, No
            return
    }
}

; 下面的例子类似于解析循环, 不过它还提供了识别
; 遇到了哪个分隔符.

; 初始化待搜索字符串.
Colors = red,green|blue;yellow|cyan,magenta
; 初始化开始搜索时基于零的偏移.
field_begin := 0
; 初始化分隔符.
delimiters = ,|;
Loop
{
    ; 找到下一个分隔符的基于零的索引, 相对于当前片段的起始处.
    field_length := DllCall("shlwapi\StrCSpn", "uint", &Colors + field_begin, "uint", &delimiters, "uint")
    ; 从输入字符串中提取片段.
    field := SubStr(Colors, field_begin + 1, field_length)
    ; 从输入字符串中提取分隔符.
    delimiter := SubStr(Colors, field_begin + field_length + 1, 1)

    MsgBox % "field: " field "`ndelimiter: " delimiter

    ; 如果分隔符为空, 那么 StrCSpn 到达了输入字符串的末尾.
    if delimiter =
        break
    ; 增加到下一个片段的开始处.
    field_begin += field_length + 1
}


Loop (注册表)

获取指定的注册表子键的内容, 每次一个项目.

Loop, RootKey [, Key, IncludeSubkeys?, Recurse?]

参数

RootKey | 必须为 HKEY_LOCAL_MACHINE (或 HKLM), HKEY_USERS (或 HKU), HKEY_CURRENT_USER (或 HKCU), HKEY_CLASSES_ROOT (或 HKCR) 或 HKEY_CURRENT_CONFIG (或 HKCC) 的其中一个. 要访问远程注册表, 在前面加上计算机名和冒号, 例如: \\workstation01:HKEY_LOCAL_MACHINE
Key | 键名 (例如 Software\SomeApplication). 如果为空或省略, 将获取 根键 的内容.
IncludeSubkeys? | 0 (默认值) 不获取 Key 中包含的子键 (仅获取值). 1获取所有的值和子键. 2仅获取子键 (不获取值).
Recurse? | 0 (默认值) 不对子键进行递归. 1对子键进行递归, 以便获取包含在其中的所有值和子键.

备注

当您想对注册表值或子键集合中的项逐个进行操作时, 注册表循环很有用. 值和子键以逆序获取 (自下而上), 这样在循环中使用 RegDelete 不会扰乱循环自身.

下列变量存在于任何注册表循环中. 如果一个内层注册表循环包含在一个外层注册表循环中, 那么最内层循环的注册表项将具有优先权:

A_LoopRegName | 当前获取项的名称, 可以是值名或子键名. 在 Windows 注册表编辑器中, 值名为 "(默认)" 的项如果分配了值, 那么也会获取它的值, 不过此时相应的 A_LoopRegName 将是空的.
A_LoopRegType | 当前获取项的类型, 可以是下列单词的其中之一: KEY (即当前获取项为子键而不是值), REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD, REG_QWORD, REG_BINARY, REG_LINK, REG_RESOURCE_LIST, REG_FULL_RESOURCE_DESCRIPTOR, REG_RESOURCE_REQUIREMENTS_LIST, REG_DWORD_BIG_ENDIAN (在大多数 Windows 硬件上相当罕见). 如果当前获取项为未知类型, 那么此变量将为空.
A_LoopRegKey | 正在访问的根键名 (HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT 或 HKEY_CURRENT_CONFIG). 访问远程注册表时, 此变量的值将 不 包含计算机名.
A_LoopRegSubKey | 当前子键名. 如果没有使用 Recurse 参数以递归查询其他子键时, 此变量的值与 Key 参数相同. 在递归查询时, 此变量的值将为当前获取项的完整路径, 其中不包含根键. 例如: Software\SomeApplication\My SubKey
A_LoopRegTimeModified | 当前子键或其中任何一个值的上次修改时间. 格式为 YYYYMMDDHH24MISS. 当前获取项不是子键 (即 A_LoopRegType 不是单词 KEY) 或操作系统为 Win9x (因为 Win9x 不记录这个信息) 时, 此变量将为空.

在注册表循环中使用下列命令时, 可以以一种简化的方式来操作当前获取项:

RegRead, OutputVar | 读取当前项. 如果当前项为键, ErrorLevel 将被置为 1 且 OutputVar 将被置空.
RegWrite [, Value] | 写入到当前项. 如果省略 Value, 根据不同的类型当前项可能被置为 0 或空. 如果当前项为键, ErrorLevel 将被置为 1 且没有其他效果.
RegDelete | 删除当前项. 如果当前项为键, 它以及它所包含的所有子键和值都将被删除.

访问远程注册表时 (通过上面描述的 RootKey 参数), 需要注意以下事项:

  • 目标机器上必须正在运行远程注册表服务或 (对于 Windows Me/98/95) 安装了微软远程注册表服务 (这个可以从微软获取).
  • 如果您和目标计算机不在相同的域或本地或远程用户名缺乏足够的权限 (然而, 参见下文了解可能的解决方法) 时, 访问远程注册表可能失败.
  • 在尝试访问远程注册表之前, 根据您的用户名所在的域, 工作组和/或权限, 您可能必须连接到共享设备, 例如通过映射驱动器. 建立这样的连接 -- 使用拥有访问或编辑注册表权限的远程用户名和密码 -- 也许可以顺带启用远程注册表访问.
  • 如果您已经作为另一个用户连接到目标计算机 (例如, 通过 Guest 用户映射驱动器), 您可能必须终止这个连接, 以允许远程注册表功能使用您当前登录的用户名重新连接和认证.
  • 对于 Windows Server 2003 和 Windows XP 专业版, MSDN 中声明: "如果 [注册表服务器] 所在的计算机加入了工作组且启用了 强制以本地账户的来宾身份进行网络登录验证 策略, 此功能无效. 请注意如果计算机加入了工作组, 那么这项策略默认是启用的."
  • 对于 Windows XP 家庭版, MSDN 中声明 "此功能总是无效". 家庭版没有注册表服务器和客户端, 尽管客户端可以从操作系统的某个 cab 压缩包提取.

参见 Loop 了解关于 区块, Break, Continue, 和 A_Index 变量 (其存在于各种类型的循环中) 的相关信息.

相关

Loop, Break, Continue, 区块, RegRead, RegWrite, RegDelete

示例

; 示例: 删除用户输入的 Internet Explorer URL 历史:
Loop, HKEY_CURRENT_USER, Software\Microsoft\Internet Explorer\TypedURLs
    RegDelete

; 示例: 有效的测试脚本:
Loop, HKEY_CURRENT_USER, Software\Microsoft\Windows, 1, 1
{
    if a_LoopRegType = key
        value =
    else
    {
        RegRead, value
        if ErrorLevel
            value = *error*
    }
    MsgBox, 4, , %a_LoopRegName% = %value% (%a_LoopRegType%)`n`nContinue?
    IfMsgBox, NO, break
}

; 示例: 用于在整个注册表中
; 递归搜索特殊值的有效例子.
SetBatchLines -1  ; 让搜索以最快速度进行.
RegSearchTarget = Notepad  ; 告知子程序搜索的目标.
Gosub, RegSearch
return

RegSearch:
ContinueRegSearch = y
Loop, HKEY_LOCAL_MACHINE, , 1, 1
{
    Gosub, CheckThisRegItem
    if ContinueRegSearch = n ; 这里告知我们要停止搜索.
        return
}
Loop, HKEY_USERS, , 1, 1
{
    Gosub, CheckThisRegItem
    if ContinueRegSearch = n ; 这里告知我们要停止搜索.
        return
}
Loop, HKEY_CURRENT_CONFIG, , 1, 1
{
    Gosub, CheckThisRegItem
    if ContinueRegSearch = n ; 这里告知我们要停止搜索.
        return
}
; 请注意: 我认为如果已经搜索了 HKEY_USERS, 那么可以不必搜索
; HKEY_CURRENT_USER.  同样地, 如果搜索了 HKEY_LOCAL_MACHINE,
; 那么可以不必搜索 HKEY_CLASSES_ROOT.
return

CheckThisRegItem:
if A_LoopRegType = KEY  ; 如果您也想检查键名, 那么移除这两行.
    return
RegRead, RegValue
if ErrorLevel
    return
IfInString, RegValue, %RegSearchTarget%
{
    MsgBox, 4, , The following match was found:`n%A_LoopRegKey%\%A_LoopRegSubKey%\%A_LoopRegName%`nValue = %RegValue%`n`nContinue?
    IfMsgBox, No
        ContinueRegSearch = n  ; 告知我们的调用者停止搜索.
}
return


Until

Until [AHK_L 59+]

根据条件判断是否继续执行 Loop 或 For 循环.

Loop {
    ...
} Until Expression

参数

Expression 任何有效的 表达式.

备注

在每次重复执行后都会计算一次表达式, 即使使用了 continue 也会进行计算. 如果表达式计算结果为 false (即为空字符串或数值 0), 循环继续; 否则循环被打破且跳到 Until 之后一行执行.

Loop Until 是下列结构的简写形式:

Loop {
    ...
    if (Expression)
        break
}

不过, Loop Until 通常更容易理解, 且与上面不同的是, 它还可以使用单行动作. 例如:

Loop
    x *= 2
Until x > y

Until 可以使用在任何 Loop 或 For 循环中. 例如:

Loop, Read, %A_ScriptFullPath%
    lines .= A_LoopReadLine . "`n"
Until A_Index=5  ; 读取前五行.
MsgBox % lines

如果 A_Index 用在 Expression 中, 那么它的值为刚结束的那次循环的索引.

相关

Loop, While 循环, For 循环, Break, Continue, 区块, 文件和文件夹循环, 注册表循环, 文件读取循环, 解析循环, If (表达式)


OnExit

指定一个 子程序 在脚本退出时自动运行.

OnExit [, Label]

参数

Label 如果省略, 脚本将返回到正常的退出行为. 否则, 指定标签的名称, 当脚本由于任意原因退出时标签的内容将被执行 (作为一个新 thread/线程) .

重要提示:因为指定的子程序被调用而没有终止该脚本, 想要终止脚本则该子程序必须使用ExitApp命令.可选的 (如同下面的示例那样), OnExit 子程序会显示一个 MsgBox 消息框提示用户确认 -- 只有当用户按下 YES/是 按钮才会执行 ExitApp 命令退出脚本.

备注

当脚本由于任意原因退出时 OnExit 子程序会被调用 (除非脚本是被像结束任务这样杀掉). 每当 #SingleInstance 和 Reload 命令要求终止前一个实例时,子过程也会被调用.

通过 OnMessage(0x11, "WM_QUERYENDSESSION") 脚本可以检测并且可以终止系统关闭或注销操作.

OnExit thread/线程 不服从于 #MaxThreads (需要时它总是会运行). 此外, 当它运行的时候, 它不会被任何其他 线程 中断, 包括 热键, 自定义菜单项, 和 定时执行的子程序. 然而, 如果用户在托盘菜单或主菜单中选择Exit , 或者通过 Reload 或 #SingleInstance 命令要求脚本终止时, 它将会终止执行 (同时脚本将退出). 因此, OnExit 子程序应该设计成快速结束除非用户明白自己正在做什么.

如果 OnExit thread 遇到诸如运行时错误的失败状况, 脚本将终止. 这样可以避免有问题的 OnExit 子程序使得脚本无法终止的情况出现.

如果 OnExit 子程序是由指定退出码的 Exit 或 ExitApp 命令运行的, 退出码被忽略. OnExit 子过程通过 ExitApp命令可以指定一个新的退出码.

每当脚本退出尝试调用 OnExit 子过程时, 这时开启了所有命令的默认设置, 例如 SendMode命令. 这些默认值可以通过 auto-execute section改变.

内置变量 A_ExitReason 为空, 除非 OnExit 子过程正在运行或者在之前的退出中至少调用一次.. 如果不是空的, 它将被设为下列单词中的一个:

Logoff | 用户正在注销.
Shutdown | 系统将被关闭或重启, 例如通过 Shutdown 命令.
Close | 脚本接收到 WM_CLOSE 或 WM_QUIT 消息, 出现一个致命错误, 或者被以其他方式关闭. 尽管这些情况都是很少见的, WM_CLOSE 消息可能是由脚本主窗口使用的 WinClose 命令发出的. 为了避免这种情况, 通过 Send, !{{/0}F4} 命令关闭主窗口.
Error | 在一个没有热键并且不是 持续 运行的脚本中发生了运行时错误. 运行时错误的一个例子是 Run/RunWait 命令无法运行指定的程序或打开指定的文档.
Menu | 用户在主窗口的菜单或标准托盘菜单中选择了退出.
Exit | 使用了 Exit 或 ExitApp 命令 (包括 自定义菜单项).
Reload | 脚本被 Reload 命令或菜单项重载.
Single | 由于 #SingleInstance 命令的结果, 脚本被它自身的一个新实例代替.

相关

OnMessage(), RegisterCallback(), OnClipboardChange, ExitApp, Shutdown, #Persistent, Threads, Gosub, Return, Menu

示例

#Persistent  ; For demonstration purposes, keep the script running if the user chooses "No".
OnExit, ExitSub
返回
ExitSub:
if A_ExitReason not in Logoff,Shutdown  ; Avoid spaces around the comma in this line.
{
    MsgBox, 4, , Are you sure you want to exit?
    IfMsgBox, No
返回}
ExitApp  ; The only way for an OnExit script to terminate itself is to use ExitApp in the OnExit subroutine.


Pause

暂停脚本的 current thread(当前线程) 。

Pause [, On|Off|Toggle, OperateOnUnderlyingThread?]

参数

On|Off|Toggle | 如果留空或省略，它默认为 Toggle 。否则，指定为下列一个单词： Toggle: 暂停 current thread 除非它下面的线程已经暂停，这种情况下将反暂停下面的线程。 On: 暂停当前线程。 Off: 如果当前线程下面的线程已经暂停，当它恢复时将成为一种反暂停状态。反之，命令无效。
OperateOnUnderlyingThread? | 此参数被 "Pause Off" 忽略。对上面参数的其他两种而言，它也被忽略除非暂停已经被开启(包括凭借 Toggle 开启的)。 指定下面的一个数字： 0 (或者省略): 命令暂停当前线程；也就是，正在运行暂定命令的线程。 1: 命令标记当前线程下面的线程为暂定，以便当它恢复时，完成它运行的命令(如果有的话)并且之后进入一个暂停状态。如果当前线程下面没有线程，脚本自己会暂停，这将阻止 timers 运行(当脚本没有线程时，这个效果和使用了菜单项 "Pause Script" 一样)。

注意

和 Suspend 不同 -- 它禁用了 hotkeys 和 hotstrings -- pause 将冻结 current thread 。作为一个副作用，任何当前线程下面被中断的线程也将潜伏着。

在任何线程被暂停时，timers 也不会运行。相比之下，明确地启动的线程例如 hotkeys 和 menu items 仍能被运行；但当它们的 threads 结束时，下面的线程仍将被暂停。换言之，每个独立于其他的线程能被暂停。

当脚本的 current thread 处于一个暂停状态时，托盘图标的颜色从绿色转为红色。这个颜色的改变能够通过冻结图标来避免，其通过为 Menu 命令的最后一个参数指定 1 来获得。例如：
Menu, Tray, Icon, C:\My Icon.ico, , 1

要禁用 timers 而不暂停脚本，使用 "Thread, NoTimers" 。

Pause 命令在功能上和内置菜单项 "Pause Script" 相似。

当一个脚本显示任何种类的 menu (tray menu, menu bar, GUI context menu 等等) 时，它总会停住(虽然不是正式地暂停)。

相关命令

Suspend, Menu, ExitApp, Threads, SetTimer

示例

Pause::Pause  ; 给 "pause" 键指定暂停切换功能...
#p::Pause  ; ... 或为 Win+p 或者其他一些热键指定此功能。


Return

从一个子程序返回至先前通过 函数调用、Gosub、热键 激活、GroupActivate 或者其他方法执行的跳转。

Return [, Expression]

参数

Expression

除了当 return 被用在一个 函数 内的时候外，此参数应该被省略。

由于此参数是一个 表达式，下面所有的都是有效的例子：

return 3
return "literal string"
return MyVar
return i + 1
return true  ; 返回数字1来表示 "true"。
return ItemCount < MaxItems  ; 返回一个 true(真) 或者 false(假) 的值。
return FindColor(TargetColor)

已知的限制：为了反向兼容性和易用性，下面两个例子是同等功能的：

return MyVar
return %MyVar%

换句话说，单独括在百分号里的变量被看成一个非表达式。要解决这种情况， 通过将其用圆括号括起来使它明确地作为一个表达式； 例如： return (%MyVar%)

说明

如果没有调用者可返回，Return 将做一个 Exit 动作来代替。

相关命令

Functions, Gosub, Exit, ExitApp, GroupActivate

范例

#z::
MsgBox Win-Z 热键已被按下。
Gosub MySubroutine
return

MySubroutine:
Sleep 1000
return


SetBatchLines

决定脚本的执行速度（影响cpu占用）。

SetBatchLines, 20ms
SetBatchLines, LineCount

参数

20ms | （ 20ms 只是举一个例子。）如果这个参数以 ms 结尾，它表示脚本每两次休眠之间的时间间隔（每次休眠 10ms）。在下面的例子中，设置脚本每执行 20ms 之后休眠 10ms ：SetBatchLines, 20ms
LineCount | 两次休眠之间执行脚本的行数。这个参数最大可以到 9223372036854775807 。但是，这个参数和上面那个参数是互相冲突的；也就是说，同时只有一个参数有效。

注意

使用 SetBatchLines -1 让脚本无休眠地执行（换句话说，也就是让脚本全速运行）。

如果没有使用这个命令：

  • AutoIt v2 （.aut）的脚本默认使用 SetBatchLines 1 ，每执行一行脚本休眠一次。
  • 其它类型的脚本（例如.ahk）默认使用 SetBatchLines 10ms 。不过在 v1.0.16 之前的版本中，默认使用的是 SetBatchLines 10 。

不论是注重脚本执行速度还是注重cpu占用，都推荐使用带“ms”的参数。例如，在大多数的系统中，设置 10ms 的休眠间隔可以让脚本占用不超过 50% 的cpu资源。这样不但让脚本快速执行，也可以保留充分的cpu资源让其它任务使用，例如游戏或者视频捕捉、回放。

内置变量 A_BatchLines 保存了当前设置。

在特定的脚本中，脚本的执行速度同时还受这些命令影响：SetWinDelay ，SetControlDelay ，SendMode ，SetKeyDelay ，SetMouseDelay 以及 SetDefaultMouseSpeed 。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将该命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

SetWinDelay, SetControlDelay, SendMode, SetKeyDelay, SetMouseDelay, SetDefaultMouseSpeed, Critical

示例

SetBatchLines, 10ms
SetBatchLines, 1000


SetTimer

以一个指定的时间间隔来自动重复地启动子程序。

SetTimer, Label [, Period|On|Off, Priority]

参数

Label 欲跳转的标签或热键标签的名称，它使 Lable 下面的命令被执行直到遇上 Return 或 Exit。与几乎所有其他命令的参数一样，Label 可以是一个变量引用比如 %MyLabel%，在这种情况下变量中存储的名称会被作为目标使用。
Period|On|Off

On: 重新启用一个在它的先前 period (周期)中被禁用的定时器。如果不存在定时器，则创建它(默认周期为 250)。如果存在定时器但先前被设置成了 run-only-once 模式，它仍然只运行一次。

Off: 禁用一个已存在的定时器。

Period: 使用这个参数作为 Label 子程序上一次开始后必须经过的近似 毫秒数来创建或更新一个定时器。在这段时间过后，将再次运行 Label （除非它仍在继续上一次运行）。定时器将被自动启用。要防止这种情况，可以随后立即再一次调用此命令，将此参数指定为 OFF。

如果此参数为空并且:
1) 定时器不存在：那么将创建一个周期为 250 的定时器。
2) 定时器已存在：那么将启用定时器，并重设它先前的 period，除非指定了 Priority。

Run only once [v1.0.46.16+]: 用一个负的 Period 来表示定时器只能运行一次。例如，指定 -100 将在 100ms 后运行定时器，然后就像使用了 SetTimer, Label, Off 那样禁用定时器。
Priority

这个可选参数是一个介于 -2147483648 和 2147483647 之间的整数（或一个表达式），用来表示此定时器的线程优先级。如果省略将视为 0。详见线程。

要改变一个已有定时器的优先级而不在任何其他方面影响它，只要将此参数前面的那些参数都留空。

注意

定时器很有用，因为它们是异步运行的，这意味着即使当脚本正在等待一个窗口，显示一个对话框，或忙于其他任务时，定时器也将按指定的频率（间隔）运行。它们的许多应用实例包括当用户闲置时(如 %A_TimeIdle% 反映的那样)采取某些行动或者在不需要的窗口出现时关闭它们。

尽管定时器会给人以脚本同时运行多个任务的错觉，但实际并非如此。而是定时的子程序被作为其他线程来处理：它们能中断别的线程或被另一个线程打断，比如热键子程序。详见线程。

无论一个定时器是被创建，重新启用，还是更新为一个新的 period，其子程序都不会马上运行；它的 period 时间必须先到期。如果你想让定时器的首次执行马上开始，可用 Gosub 来执行定时器的子程序（不过这种方式不会像定时器自身那样开启一个新线程；所以像 SendMode 这样的设置就不会以它们的默认值启动了）。

如果 SetTimer 被用在一个已存在的定时器上且第二个参数是一个数字或单词 ON(或它被省略)，定时器内部的“上次被运行时间”将被重置为当前时间；换句话说，必须在定时器经过它的整个周期后，其子程序才会再次运行。

定时器精度: 由于操作系统的时间记录系统的间隔原因, 周期 通常最接近10或15.6毫秒的倍数(取决于硬件和安装的驱动)。比如，一个在1和10之间(包括10)的周期在Windows NT/2000/XP下通常等于10或15.6(Windows 9x下约为55ms)。通过Loop+Sleep可以获得更短的延时，请看示例：DllCall+timeBeginPeriod+Sleep.

定时器在下列情况中可能无法按指定频率运行：

  1. 其它应用程序使 CPU 负担过重。
  2. 定时器的子程序本身花费了比它的周期更长的时间来运行，或有太多相抵触的定时器（调整 SetBatchLines 可能会有所帮助）。
  3. 定时器被另一个线程，即另一个定时的子程序、热键子程序或者自定义菜单项打断(这可以通过 Critical 避免)。如果发生了这种情况且打断线程花了很长时间才结束，那么实际上被打断的定时器在这段时间中将被禁用。不过，其它的定时器对打断首个定时器的线程进行中断，仍可继续运行。
  4. 脚本由于 Critical 或 Thread Interrupt/Priority 而不可中断。在此时间内，定时器不会运行。之后，当脚本可再次中断时，延误的定时器会尽快运行一次然后恢复到它的正常运作。

由于定时器靠临时中断脚本的当前活动来运作，所以它们的子程序应保持简短（以便它们迅速完成），无论何时都不适宜有很长的中断。

一个脚本运行期间持续生效的定时器通常应在自动执行部分创建。相比之下，临时定时器经常会被它的子程序禁用（请看本页底部的示例）。

每当一个定时的子程序运行时，它的设置比如 SendMode 都会以默认值重新开始。这些默认值可在自动执行部分修改。

虽然定时器会在脚本挂起时运作，但如果当前线程的 "Thread NoTimers" 正生效或者每当线程被暂停时，它们是不会运行的。另外，在用户浏览脚本的某个菜单时（如托盘图标菜单或菜单栏）定时器也不会运作。

如果热键的响应时间很重要（比如游戏中）且脚本包含的定时器子程序执行时间会超过 5 ms，那么可以使用如下命令来避免 15 ms 的延迟。否则如果热键正好在一个定时器线程处于它的不可中断周期时被按下，这个延迟就会发生：

Thread, interrupt, 0  ;使所有线程始终可中断。

如果定时器在它的子程序正运行时被禁用，该子程序会继续运行直到完成。

KeyHistory 功能会显示存在多少个定时器，当前启用了多少个。

定时器的周期不可大于 4294967295 毫秒(49.7 天)。

要让脚本持续运行，比如那些只包含了定时器的脚本，请用 #Persistent。

相关命令

Gosub, Return, Threads, Thread (command), Critical, IsLabel(), Menu, #Persistent

示例

;例 1: 当不需要的窗口出现时将其关闭：
#Persistent
SetTimer, CloseMailWarnings, 250
return

CloseMailWarnings:
WinClose, Microsoft Outlook, A timeout occured while communicating
WinClose, Microsoft Outlook, A connection to the server could not be established
return

;例 2: 等待一个特定的窗口出现，然后通知用户：
#Persistent
SetTimer, Alert1, 500
return

Alert1:
IfWinNotExist, Video Conversion, Process Complete
    return
;否则:
SetTimer, Alert1, Off  ;即定时器在此处将自己关闭。
SplashTextOn, , , 视频转换已完成。
Sleep, 3000
SplashTextOff
return

;例 3: 检测热键的单击、双击和三次按击。
;这允许热键可以按你按键的次数来执行不同的操作：
#c::
if winc_presses > 0 ; SetTimer 已经启动，所以我们记录按键。
{
    winc_presses += 1
    return
}
;否则，这是新一系列按键的首次按键。将计数设为 1 并启动定时器：
winc_presses = 1
SetTimer, KeyWinC, 400 ;在 400 毫秒内等待更多的按键。
return

KeyWinC:
SetTimer, KeyWinC, off
if winc_presses = 1 ;该键已按过一次。
{
    Run, m:\  ;打开一个文件夹。
}
else if winc_presses = 2 ;该键已按过两次。
{
    Run, m:\multimedia  ;打开一个不同的文件夹。
}
else if winc_presses > 2
{
    MsgBox, 检测到三次或更多次点击。
}
;不论上面哪个动作被触发，将计数复位以备下一系列的按键：
winc_presses = 0
return


Sleep

在继续前等待指定的时间量。

Sleep, DelayInMilliseconds

参数

Delay 要停顿的时间量(以毫秒形式)在 0 和 2147483647 (24 天) 之间，其可以是一个 表达式 。

说明

由于操作系统的时间控制系统的间隔尺寸，Delay 典型地上舍入为最临近10的倍数。例如，在大多数 Windows NT/2000/XP 系统上，一个在 1 和 10 (包含的)之间的 delay 相当于 10。不过，由于硬件差异，一些系统将上舍入为一个不同的值像15。

如果 CPU (中央处理器)处于负担状态，实际延迟时间可能比它请求的要更久结束。这是因为操作系统在给脚本另一个时间片之前，给每个有需要的进程一个 CPU 时间片(典型地有 20 毫秒)。

一个为 0 的 delay 让出脚本当前的时间片的剩余给任何其他需要它的进程(只要它们不在 priority(优先权)上比脚本显著地较低)。因此，一个为 0 的 delay 产出一个在 0 和 20ms (或更久)之间的实际延迟，取决于有需要的进程的数量 (如果无有需要的进程，也就根本没有 delay )。不过，一个为 0 的 Delay 将总是比任何更长的 Delay 结束得更早。

当脚本停顿时，新的 threads(线程) 能通过 hotkey 、自定义菜单项 或 timer 被运行。

"Sleep -1": 一个为 -1 的 delay 不会停顿，而是让脚本立即检查它的消息队列。这能被用来强制任何待定的 中断 发生在一个特定的地方，而不是更随机的某处。详见 Critical 。

相关命令

SetKeyDelay, SetMouseDelay, SetControlDelay, SetWinDelay, SetBatchLines

范例

Sleep, 1000  ; 1秒


Suspend

禁用或启用所有的或是选择的 热键 。

Suspend [, Mode]

参数

Mode

On: 挂起所有的热键，除了那些在下面注意部分做出解释的外。

Off: 重新启用所有的热键。

Toggle (默认): 变更为它先前的相反状态 (On 或 Off)。

Permit: 除了把当前的子程序标记为免除挂起外，什么也不做。

注意

任何第一行有 Suspend (除了 "Suspend On") 的热键子程序将被免于挂起。换句话说，热键在 Suspend 为 ON 的状态下仍将可用。这就允许了通过这样的一个热键来关掉挂起。

要根据当前窗口的类型自动地禁用选择的热键或热字符串，请用 #IfWinActive/Exist 。

挂起一个脚本的热键不会终止脚本已在运行的 线程 (如果有的话)；请用 Pause 命令来终止。

当脚本的热键被挂起时，它的托盘图标变为字母 S 。可以通过冻结图标来避免，只要将 Menu 命令的最后一个参数指定为 1 即可。例如：

Menu, Tray, Icon, C:\My Icon.ico, , 1

如果脚本被挂起，内置变量 A_IsSuspended 将包含 1 ，否则为 0 。

相关命令

#IfWinActive/Exist, Pause, Menu, ExitApp

示例

^!s::Suspend  ; 给一个热键指定挂起的开关功能。


While 循环

While 循环 [v1.0.48+]

重复执行一系列命令, 一直到指定的 表达式 计算结果为假.

While Expression

参数

Expression 任何有效的 表达式. 例如: while x < y

备注

在每次重复执行前都会计算一次表达式. 如果表达式计算结果为 true (即除空字符串和数值 0 以外的任何结果), 那么执行循环体; 否则跳到循环体之后一行执行.

while 循环后通常跟着 区块, 这是组成循环 体 语句的集合. 不过, 在单语句的循环中可以不使用区块 (用于此目的时 "if" 与其相匹配的 "else" 一起被视为单语句).

可以使用 One True Brace (OTB) 风格, 这样允许左大括号与 while 在同一行而不是在其下面. 例如: while x < y {

内置变量 A_Index 包含当前循环重复的次数. 首次计算循环的表达式和执行循环体时其值为 1. 第二次时其值为 2; 依此类推. 如果一个内层循环包含在一个外层循环中, 那么内层循环具有优先权. A_Index 在所有类型的循环中都有效, 但是在循环外部时其值为 0.

和所有的循环一样, 可以使用 Break 提前退出循环. 同样地, 可以使用 Continue 跳过当前循环的剩余部分, 此时 A_Index 增加 1 且重新计算 while 循环的表达式. 如果结果仍为 true, 开始新的循环; 否则循环结束.

专用循环: 循环可以用来自动获取文件, 文件夹或注册表项 (每次一个). 参见 文件循环 和 注册表循环 了解详细信息. 此外, 文件读取循环 可以对整个文件的内容进行操作, 每次一行. 最后, 解析循环 可以对包含在可分隔的字符串中的单独片段进行操作.

相关

Until, Break, Continue, 区块, Loop, For 循环, 文件和文件夹循环, 注册表循环, 文件读取循环, 解析循环, If (表达式)

示例

; 当用户按住鼠标左键拖动时, 在拖动区域中会出现工具提示显示区域的大小.

CoordMode, Mouse, Screen

~LButton::
    MouseGetPos, begin_x, begin_y
    while GetKeyState("LButton")
    {
        MouseGetPos, x, y
        ToolTip, % begin_x ", " begin_y "`n" Abs(begin_x-x) " x " Abs(begin_y-y)
        Sleep, 10
    }
    ToolTip
return


DllCall()

调用 DLL 文件中的函数, 例如标准的 Windows API 函数.

Result := DllCall("[DllFile\]Function" [, Type1, Arg1, Type2, Arg2, "Cdecl ReturnType"])

参数

Result | DllCall 返回调用函数返回的实际值. 如果函数没有返回值, 那么结果为一个未定义整数. 如果函数在调用时发生 错误, 那么返回值为空 (一个空字符串).
[DllFile\]Function

DLL 或 EXE 文件的名字后面跟着一个反斜线和函数名. 例如: "MyDLL\MyFunction" (省略时文件扩展名默认为 ".dll"). 如果未指定绝对路径, 则假定 DllFile 在系统的 PATH 变量指定的路径或 A_WorkingDir 中.

调用 User32.dll, Kernel32.dll, ComCtl32.dll, 或 Gdi32.dll 中的函数时可以省略 DllFile. 例如, "User32\IsWindowVisible" 和 "IsWindowVisible" 得到相同的结果. 对于这些标准的 DLL, 一些 API 函数含有的字母 "A" 后缀可以省略. 例如, "MessageBox" 等同于 "MessageBoxA".

当 重复 调用 DLL 时通过 预先装载此 DLL 文件 可以显著改善执行效率.

在 1.0.46.08 以上版本中, 此参数也可以是表示需调用函数的内存地址的整数. 如 COM 和 RegisterCallback() 提供的地址.
Type1, Arg1 | 这样的每对数据, 表示需传递给函数的单个参数. 参数的个数没有限制. 关于 Type, 参见下面的 类型表. 关于 Arg, 指定传递给函数的值.
Cdecl ReturnType

通常省略 单词 Cdecl 因为大多数函数使用标准调用约定而不是 "C" 调用约定 (像 wsprintf 这样接受可变数目参数的函数在这点上是个例外). 如果您省略了 Cdecl 但调用时产生了 ErrorLevel An -- 这里 n 是您传递的参数的总大小 -- 此时可能需要加上 Cdecl.

如果使用了, 那么单词 Cdecl 应该在返回值类型前列出 (如果有的话). 在单词间使用空格或 Tab 分隔. 例如: "Cdecl Str"

[AHK_L 53+]: 因为在 64 位代码中不使用 "C" 调用约定, 所以在 AutoHotkey_L 的 x64 版本中可以指定 Cdecl 但没有效果.

ReturnType: 如果函数返回一个 32 位的有符号整型 (Int), BOOL 或无返回值, ReturnType 可以省略. 否则需要指定下面 类型表 中参数类型的其中一个. 还支持 星号后缀.

参数和返回值类型

Str

如 "Blue" 或 MyVar 这样的字符串型. 如果被调用函数修改了字符串并且此参数是个裸变量, 那么其内容将被更新. 例如, 后面的调用将把 MyVar 的内容转换成大写: DllCall("CharUpper", "Str", MyVar)

然而, 如果函数需要保存超过变量当前容量的字符串, 在调用前必须确保此变量的容量足够大. 这可以通过调用 VarSetCapacity(MyVar, 123) 来实现, 这里 123 是为 MyVar 保留的容量.

Str 参数不能是计算结果为数字 (例如 i+1) 的 表达式. 如果这样, 不会调用函数并设置 ErrorLevel 的值为 -2.

支持 asterisk variable "Str*" 但极少使用. 它可以用在期望如 "char **" 或 "LPSTR *" 类型参数的函数中.

注意: 传递字符串给函数时, 应该知道函数期望什么 类型 的字符串.
AStr
WStr 		[AHK_L 42+]: ANSI 或 Unicode (宽 字符) 字符串型. 参见 脚本兼容性 了解等同的 Win32 类型和其他细节.
Int64 | 64 位整型, 其范围为 -9223372036854775808 (-0x8000000000000000) 到 9223372036854775807 (0x7FFFFFFFFFFFFFFF).
Int

32 位整型 (最常用的整数类型), 其范围为 -2147483648 (-0x80000000) 到 2147483647 (0x7FFFFFFF). Int 有时也写成 "Long".

整型也用于描述 BOOL 类型的参数 (一个 BOOL 值应该为 1 或 0).

无符号 整型 (UInt) 也是频繁使用的类型, 例如用于 DWORD 和 HWND.
Short | 16位整型, 其范围为 -32768 (-0x8000) 到 32767 (0x7FFF). 无符号 短整型 (UShort) 可用于函数参数的 WORD 类型.
Char | 8 位整型, 其范围为 -128 (-0x80) 到 127 (0x7F). 无符号 字符型 (UChar) 可用于函数参数的 BYTE 类型.
Float | 32 位浮点数, 具有 6 位精确度.
Double | 64 位浮点数, 具有 15 位精确度.
Ptr

[AHK_L 42+]: 指针大小的 整型. Ptr 应该用于数组或结构中的指针 (例如 RECT*) 和几乎所有句柄 (例如 HWND, HBRUSH 和 HBITMAP). 它通常不应该与指向简单值的指针例如 LPDWORD 或 int* 一起使用; 在这样情况下合适的 DllCall 类型应该带有 * 或 P 后缀 (见下面).

Ptr 也可以和 * 或 P 后缀一起使用; 它应该和通过 LPVOID* 或类似类型输出指针的函数一起使用.

UPtr 也是有效的, 但仅适用于 32 位版本中的无符号整型因为 AutoHotkey 不支持无符号的 64 位整型.

如果需要和旧版本的 AutoHotkey 兼容, 使用如下所示的变量类型:

Ptr := A_PtrSize ? "Ptr" : "UInt" ; If A_PtrSize is not defined, use UInt instead.
DllCall("DeleteFile", Ptr, &filename) ; Omit the quote marks around Ptr.

注意: 要传递 NULL 句柄或指针, 请传递整数 0.
* or P
(后缀)

在上述任一类型后附加一个星号 (星号前可以含有空格) 表示传递参数的地址而不是参数的值 (被调用函数必须接受地址). 由于这样的参数的值可能被函数修改, 每当不受保护的变量作为参数传递时, 变量的内容都会被更新. 例如, 后面的调用把 MyVar 的地址传给 MyFunction 但也会更新 MyVar 的内容来反映 MyFunction 对其做出的修改: DllCall("MyDll\MyFunction", "Int*", MyVar)

一般说来, 星号可用于函数中以 "LP" 开始的参数类型或返回值类型. 最常见的例子是 LPDWORD, 这是指向变量类型 DWORD 的指针类型. 因为 DWORD 是无符号 32 位整型, 所以用 "UInt*" 或 "UintP" 来表示 LPDWORD 的类型. 星号不应该用于字符串类型如 LPTSTR, 指向结构的指针如 LPRECT, 或数组; 对于这些, 根据您需要传递的是变量还是其地址应该使用 "Str" 或 "Ptr".

注意: "Char*" 与 "Str" 的类型是不同的因为 "Char*" 传递 8 位数的地址, 而 "Str" 传递一序列字符的地址. 同样地, "UInt*" 传递 32 位数的地址, 所以如果函数期望大于 32 位的结构或值的数组时不应该使用. 并且, 在函数将保存数字时不需要对星号变量调用 VarSetCapacity 来扩大其容量.
U (前缀)

在上述任一整型前加上字母 U 表示无符号整型 (UInt64, UInt, UShort, 和 UChar). 严格说来, 这仅对于返回值或 星号变量 才是必要的因为它不影响传递值的参数是无符号的还是有符号的 (除了 Int64).

如果在无符号参数中指定负整数, 那么它会被转换到无符号范围内. 例如, 把 -1 作为 UInt 类型, 它会被转换成 0xFFFFFFFF.

不支持由函数产生的 无符号 64 位整型. 因此, 要让大于或等于 0x8000000000000000 的数字起作用, 忽略 U 前缀并且把任何从函数接收到的负值转换成很大的正数. 例如, 如果设计返回值为 UInt64 类型的函数当函数返回 Int64 类型的 -1 值时实际返回值是 0xFFFFFFFFFFFFFFFF.

注意: 当指定不包含空格或星号的参数类型或返回值类型时, 包围的引号可以省略. 例如, 可以使用 str 代替 "Str" 而 CDecl 代替 "CDecl". 此外, 用字母 P 代替星号这样也可以省略引号. 例如: UIntP.

返回值

ErrorLevel 会被设置为下列值的其中一个来表示调用成功或失败.

0: 成功.

-1 (负 1): [DllFile\]Function 参数是一个浮点数. 要求参数为字符串或正整数.

-2: 返回值类型 或指定的 参数类型 中某一个无效. 此错误也可能由传递一个计算结果为数字的 表达式 给一个字符串 (str) 参数引起.

-3: 无法访问指定的 DllFile. 如果没有明确指明 DllFile 的路径, 则文件必须在系统的 PATH 变量路径或 A_WorkingDir 中. 此错误也可能由用户缺少访问此文件的权限引起.

-4: 在 DLL 中没有找到指定的函数.

N (任意正数): 调用了函数但异常终止了, 致命异常号为 N (例如, 0xC0000005 表示 "访问违例"). 此时函数返回一个空值 (空字符串), 但所有 星号变量 仍会被更新. 致命异常的一个例子是间接引用了无效的指针例如 NULL. 因为 Cdecl 函数决不会产生下一段中的 "An" 错误, 所以当传递给它的参数太少时可能会产生异常.

An (字母 A 后面跟着一个整数 n): 表示调用了函数但传递给它的参数太多或太少了. "n" 是is the number of bytes by which the argument list was incorrect. 如果 n 为正数, 表示传递的参数过多 (或参数太大), 或函数调用要求 CDecl 类型的参数. 如果 n 为负数, 表示传递的参数过少. 应该改正这种情况来确保函数的可靠运行. 此错误的出现也可能表示出现了异常, 此时函数返回空字符串. 请注意由于 x64 调用约定, 64 位版本不会设置 ErrorLevel 为 An.

异常和 A_LastError

尽管有内置的异常处理机制, 但仍有可能使用 DllCall 而让脚本崩溃. 当一个函数不直接产生异常而产生一些不适当的数据例如无效指针或没有结束符的字符串时, 这种情况可能发生. 这可能不是因为函数本身的错误而是脚本传递给它不适合的值例如一个无效指针或一个内存空间不足的 "str". 当脚本指定一个不适当的参数类型或返回值类型, 例如要求由函数生成的整数是一个 星号变量 或 str, 这时它也可能崩溃.

内置变量 A_LastError 包含了操作系统 GetLastError() 函数返回的结果, 此函数会在调用函数后被立即执行 (对效率的影响不可知). A_LastError 是一个介于 0 和 4294967295 之间的数字 (通常表示为十进制而非十六进制). 像 ErrorLevel 一样, A_LastError 是一个与每个线程关联的设置; 即由其他 线程 产生的中断无法改变它的值. 不过, Run/RunWait 也会设置 A_LastError 的值.

性能

当需要重复调用一个 DLL 时, 事先明确装载它可以显著提高执行效率 (对于 标准的 DLL 文件如 User32 可以不需要, 因为它总是常驻的). 这样的实现避免了 DllCall 每次内部调用 LoadLibrary 和 FreeLibrary 的需要. 例如:

hModule := DllCall("LoadLibrary", "Str", "MyFunctions.dll")  ; 避免了 DllCall() 在循环中每次都装载库的需要.
Loop, C:\My Documents\*.*, , 1
    result := DllCall("MyFunctions\BackupFile", "Str", A_LoopFileFullPath)
DllCall("FreeLibrary", "Ptr", hModule)  ; 为了释放内存, DLL 在使用后需要卸载.

在高于 1.0.46.08 的版本中, 通过预先查找函数的地址甚至可以获得更快的性能. 例如:

; 在后面的例子中, 如果 DLL 还没有装载, 使用 LoadLibrary 代替 GetModuleHandle.
MulDivProc := DllCall("GetProcAddress", Ptr, DllCall("GetModuleHandle", Str, "kernel32"), AStr, "MulDiv")
循环 500
    DllCall(MulDivProc, Int, 3, Int, 4, Int, 3)

[AHK_L 31+]: 如果 DllCall 的首个参数是一个原义的字符串例如 "MulDiv" 并且包含了函数的 DLL 在脚本开始前已正常装载了, 此字符串会自动被解析为函数地址. 这个内置的最优化比上述演示的例子执行的更高效.

同时, 在脚本的任意位置添加 #NoEnv 行可以改善 DllCall 的性能当使用了未引用的参数类型时 (例如 Int 与 "Int").

最后, 当传递一个字符串变量给不会改变它长度的函数时, 传递变量的 地址 可以提升性能 (例如 &MyVar) 而不是作为 "str" (尤其是当字符串很长的时候). 后面的例子把字符串转换成大写: DllCall("CharUpper", Ptr, &MyVar)

结构体和数组

结构体是内存中一系列连续的 成员 (空间). 大多数成员变量类型是整型.

调用接受结构体地址 (或内存块数组) 的函数可以把结构体的原始二进制数据保存到普通变量中. 一般步骤如下:

1) 调用 VarSetCapacity(MyStruct, 123, 0) 确保目标变量足够大以便保存结构体数据. 把 123 替换为至少和结构体大小一样大的数字. 最后一个参数零是可选的; 它会初始化所有成员变量为二进制零, 这样通常可以避免在下一步中频繁调用 NumPut().

2) 如果目标函数需要初始化结构体, 调用 NumPut(123, MyStruct, 4, "UInt") 来初始化任意一个成员为非零数据. 把 123 替换为需要向目标成员存入的整数 (或指定 &Var 来存入变量的 地址). 把 4 替换为目标成员的偏移量 (关于 "偏移" 的描述请参见步骤 #4). 把 "UInt" 替换为合适的类型或当成员是指针或句柄时省略.

3) 调用目标函数, 把 MyStruct 的 地址 作为 UInt 类型 (或 Ptr 在 AHK_L 42+ 时) 的参数传递过去. 例如, DllCall("MyDll\MyFunc", Ptr, &MyStruct). 函数将检查和/或改变其中的某些成员变量.

4) 使用 MyInteger := NumGet(MyStruct, 4, "UInt") 从结构体中获取任何想要的成员变量. 把 4 替换为结构体中目标成员的偏移量. 首个成员变量的偏移量总为 0. 第二个成员的偏移量为 0 加上首个成员的大小 (一般为 4 字节). 后面成员的偏移量等于它前一个成员的偏移量加上前一个成员的大小. 大多数成员 -- 例如 DWORD, Int, 和 其他 32 位整型 -- 是 4 个字节的大小. 把 "UInt" 替换为合适的类型或当成员是指针或句柄时省略.

参见 结构体示例 了解实际用法.

已知限制

当把一个 变量的地址 (例如 &MyVar) 传递给函数而此函数修改了变量内容的长度, 后面使用这个变量可能产生错误. 要解决此问题, 有后面几种方法: 1) 把 MyVar 作为 "Str" 参数而不是 Ptr/地址 传递; 2) 在 1.0.44.03+ 版本中, 在调用 DllCall 后使用 VarSetCapacity(MyVar, -1) 更新变量的内部容量.

由函数保存到变量中的任何二进制零会隐藏这个零右边的所有数据; 即这样的数据无法被大多数命令和函数访问或修改. 但是这样的数据可以通过 地址运算符 和 NumPut/NumGet 操作, 和 DllCall 一样.

当一个字符串传递给一个返回此字符串地址的函数后, 此函数可能会出乎意料地返回一个地址不同内容相同的字符串. 例如在编程语言中调用 CharLower(CharUpper(MyVar)) 将把 MyVar 的内容转换成小写. 但当使用 DllCall() 进行相同操作时, 在后面的调用操作后 MyVar 将是小写的因为 CharLower 对一个内容与 MyVar 相同地址不同的临时字符串进行操作:

MyVar = ABC
result := DllCall("CharLower", str, DllCall("CharUpper", Str, MyVar, Str), Str)

要变通解决此问题, 把上面两个带下划线的 "Str" 修改成 Ptr. 这种情况说明了 CharUpper 的返回值为纯地址并作为整数类型传递给 CharLower.

处理字符串时可能遇到某些限制. 想了解详情, 参见 脚本兼容性.

VBScript, JScript, 和组件对象模型 (COM)

[AHK_L 53+]: 通过 ComObjCreate, ComObjGet 或 ComObjActive 可以原生支持实现了 IDispatch 的 COM 对象.

VBScript 和 JScript 可以通过 Windows Scripting for AutoHotkey 嵌入到脚本中, 这样也可以访问 COM.

同样, 通过 DllCall 可以直接使用 COM, 参考示例: www.autohotkey.com/wiki/index.php?title=COM_Wrappers.

相关

脚本兼容性, PostMessage, OnMessage(), RegisterCallback(), Run, VarSetCapacity, 函数, SysGet, MSDN Library

示例

; 示例: Calls the Windows API function "MessageBox" and report which button the user presses.

WhichButton := DllCall("MessageBox", "Int", "0", "Str", "Press Yes or No", "Str", "Title of box", "Int", 4) MsgBox You pressed button #%WhichButton%.
; 示例: Changes the desktop wallpaper to the specified bitmap (.bmp) file.

DllCall("SystemParametersInfo", UInt, 0x14, UInt, 0, Str, A_WinDir . "\winnt.bmp", UInt, 2)
; 示例: Calls the API function "IsWindowVisible" to find out if a Notepad window is visible.

DetectHiddenWindows On if not DllCall("IsWindowVisible", "Ptr", WinExist("Untitled - Notepad")) ; WinExist() returns an HWND.
 MsgBox The window is not visible.
; 示例: Calls the API's wsprintf() to pad the number 432 with leading zeros to make it 10 characters wide (0000000432).

VarSetCapacity(ZeroPaddedNumber, 20) ; Ensure the variable is large enough to accept the new string.
DllCall("wsprintf", "Str", ZeroPaddedNumber, "Str", "%010d", "Int", 432, "Cdecl") ; Requires the Cdecl calling convention.
MsgBox %ZeroPaddedNumber%
; 示例: Demonstrates QueryPerformanceCounter(), which gives more precision than A_TickCount's 10ms.

DllCall("QueryPerformanceCounter", "Int64*", CounterBefore) Sleep 1000 DllCall("QueryPerformanceCounter", "Int64*", CounterAfter) MsgBox % "Elapsed QPC time is " . CounterAfter - CounterBefore
; 示例: This is a hotkey that temporarily reduces the mouse cursor's speed, which facilitates precise positioning. ; Hold down the F1 key to slow down the cursor. Release it to return to original speed.

F1:: SPI_GETMOUSESPEED = 0x70 SPI_SETMOUSESPEED = 0x71
; Retrieve the current speed so that it can be restored later:
DllCall("SystemParametersInfo", UInt, SPI_GETMOUSESPEED, UInt, 0, UIntP, OrigMouseSpeed, UInt, 0)
; Now set the mouse to the slower speed specified in the next-to-last parameter (the range is 1-20, 10 is default):
DllCall("SystemParametersInfo", UInt, SPI_SETMOUSESPEED, UInt, 0, Ptr, 3, UInt, 0) KeyWait F1 ; This prevents keyboard auto-repeat from doing the DllCall repeatedly.
return F1 up::DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, Ptr, OrigMouseSpeed, UInt, 0) ; Restore the original speed.
; 示例: When passed a window's Unique ID and the text or ClassNN of one of its controls, ; the following function returns the HWND (unique ID) of that control. ; v1.0.43.06+: This function has been superseded by the following command, which is more accurate.

ControlGet, OutputVar, Hwnd,, ClassNN, WinTitle
; 示例: Monitors the active window and display the position of its vertical scroll bar in its ; focused control (with real-time updates). This requires v1.0.43.06+ because it uses ControlGet Hwnd. #Persistent SetTimer, WatchScrollBar, 100 return WatchScrollBar: ActiveWindow := WinExist("A") if not ActiveWindow ; No active window.
 return ControlGetFocus, FocusedControl, ahk_id %ActiveWindow% if not FocusedControl ; No focused control.
 return
; Display the vertical or horizontal scroll bar's position in a ToolTip:
ControlGet, ChildHWND, Hwnd,, %FocusedControl%, ahk_id %ActiveWindow% ToolTip % DllCall("GetScrollPos", "Ptr", ChildHWND, "Int", 1) ; Last parameter is 1 for SB_VERT, 0 for SB_HORZ.
return
; 示例: This is a working script that writes some text to a file then reads it back into memory (requires v1.0.34+). ; This method can be used to help performance in cases where multiple files are being read or written simultaneously.

FileSelectFile, FileName, S16,, Create a new file: if FileName = return GENERIC_WRITE = 0x40000000 ; Open the file for writing rather than reading.
CREATE_ALWAYS = 2 ; Create new file (overwriting any existing file).
hFile := DllCall("CreateFile", Str, FileName, UInt, GENERIC_WRITE, UInt, 0, Ptr, 0, UInt, CREATE_ALWAYS, UInt, 0, Ptr, 0) if not hFile { MsgBox Can't open "%FileName%" for writing. return } TestString = This is a test string.`r`n ; When writing a file this way, use `r`n rather than `n to start a new line.
DllCall("WriteFile", Ptr, hFile, Str, TestString, UInt, StrLen(TestString), UIntP, BytesActuallyWritten, Ptr, 0)
DllCall("CloseHandle", Ptr, hFile) ; Close the file.

; Now that the file was written, read its contents back into memory.
GENERIC_READ = 0x80000000 ; Open the file for reading rather than writing.
OPEN_EXISTING = 3 ; This mode indicates that the file to be opened must already exist.
FILE_SHARE_READ = 0x1 ; This and the next are whether other processes can open the file while we have it open.
FILE_SHARE_WRITE = 0x2 hFile := DllCall("CreateFile", Str, FileName, UInt, GENERIC_READ, UInt, FILE_SHARE_READ|FILE_SHARE_WRITE, Ptr, 0, UInt, OPEN_EXISTING, UInt, 0, Ptr, 0) if not hFile { MsgBox Can't open "%FileName%" for reading. return }
; Make the variable empty for testing purposes, but ensure it retains sufficient capacity:
BytesToRead := VarSetCapacity(TestString, StrLen(TestString))
DllCall("ReadFile", Ptr, hFile, Str, TestString, UInt, BytesToRead, UIntP, BytesActuallyRead, Ptr, 0)
DllCall("CloseHandle", Ptr, hFile) ; Close the file.
MsgBox The following string was read from the file: %TestString%
; 示例: Hides the mouse cursor when you press Win+C. To later show the cursor, press Win+C again. ; This script is from www.autohotkey.com/forum/topic6107.html

OnExit, ShowCursor ; Ensure the cursor is made visible when the script exits.
return ShowCursor: SystemCursor("On") ExitApp #c::SystemCursor("Toggle") ; Win+C hotkey to toggle the cursor on and off.

SystemCursor(OnOff=1) ; INIT = "I","Init"; OFF = 0,"Off"; TOGGLE = -1,"T","Toggle"; ON = others
{ static AndMask, XorMask, $, h_cursor ,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13 ; system cursors
 , b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13 ; blank cursors
 , h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13 ; handles of default cursors
 if (OnOff = "Init" or OnOff = "I" or $ = "") ; init when requested or at first call
 { $ = h ; active default cursors
 VarSetCapacity( h_cursor,4444, 1 ) VarSetCapacity( AndMask, 32*4, 0xFF ) VarSetCapacity( XorMask, 32*4, 0 ) system_cursors = 32512,32513,32514,32515,32516,32642,32643,32644,32645,32646,32648,32649,32650 StringSplit c, system_cursors, `, Loop %c0% { h_cursor := DllCall( "LoadCursor", "Ptr",0, "Ptr",c%A_Index% ) h%A_Index% := DllCall( "CopyImage", "Ptr",h_cursor, "UInt",2, "Int",0, "Int",0, "UInt",0 ) b%A_Index% := DllCall( "CreateCursor", "Ptr",0, "Int",0, "Int",0 , "Int",32, "Int",32, "Ptr",&AndMask, "Ptr",&XorMask ) } } if (OnOff = 0 or OnOff = "Off" or $ = "h" and (OnOff < 0 or OnOff = "Toggle" or OnOff = "T")) $ = b ; use blank cursors
 else $ = h ; use the saved cursors

 Loop %c0% { h_cursor := DllCall( "CopyImage", "Ptr",%$%%A_Index%, "UInt",2, "Int",0, "Int",0, "UInt",0 ) DllCall( "SetSystemCursor", "Ptr",h_cursor, "UInt",c%A_Index% ) } }
; Structure Example: Pass the address of a RECT structure to GetWindowRect(), which sets the structure's ; members to the positions of the left, top, right, and bottom sides of a window (relative to the screen).

Run Notepad WinWait Untitled - Notepad ; This also sets the "last found window" for use with WinExist() below.
VarSetCapacity(Rect, 16) ; A RECT is a struct consisting of four 32-bit integers (i.e. 4*4=16).
DllCall("GetWindowRect", Ptr, WinExist(), Ptr, &Rect) ; WinExist() returns an HWND.
MsgBox % "Left " . NumGet(Rect, 0, "Int") . " Top " . NumGet(Rect, 4, "Int") . " Right " . NumGet(Rect, 8, "Int") . " Bottom " . NumGet(Rect, 12, "Int")
; Structure Example: Pass to FillRect() the address of a RECT structure that indicates a part of the ; screen to temporarily paint red.

VarSetCapacity(Rect, 16, 0) ; Set capacity to hold four 4-byte integers and initialize them all to zero.
NumPut(A_ScreenWidth//2, Rect, 8, "Int") ; The third integer in the structure is "rect.right".
NumPut(A_ScreenHeight//2, Rect, 12, "Int") ; The fourth integer in the structure is "rect.bottom".
hDC := DllCall("GetDC", "Ptr", 0, "Int") ; Pass zero to get the desktop's device context.
hBrush := DllCall("CreateSolidBrush", "UInt", 0x0000FF) ; Create a red brush (0x0000FF is in BGR format).
DllCall("FillRect", "Ptr", hDC, "Ptr", &Rect, "Ptr", hBrush) ; Fill the specified rectangle using the brush above.
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC) ; Clean-up.
DllCall("DeleteObject", "Ptr", hBrush) ; Clean-up.
; Structure Example: Change the system's clock to the specified date and time. Use caution when ; changing to a date in the future as it may cause scheduled tasks to run prematurely!

SetSystemTime("20051008142211") ; Pass it a timestamp (local, not UTC).

SetSystemTime(YYYYMMDDHHMISS)
; Sets the system clock to the specified date and time. ; Caller must ensure that the incoming parameter is a valid date-time stamp ; (local time, not UTC). Returns non-zero upon success and zero otherwise.
{ ; Convert the parameter from local time to UTC for use with SetSystemTime().
 UTC_Delta -= A_NowUTC, Seconds ; Seconds is more accurate due to rounding issue.
 UTC_Delta := Round(-UTC_Delta/60) ; Round to nearest minute to ensure accuracy.
 YYYYMMDDHHMISS += UTC_Delta, Minutes ; Apply offset to convert to UTC.

 VarSetCapacity(SystemTime, 16, 0) ; This struct consists of 8 UShorts (i.e. 8*2=16).

 StringLeft, Int, YYYYMMDDHHMISS, 4 ; YYYY (year)
 NumPut(Int, SystemTime, 0, "UShort") StringMid, Int, YYYYMMDDHHMISS, 5, 2 ; MM (month of year, 1-12)
 NumPut(Int, SystemTime, 2, "UShort") StringMid, Int, YYYYMMDDHHMISS, 7, 2 ; DD (day of month)
 NumPut(Int, SystemTime, 6, "UShort") StringMid, Int, YYYYMMDDHHMISS, 9, 2 ; HH (hour in 24-hour time)
 NumPut(Int, SystemTime, 8, "UShort") StringMid, Int, YYYYMMDDHHMISS, 11, 2 ; MI (minute)
 NumPut(Int, SystemTime, 10, "UShort") StringMid, Int, YYYYMMDDHHMISS, 13, 2 ; SS (second)
 NumPut(Int, SystemTime, 12, "UShort") return DllCall("SetSystemTime", Ptr, &SystemTime) }
/* More Structure Examples:

1) See the WinLIRC client script for a demonstration of how to use DllCall() to make a network connection to a TCP/IP server and receive data from it. 2) The operating system offers standard dialog boxes that prompt the user to pick a font and/or color, or an icon. These dialogs use structures and are demonstrated at www.autohotkey.com/forum/topic17230.html. */


OnMessage()

指定一个函数，当脚本接收到指定消息时会自动调用它。

OnMessage(MsgNumber [, "FunctionName", MaxThreads])

参数

MsgNumber | 需要监视或查询的消息编号，应该在 0 与 4294967295 (0xFFFFFFFF) 之间。如果您不希望监视系统消息 （编号小于 0x400），最好在大于 4096 (0x1000) 的数中选择一个。这可以尽量避免干扰到当前及以后版本的 AutoHotkey 内部所使用的消息。
FunctionName | 函数名，如果是一个原意的字符串，必须用引号引起来。当脚本收到 MsgNumber 时该函数会被自动调用。省略这个和下一个参数可以获取到函数当前正在监视的 MsgNumber （若无则为空）。指定一个空字符串 ("") 或一个空变量可以关闭对 MsgNumber 的监视。
MaxThreads [v1.0.47+] | 该整数通常省略，表示限制监视函数在同一时刻只能有一个 线程。这通常是最佳的，因为若不如此，只要监视函数中断它自己，脚本将不会按照时间先后顺序处理消息。因此，可以考虑使用 Critical 来代替 MaxThreads 。说明见下。

返回值

如果省略 FunctionName 和 MaxThreads，将返回正在监视 MsgNumber 的函数名（若无则为空）。无论如何，这并不会改变什么。

如果明确地将 FunctionName 置空 （如 ""），将返回正在监视 MsgNumber 的函数名（若无则为空），然后关闭对 MsgNumber 的监视。

如果 FunctionName 非空：如果 MsgNumber 已经处于被监视状态，则返回先前的函数名并让新函数生效。否则，指派 FunctionName 监视 MsgNumber 然后返回相同的 FunctionName。无论哪种情况，当失败时会返回一个空值。发生失败的原因是当 FunctionName：1) 不存在（可能是由于 FunctionName 前后缺少引号）；2) 接受多于四个参数；或者 3) 有任何的 ByRef 或 可选 参数。发生以下情况也会失败：当已经有500个消息受到监视的情况下脚本试图监视新消息。

函数的参数

一个被指派用于监视一个或多个消息的 函数 最多可以接受四个参数：

MyMessageMonitor(wParam, lParam, msg, hwnd)
{
    ... 函数体...
}

您所给出的参数名是什么没有关系，但是以下信息是与这些参数的顺序一一对应的：

参数 #1：消息的 WPARAM 值，一个 0 与 4294967295 之间的整数。
参数 #2: 消息的 LPARAM 值，一个 0 与 4294967295 之间的整数。
参数 #3: 消息码，在函数监视多于一个消息时很有用。
参数 #4: 接收消息的窗口或控件的 HWND（唯一标识号）。要使用 HWND 可以加上 ahk_id 。

当您不需要从右边开始的一个或多个参数所对应的信息时，可以省略它们。例如，一个定义成 MyMsgMonitor(wParam, lParam) 的函数将只接收头两个参数，而定义成 MyMsgMonitor() 的函数将不接收任何参数。

如果一个新来的 WPARAM 或 LPARAM 应该是一个有符号数，任何负数可以用以下例子展现出来：

if wParam > 0x7FFFFFFF
    wParam := -(~wParam) - 1

函数中有效的附加信息

除了上面接收到的参数外，函数还可以使用下面的内置变量：

  • A_Gui: 为空，除非消息被发送给一个 GUI 窗口或控件，在这种情况下 A_Gui 是 Gui 窗口编号 （该窗口还会被设为函数的 默认 GUI 窗口 )。
  • A_GuiControl: 为空，除非消息被发送给一个 GUI 控件，在这种情况下它包含了控件的变量名或其他在 A_GuiControl 描述过的值。有些控件不会接收某些类型的消息。例如，当用户单击一个文本控件时，操作系统会发送 WM_LBUTTONDOWN 到它的父窗口而不是控件本身；结果导致 A_GuiControl 为空。
  • A_GuiX 和 A_GuiY： 如果新来的消息是通过 SendMessage 被发送的，则两者都包含 -2147483648。如果消息是通过 PostMessage 被发送的，它们包含的是在消息被投递的那一刻鼠标指针的坐标（相对于屏幕）。
  • A_EventInfo: 如果消息是通过 SendMessage 被发送的，则包含 0 。如果是通过 PostMessage 发送的，它包含消息被投递时的 tick-count 时间 。

一个监视函数的 上一次找到的窗口 开始于消息的目的父窗口（即使消息被发送到一个控件）。如果窗口是隐藏的但不是一个 GUI 窗口（如脚本的主窗口），则在使用它前开启 DetectHiddenWindows。举个例子：

DetectHiddenWindows On
MsgParentWindow := WinExist()  ; 保存接收消息的窗口的唯一标识号(unique ID)。

函数应该 返回 什么

如果一个监视函数使用不带任何参数的 Return，或者指定一个空值如 "" （或者根本不使用 Return ），当函数结束时新来的消息将继续被正常处理。同样的事也会发生在当函数使用 Exit 退出或产生了一个运行时错误，比如 运行 了一个不存在的文件。相比之下，返回一个 -2147483648 与 4294967295 之间的整数会使得那个数直接作为一个回覆被发送；也就是说，程序不会再进一步处理该消息。举个例子，一个监视 WM_LBUTTONDOWN (0x201) 的函数可以返回一个整数以阻止目标窗口收到鼠标点击产生的通知。在多数情况下（例如消息经由 PostMessage 而来），返回哪个值并没有关系；不过若您吃不准，0 通常是最安全的。

综合注意事项

不像普通的函数调用，被监视消息的到来会开一个新 线程 调用监视函数。因此，函数会全新地以设置（如 SendMode 和 DetectHiddenWindows）的默认值开始运行。这些默认值可以在自动执行段中被修改。

被发送(send)（不是投递(post)）给一个控件的消息将不会被监视到，因为系统会在后台直接将它们路由给控件。在系统生成的消息里是一种罕见的现象，因为它们多数是被投递的。

任何的在任何地方调用 OnMessage 的脚本都会自动地常驻(persistent)。同时还是单一进程(single-instance)的，除非使用 #SingleInstance 覆盖。

当一个消息到来时如果它的函数由于没有处理完先前到来的同样的消息而仍在运行，该函数将不会被再次调用（除非 MaxThreads 大于 1）；或者说，该消息将会被视为不受监视的。如果您不希望如此，通过在函数的第一行指定 Critical 可以让一个大于等于 0x312 的消息在函数完成前被缓冲。或者，Thread Interrupt 可以完成同样的事，只要它持续到函数完成。相比之下，小于 0x312 的消息是不能通过 Critical 或 Thread Interrupt 被缓冲的（然而在 v1.0.46 及以后版本中，Critical 可能会有所帮助，因为它 以更低的频率 检查消息，这可以让函数有更多的时间去完成）。只有一种方法可以保证没有遗漏类似的消息，就是要确保函数在 6 毫秒内（不过这个限制可以通过 Critical 30 来提升）执行完成。要做到这一点，一个方法是通过将一个受监视的大于 0x312 的消息投递到脚本主窗口来让新来的消息等候一个未来线程。这个大于 0x312 消息的监视函数应该在第一行使用 Critical 以确保它的消息被缓冲。

如果一个数值小于 0x312 的被监视消息在脚本处于绝对不可中断状态——例如 菜单 正在被显示，一个 KeyDelay/MouseDelay 正在进行中，或者剪贴板正要被 打开——时到来，则消息监视函数将不会被调用，并且消息会被视为不受监视的。相比之下，大于等于 0x312 的被监视消息将在这个不可中断时期内被缓冲；就是说，它的函数将在脚本变为可中断时被调用。

如果一个数值小于 0x312 的被监视消息在脚本不可中断时到来，而且不可中断的原因仅仅是因为 Thread Interrupt 或 Critical 的设置，那么当前线程将被中断，好让监视函数得以被调用。相比之下，大于等于 0x312 的被监视消息将在线程结束或变为可中断前被缓冲。

OnMessage 线程的 优先级 总是 0 。因此，若当前线程的优先级高于 0 将不会有消息被监视或缓冲。

监视系统消息（低于 0x400）时应多加小心。举个例子，如果一个监视函数不是很快地就结束，那么对消息的响应时间可能超出系统预期，由此可能引发副作用。如果一个监视函数为了阻止消息被进一步处理而返回一个整数，但是系统期望的却是不同的处理或不同的响应，那么不想要的行为亦有可能发生。

如果脚本正在显示一个系统对话框比如 MsgBox ，任何投递给控件的消息将不会被监视到。举个例子，如果脚本正在显示一个 MsgBox 且用户点击了一个 GUI 窗口中的某个按钮， WM_LBUTTONDOWN 消息将被直接发送给按钮而不调用监视函数。

尽管一个外部程序可以通过 PostThreadMessage() 或其他 API 调用直接将消息投递给脚本的线程，但并不推荐这样做，因为如果脚本正在显示一个系统窗口比如 MsgBox 的话会导致消息丢失。或者说，通常最好投递或发送消息给脚本的主窗口或其中的一个 GUI 窗口。

相关命令

RegisterCallback(), OnExit, OnClipboardChange, Post/SendMessage, 函数, Windows 消息列表, 线程(Threads), Critical, DllCall()

示例

; 示例：下面是一个可用脚本，监视 GUI 窗口中的鼠标点击。
; 相关主题： GuiContextMenu

Gui, Add, Text,, 点击此窗口中的任何地方
Gui, Add, Edit, w200 vMyEdit
Gui, Show
OnMessage(0x201, "WM_LBUTTONDOWN")
return

WM_LBUTTONDOWN(wParam, lParam)
{
    X := lParam & 0xFFFF
    Y := lParam >> 16
    if A_GuiControl
        Control := "`n(位于控件 " . A_GuiControl . ")"
    ToolTip 您在 Gui 窗口 #%A_Gui% 中的客户区坐标 %X%x%Y%.%Control% 处单击了。
}

GuiClose:
ExitApp

; 示例：以下脚本检测系统的关机/注销事件并允许你终止它（据说
; 在 Windows Vista 下不会工作）。
; 相关主题：OnExit

; 以下 DllCall 是可选的：它告诉操作系统要最先（优先于其他所有的应用程序）关闭该脚本。
; 在 Windows 9x 下该调用无效。
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)
OnMessage(0x11, "WM_QUERYENDSESSION")
return

WM_QUERYENDSESSION(wParam, lParam)
{
    ENDSESSION_LOGOFF = 0x80000000
    if (lParam & ENDSESSION_LOGOFF)  ; 用户正在注销
        EventType = 注销
    else  ; 系统正在关闭或重启。
        EventType = 关机
    MsgBox, 4,, 正在%EventType%，是否允许？
    IfMsgBox Yes
        return true  ; 告诉操作系统允许让 关机/注销 操作继续。
    else
        return false  ; 告诉操作系统终止 关机/注销。
}

; 示例：拥有一个能接受来自其他脚本或程序的自定义消息和不超过两个数的脚本
; （若要发送字符串而不是数，参见后面一个例子。

OnMessage(0x5555, "MsgMonitor")
OnMessage(0x5556, "MsgMonitor")

MsgMonitor(wParam, lParam, msg)
{
    ; 由于尽快返回常常很重要，使用 ToolTip 比
    ; MsgBox 之类的（因为会阻止函数结束）要好：
    ToolTip Message %msg% arrived:`nWPARAM: %wParam%`nLPARAM: %lParam%
}

; 以下代码可用于其他脚本内部，以运行上述脚本中的函数：
SetTitleMatchMode 2
DetectHiddenWindows On
if WinExist("接收脚本名.ahk ahk_class AutoHotkey")
    PostMessage, 0x5555, 11, 22  ; 因为上面有 WinExist()，消息将被发送到 "上一次找到的窗口"。
DetectHiddenWindows Off  ; 在 PostMessage 之前不可设为关闭(off)。

; 示例：从一个脚本发送任意长度的字符串到另一个脚本。这是一个可用的例子。
; 使用方法：保存并运行以下两个脚本后按 Win+空格，会显示一个
; InputBox 提示您输入一个字符串。

; 以 "Receiver.ahk" 为名保存以下脚本，然后运行它：
#SingleInstance
OnMessage(0x4a, "Receive_WM_COPYDATA")  ; 0x4a 是 WM_COPYDATA
return

Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 8)  ; lParam+8 是 CopyDataStruct 的 lpData 成员的地址。
    StringLength := DllCall("lstrlen", UInt, StringAddress)
    if StringLength <= 0
        ToolTip %A_ScriptName%`n接收到了一个空串或遇到一个错误。
    else
    {
        VarSetCapacity(CopyOfData, StringLength)
        DllCall("lstrcpy", "str", CopyOfData, "uint", StringAddress)  ; 复制字符串到结构体外。
        ; 用 ToolTip 而不是 MsgBox 来显示，这样我们就可以及时返回了：
        ToolTip %A_ScriptName%`n接收到了以下字串：`n%CopyOfData%
    }
    return true  ; 返回 1 (true) 是回应此消息的传统方法。
}

; 以 "Sender.ahk" 为名保存下列脚本并运行它。之后，按 Win+空格。
TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey

#space::  ; Win+空格 热键。按下该热键会显示一个用于输入消息字符串的输入框(Inputbox)。
InputBox, StringToSend, 通过 WM_COPYDATA 发送文本, 输入要发送的文本：
if ErrorLevel  ; 用户按下了 Cancel(取消) 按钮。
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
    MsgBox SendMessage 失败。具有下列标题的窗口是否存在？：`n%TargetScriptTitle%
else if result = 0
    MsgBox 消息被发送了，但是目标窗口用 0 回应该消息，这可能意味着该窗口忽略了它。
return

Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; 此种情况下 ByRef 会节约一点内存。
; 该函数发送指定的字符串到指定的窗口然后返回。
; 若目标窗口处理了该消息则返回 1 ，否则返回 0 表示忽略了它。
{
    VarSetCapacity(CopyDataStruct, 12, 0)  ; 分配结构体内存区域。
    ; 首先设置结构体的 cbData 成员为字符串长度，包括零结束符：
    NumPut(StrLen(StringToSend) + 1, CopyDataStruct, 4)  ; 操作系统要求这已完成。
    NumPut(&StringToSend, CopyDataStruct, 8)  ; 设置 lpData 为指向字符串自身的指针。
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%  ; 0x4a 是 WM_COPYDATA。必须使用 Send 而不是 Post。
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; 为调用者恢复原来的设置。
    SetTitleMatchMode %Prev_TitleMatchMode%         ; 同上。
    return ErrorLevel  ; 将 SendMessage 的返回值返回给我们的调用者。
}

; 示例：参见 WinLIRC 客户端脚本 ，该脚本演示了如何使用 OnMessage() 接收
; 当一个网络连接上有数据到来时的通知。


RegExMatch

RegExMatch() [v1.0.45+]

确定一个字符串中所包含的匹配模式 (即：正则表达式)。

FoundPos := RegExMatch(Haystack, NeedleRegEx [, UnquotedOutputVar = "", StartingPosition = 1])

参数

FoundPos | RegExMatch() 返回从源字符串 Haystack 最左边开始找到的第一个匹配 NeedleRegEx 模式的位置。首字符的位置是 1 。要是在字符串中没有找到匹配模式的时候就会返回 0。如果出现了错误 (比如：正则表达式 NeedleRegEx 的语法错误)，它将会返回一个空的字符串和 ErrorLevel 。ErrorLevel 将是 下面 值中的一个，包括 0。
Haystack | 源字符串。
NeedleRegEx | 这种匹配模式是和 Perl 兼容的正则表达式 (PCRE) 。如果有必要的话，可以在正则表达式前加上 选项 ，并以 ")" 结束。例如：这个匹配模式 "i)abc.*123" 将匹配不区分大小写的 "abc" ，中间可以是任何字符，并以 123 结尾的模式进行搜索。要是没有 选项 ，这个 ")" 是可选的，例如： ")abc" 就等同于 "abc" 。
UnquotedOutputVar

形式1 (默认)：OutputVar 是 unquoted 的一个变量名，它将存储 Haystack 中符合匹配模式的那一部分字符串。如果没有找到符合这个模式的子串 (那么，RegExMatch() 将返回 0 )，而输出变量和所有的数组元素将被置为空。

如果在 NeedleRegEx 中包含 捕捉子模式 ，那么它们将存储在以 OutputVar 为基变量的 数组 里。例如：输出的变量名是 Match ，那它第一个能匹配子模式的子串将存储在 Match1 ，第二个存储在 Macth2 ，等等。有一个例外是 命名子模式 ：它用名字代替了数字的形式来存储。例如：这种模式 (?P<Year>\d{4}) ，会把输出的子串存储在 MatchYear 里面。如果没有任何字符串 (或者此函数返回的值是 0 )，那么这一输出变量置为空。

在 函数 中创建一个全局变量的数组来替代局部变量，就要在使用前 声明 数组名 (比如刚才的 Match ) 为全局变量。

形式2 (位置 – 长度)：若以 P 开头的正则表达式，比如，"P)abc.*123"，则完全匹配正则表达式的字符串的 长度 将存储在 OutputVar 里 (没有匹配到，长度就是 0 )。如果现在使用了 捕捉子模式 ，就会有两个数组 OutputOvarPos 和 OutputVarLen 分别存储匹配到的字符串的位置和长度。例如：若基变量名为 Match ，则符合模式的第一个子串的位置存储在 MatchPos1 ，长度存储在 MatchLen1 (没到匹配到任何子串则全部返回 0 ，函数值也会为 0 )。仍有一个例外，就是 命名子模式：它将存储名用名字替代了数字 (比如，MatchPosYear 和 MatchLenYear )。
StartingPosition

如果省略 StartingPostion 的值，它会默认为 1 (从源字符串 Haystack 的第一个字符开始)。另外，设置为 2 则以第二个字符开始，值为 3 就从第三个开始，依次类推。如果 StartingPostion 的值超出了 Haystack 的长度范围，则函数返回为 0 ，变量值为空。

如果 StartingPostion 的值小于1，函数会认为是从 Haystack 的末尾处开始。例如：0 就是倒数一个字符的位置，-1 就是倒数第二个字符，依次类推。如果 StartingPostion 超过了 Haystack 最左边的位置，它就会搜索整个 Haystack 。

无论 StartinPostion 的值是什么，函数返回的值都是根据 Haystack 的第一个字符所确定的。例如："123abc789” 中 "abc” 的位置总是 4 。

ErrorLevel

ErrorLevel 的值是下面中的一个:

  • 0, 表示没发现错误。
  • 一个有如下格式的字符串：Complie error N at offset M: description. 在这个字符串里，N 是 PCRE ( Perl 兼容正则表达式 ) 的错误值，M 是正则表达式中出现错误的位置，description 是描述这个错误的文本信息。
  • 一个负数，是指在 执行 正则表达式过程中出现的错误。尽管这种错误非常罕见，如这些情况就容易出现这种错误：”太多的空匹配“ (-22)，”递归太深“ (-21)，”太到匹配极限“ (-8)。如果出现了这些错误，就试着重新写更严格的正则表达式，如用 ? , + 或者用有限制的方式，如 {0,3} 来取代 * 。

选项 ( 区分大小写 )

在正则表达式之前加上 0 个或者多个选项并以右括号结束。例如：模式 "im)abc” 将搜索多行中不区分大小写的 abc ，若没有选项可以省略圆括号。尽管这将原来的语法打断，但是它不需要新的前分割符 (比如右斜杠)，因此没有必要转换模式内的分割符。另外，由于使用了选项，函数性能有所提升。

i | 不区分大小写。
m | 多行是指由多个单行 (有换行符) 所组成的一个集合 (它包括换行符) 。但在下列情况会有所改变： 1) 弯折符号 (^) 在所有行内匹配 -- 总是从源字符串开头的地方开始匹配 (但不是匹配源字符串 Haystack 中换行 靠后 的地方)。 2) 美元符号 ($) 在源字符串中任意换行符之前匹配 (也就是说，它总是匹配每行靠近结尾的地方)。 例如：源字符串是 "xyz`r`nabc" 中的 abc 要用模式 "m)^abc$" 来精确匹配。 如果选项是 "D"，它就将会忽略当前的 "m"。
s | 该选项会使点 (.) 能匹配一行内所有的字符 (通常不会换行符后的) 。如果换行符是默认的 CRLF (`r`n) ，就要用两个点去匹配它 (而不是一个点)。无论这个选项如何，[^a] 总是匹配换行符。
x | 忽略模式中空白字符类。如字符 `n 和 `t 这类的字符将被在正则表达式中的忽略，这些字符都是出现在正则表达式中 (与此相反，使用 \n 和 \t 之类的字符就不会被正则表达式忽略)。x 选项也是一个复杂的模式。然而，这种模式必须遵循这个条件： 只能 应用在数据字符中；空白字符也许不会出现特殊的序列，如 (?(。
A | 强制将匹配模式固定；也就是说，它只能从源字符串的第一个字符开始匹配。大数情况下，和 "^" 的功能一样。
D | 强制用 ($) 的方式来从靠近源字符串末尾的地方开始匹配，即使源字符串以的换行符结尾的。没有这个选项时，$ 就只能匹配换行符 (如果有的话) 前的字符了。注意：这个选项会让 "m" 选项不起作用。
J | 允许重复 命名子模式 。这是一个很有用的模式，它在一组相同命名子模式下也能够匹配。注意：如果有多个实例命名去匹配字符串的话，就只有最左边的那个命名才会被存储 (变量名不区分大小写)。
U | 非贪婪的。只有在绝对必要的情况下才会使用量词 *+?{} ，并将剩下的部分提供给下一个模式。当 "U" 选项无效时，可以通过一个问号作为量词进行非贪婪匹配。相反地，当 "U" 选项有效，问号就会进行贪婪搜索。
X | PCRE 扩展。它使 PCRE 不完全符合 Perl 的正则表达式。目前，仅仅只有一个这样的特点，那就是在模式中的任何的反斜杠后加一个字符就没有特殊的意义并导致匹配失败和设置 ErrorLevel 相应的值。这个选项帮助保留未使用的反斜杠序列供以后使用。没有这个选项，反斜杠后的字符就会看成一般的字符而没有特殊的意义 (例如：\g 和 g 都被认为是字母 g )。不论此选项怎样，非字母反斜杠序列都没有特别的意义，它将总是认为是普通的字符 (例如：\/ 和 / 都被认为是 / )。
P | 位置模式。它会使函数 RegExMatch() 产生匹配到的子串的位置和长度。更详细的了解，请看上面的 输出变量。
S | 研究模式可以提高函数的性能。当匹配模式比较复杂或者被重复执行很多次的情况下，这个选项很有用。它会让匹配模式存储在高速缓存中，以便下次使用，通过这种方法来提高了正则表达式的性能。
`n | 替换默认的换行符 (`r`n) 为符合 UNIX 系统的标准的 (`n)。所选择的换行符会影响到 anchors (^ and $) 和 dot/period pattern 。
`r | 替换默认的换行符 (`r`n) 为符合 Windwos 标准的 (`r)。
`a | 在 1.0.46.06+ 的版本中，`a 看作是换行符，也就是指这些符号，`r，`n，`r`n，`v/VT/vertical tab/chr(0xB)，`f/FF/formfeed/chr(0xC)，and NEL/next-line/chr(0x85)。在 1.0.47.05+ 的版本中，换行符被限制为 CR，LF 和 CRLF 为 (*ANYCRLF) ，在选项后的正则表达式之前大写；例如： im)(*ANYCRLF)^abc$

注意：可用空格和 Tab 随意的隔开每个选项。

性能

如果从一个较长的字符串中搜索一个简单的子串，请使用 InStr() 函数，因为它比 RegExMatch() 更有效率。

为了提高性能，它将最近使用的 100 个正则表达式缓存在内存里 (在编译的时候)。

当一个正则表达式重复使用的情况下，使用 S 选项 来提高性能。(比如在 loop 循环中)

注意

一个命名子模式都有一个名字，如上文模式 (?P<Year>\d{4}) 中的 Year 。这些名字可能包括多达 32 个字母、数字和下划线。虽然这些命名子模式都是通过数字在对正则表达式本身的操作 (如：向后引用)，结果是仅仅用名字存储 输出数组，而不是用数字。例如 "Year" 是第一个名字，把匹配到的子串存储在 OutputVarYear 里，但是 OutputVar1 的值是没有改变 (它将保留以前的值，如果有的话)。如果是 非命名子模式 的 "Year" ，它将匹配到的子串存储在 OutputVar2 里，而不是 OutputVar1 里。

大多数的字符串 ( 像 abc123 ) 就能用一般的字符来匹配。而匹配像 \.*?+[{|()^$ 这样被保护的字符就要在其前面加是一个反斜杠。比如：\. 代表一个点，\\ 代表一个反斜杠。转义符可避免使用 \Q…\E。比如 \QLiteral Text\E。

在正则表达式中，一些特殊的字符，如制表符和换行符就用重音符号 (`) 或反斜杠 (\) 来表示。例如：`t is the same as \t 。

如学习正则表达式的基础 (或者重新记忆一下正则表达式的语法) ，请看 RegEx Quick Reference。

AutoHotKey 所使用的正则表达式是来自于 www.pcre.org 的兼容 Perl 语言的正则表达式。

相关命令

RegExReplace(), RegEx Quick Reference, InStr(), IfInString, StringGetPos, SubStr(), SetTitleMatchMode RegEx, Global matching and Grep (forum link)

Common sources of text data: FileRead, UrlDownloadToFile, Clipboard, GUI Edit controls

示例

FoundPos := RegExMatch("xxxabc123xyz", "abc.*xyz")  ; 返回值 4，它就是匹配到的位置。
FoundPos := RegExMatch("abc123123", "123$")  ; 返回值 7，因为 $ 要求从靠近最后的字符处开始匹配。
FoundPos := RegExMatch("abc123", "i)^ABC")  ; 返回值 1，因为是要求从第一个字符处开始匹配，而且不区分大小写。
FoundPos := RegExMatch("abcXYZ123", "abc(.*)123", SubPat)  ;返回 1 并且 SubPat1 的值是 "XYZ"。
FoundPos := RegExMatch("abc123abc456", "abc\d+", "", 2)  ; 返回值 7 ，由于它是从第二个字符开始匹配的。

; 更多正则表达式的例子，请看 RegEx Quick Reference.


RegExReplace

RegExReplace() [v1.0.45+]

替换字符串中匹配模式 (正则表达式) 出现的地方.

NewStr := RegExReplace(Haystack, NeedleRegEx [, Replacement = "", OutputVarCount = "", Limit = -1, StartingPosition = 1])

参数

NewStr | RegExReplace() 返回内容被替换过的 Haystack 的一个版本. 如果没有替换操作发生, Haystack 保持不变. 如果遇到错误 (例如 NeedleRegEx 出现语法错误 ), Haystack 保持不变 (此时早于 1.0.46.06 的版本会返回 "") 同时 ErrorLevel 被设置为 下列 值的其中一个而不是 0.
Haystack | 源字符串.
NeedleRegEx | 此匹配模式是和 Perl 兼容的正则表达式 (PCRE). 如果需要, 可以在正则表达式前加上 选项, 并以 ")" 结束. 例如, 匹配模式 "i)abc.*123" 将匹配不区分大小写的 "abc", 接着0个或多个任意字符, 并以 "123" 结尾的字符串. 如果不含选项, ")" 是可选的; 例如, ")abc" 相当于 "abc".
Replacement

用于替换每个匹配的字符串, 它是普通的文本 (不是正则表达式). 此参数可以包含像 $1 这样的后向引用, 它引用了 Haystack 中匹配首个 子模式 的子字符串. 最简单的后向引用是从 $0 到 $9, 这里 $0 是匹配整个模式的子字符串, $1 是匹配首个子模式的子字符串, $2 是第二个, 依此类推. 对于大于 9 的后向引用(对于小于 9 的那些, 这是可选的), 需要把数字括在大括号中; 例如 ${10}, ${11}, 等等. 对于 命名子模式, 需要将名称括在大括号中; 例如 ${SubpatternName}. 要指定原义的 $, 请使用 $$ (这是唯一需要特殊处理的字符; 反斜杠不需要转义).

要转换子模式的大小写, 请在 $ 后跟着下列字符的其中一个: U 或 u (大写), L 或 l (小写), T 或 t (标题格式, 此时每个单词的首个字母大写, 而其他的所有字母改成小写). 例如, $U1 和 $U{1} 都会把首个子模式转换成大写的版本.

不存在的后向引用和不匹配 Haystack 中任何字符串的模式 -- 例如 (abc)|(xyz) 其中一个子模式 -- 被转译为空字符串.
OutputVarCount | 此参数是不引用的变量名(即不需要使用百分号包围), 它用于保存替换的次数(如果没有则为 0).
Limit | 如果 Limit 省略, 默认值为 -1, 此时会替换 Haystack 中 所有 发现匹配模式的地方. 否则, 请指定允许替换的最大次数. Haystack 最后一次替换右边的部分保持不变.
StartingPosition

如果 StartingPosition 省略, 默认值为 1 (从 Haystack 的第一个字符开始). 否则, 从第二个字符开始请指定 2, 第三个字符指定 3, 依此类推. 如果 StartingPosition 超过了 Haystack 的长度, 搜索会从 Haystack 的结尾后的空字符串开始 (这是导致没有替换发生的常见情况).

如果 StartingPosition 小于 1, 函数会认为是从 Haystack 末尾处开始. 例如, 0 从最后一个字符开始, -1 则从倒数第二个字符开始. 如果 StartingPosition 超过了 Haystack 最左边的位置, 它会搜索整个 Haystack.

不论 StartingPosition 的值是什么, 返回值总是 Haystack 的完整副本 -- 唯一的区别是比起 StartingPosition 为 1 时发生的情况此时源字符串左边可能更多的部分保持不变.

ErrorLevel

ErrorLevel 被设置为下列值的其中一个:

  • 0, 表示没发现错误.
  • 一个如下格式的字符串: Compile error N at offset M: description. 在此字符串中, N 是 PCRE 错误值, M 正则表达式中出现错误的字符的位置, 而 description 是描述这个错误的文本信息.
  • 一个负数, 表示在正则表达式 执行 时遇到的错误. 尽管这种错误非常罕见, 像这些情况就容易出现这种错误 "太多空字符串匹配" (-22), "递归太深" (-21), 和 "达到匹配限制" (-8). 如果出现上述情况, 请尝试重新设计更严格的匹配模式, 例如使用一个 ?, +, 或一个像 {0,3} 这样的限制代替每个 *, 不管是否可行.

选项

关于修饰符请参见 选项, 例如 "i)abc", 此选项会使得模式 "abc" 进行不区分大小写的匹配.

性能

简单的字符串替换, 请使用 StringReplace 命令因为它比 RegExReplace() 执行的更快.

如果您知道替换的最大次数是多少, 请在 Limit 参数中指定来提高性能因为这样可以早一些停止搜索 (这样也可能会降低在替换操作过程中占用的系统内存). 例如, 如果您知道在一个大字符串开始处仅有一个匹配, 请指定最大次数为 1.

为了提高性能, 它将最近使用的 100 个正则表达式缓存在内存里 (在已编译的形式中).

多次使用一个正则表达式时, 使用 研究选项 (S) 可以提高性能 (例如在一个循环中).

备注

大多数字符例如 abc123 可以直接使用于正则表达式中. 而 \.*?+[{|()^${/2} 这些字符必须在其前面加上反斜杠来进行匹配. 例如, \. 匹配一个原义的句号, \\ 匹配一个原义的反斜杠. 使用 \Q...\E 可以避免转义. 例如: \QLiteral Text\E.

在正则表达式中, 特殊字符如制表符和新行符可以使用一个重音符 (`) 或反斜杠 (\) 进行转义. 例如, `t 等同于 \t.

要了解正则表达式的基础 (或重新记忆正则表达式语法), 请参看 正则表达式快速参考.

相关

RegExMatch(), RegEx Quick Reference, StringReplace, InStr()

文本数据的通常来源: FileRead, UrlDownloadToFile, Clipboard, GUI Edit controls

示例

NewStr := RegExReplace("abc123123", "123$", "xyz")  ; Returns "abc123xyz" because the $ allows a match only at the end.
NewStr := RegExReplace("abc123", "i)^ABC")  ; Returns "123" because a match was achieved via the case-insensitive option.
NewStr := RegExReplace("abcXYZ123", "abc(.*)123", "aaa$1zzz")  ; Returns "aaaXYZzzz" by means of the $1 backreference.
NewStr := RegExReplace("abc123abc456", "abc\d+", "", ReplacementCount)  ; Returns "" and stores 2 in ReplacementCount.

; For general RegEx examples, see the RegEx Quick Reference.


RegisterCallback

RegisterCallback() [v1.0.47+]

创建一个机器码地址(machine-code address)。当它被调用时，会将调用重定向至脚本中的一个 函数 。

Address := RegisterCallback("FunctionName" [, Options = "", ParamCount = FormalCount, EventInfo = Address])

参数

Address | 若成功，RegisterCallback() 返回一个数值地址(numeric address)，可以被 DllCall() 或任何有能力调用机器码函数的其他东西调用。若失败，会返回一个空字符串。失败的原因是当 FunctionName: 1) 不存在； 2) ParamCount 接受太多或太少的参数；或 3) 接受任何的 ByRef 参数.
FunctionName | 一个 函数 的名字，如果是一个原意的(literal)字符串，必须用引号引起来。只要 Address 被调用，这个函数就会被自动调用。函数还会接收到传给 Address 的参数。
Options | 指定下列中零个或更多个单词。用空格隔开每一个选项（例如 "C Fast"）。 Fast 或 F: 避免每次 FunctionName 被调用时创建新 线程 。 这会提升效率，但必须避免调用 Address 的线程发生变化 （例如：当回调函数被新来的消息触发）. 这是因为 FunctionName 被调用时可以为每一个即将运行的线程改变全局设置如 ErrorLevel, A_LastError，还有 上一次找到的窗口。要获得更多信息，参见 注意事项. CDecl 或 C ：让 Address 遵守 "C" 调用约定。此选项通常省略，因为标准调用约定更常用于回调函数。
ParamCount | Address 的调用者将传递的参数数量。如果全部省略，默认为 FunctionName 函数定义 中 强制参数(mandatory parameters) 的数量。无论如何都要确保调用者会确切地传递此数量的参数。
EventInfo | 一个 0 与 4294967295 之间的整数。只要 FunctionName 是通过这个 Address 被调用的， 它就可以在 A_EventInfo 中看到。当 FunctionName 是通过多个 Address 被调用时这是很有用的。如果省略，默认为 Address。注释：与其他全局设置不同，当前线程的 A_EventInfo 不会被 fast mode 打乱。

回调函数的参数

一个分配了回调地址的 函数 最多可接受 31 个参数。允许有 可选参数 ，当函数被多个调用者调用时这是很有用的。

所有 传入参数(incoming parameters) 都必须是一个 0 到 4294967295 之间的整数。如果一个传入参数应该是有符号的，以下例子可以展现任何的负值：

if wParam > 0x7FFFFFFF
    wParam := -(~wParam) - 1

如果一个传入参数应该是一个字符串，可以通过复制这个字符串来接收。例如：

VarSetCapacity(MyString, DllCall("lstrlen", UInt, MyParameter))  ; 如果MyString已经足够大，则不必如此。
DllCall("lstrcpy", Str, MyString, UInt, MyParameter)  ; 复制字符串到脚本的 MyString 变量。
VarSetCapacity(MyString, -1)  ; 更新内部存储的变量长度以反映出新内容。

如果一个传入参数是结构体的地址，参照 DllCall 结构体 中的步骤可以展开其内部成员。

函数应该 返回 什么

如果函数使用不带参数的 Return，或者指定了一个空值例如 "" （或者根本不使用 Return）， 0 将被返回给 Address 的调用者。否则，函数应该返回一个 -2147483648 与 4294967295 之间的整数，它将会被返回给 Address 的调用者。

快速模式与慢速模式(Fast vs. Slow)

默认/慢速 模式(default/slow mode) 让函数全新地以设置（比如 SendMode 和 DetectHiddenWindows）的默认值启动。这些默认值可以在 自动执行部分 中被修改。

相比之下，快速模式(fast mode) 在函数被调用时会从任何即将运行的 线程 上继承全局设置。而且，函数对全局设置的任何修改（包括 ErrorLevel 和 上一次找到的窗口） 都将在 当前线程 中生效。因此，快速模式应该只在确切地知道函数会被哪个线程调用的情况下才去使用。

要避免被自己（或任何其他的线程）中断，一个回调函数可以在第一行使用 Critical。然而，当函数因小于 0x312 的消息的到来而被间接调用时，这并不是完全有效的 (增加 Critical 的 interval(时间间隔) 可能有帮助)。而且， Critical 不会阻止函数做一些可能引起调用它自己的事，如调用 SendMessage 或 DllCall。

内存

每次使用 RegisterCallback() 会分配少量的内存 (32 个字节加上系统开销)。由于在脚本退出时操作系统会自动释放这段内存，任何分配数量少而固定的回调地址的脚本无须显式地释放内存。相比之下，一个调用 RegisterCallback() 次数 不确定/无限 的脚本应该显式地对任何不再需要的回调地址调用以下函数： DllCall("GlobalFree", UInt, Address)

相关命令

DllCall(), OnMessage(), OnExit, OnClipboardChange, Sort 的回调函数, Critical, Post/SendMessage, Functions(函数), Windows 消息列表, Threads(线程)

示例

; 示例：下面是一个可用脚本，显示所有顶层窗口的摘要。

; 为了提升性能和保护内存，只为一个回调地址调用一次 RegisterCallback() ：
if not EnumAddress  ; 可以用快速模式，因为它只会被这个线程调用：
    EnumAddress := RegisterCallback("EnumWindowsProc", "Fast")

DetectHiddenWindows On  ; 由于是快速模式，这个设置也会在回调函数中生效。

; 将控制权交给 EnumWindows()，它会反复调用回调函数：
DllCall("EnumWindows", UInt, EnumAddress, UInt, 0)
MsgBox %Output%  ; 显示由回调函数收集的信息：

EnumWindowsProc(hwnd, lParam)
{
    global Output
    WinGetTitle, title, ahk_id %hwnd%
    WinGetClass, class, ahk_id %hwnd%
    if title
        Output .= "HWND: " . hwnd . "`tTitle: " . title . "`tClass: " . class . "`n"
    return true  ; 告诉 EnumWindows() 在所有窗口被列举完之前继续。
}

; 示例：下面是一个可用脚本，演示如何在脚本中通过
; 重定向一个窗口的 WindowProc(窗口过程函数) 到一个新的 WindowProc 来 subclass(子类化) 一个 GUI 窗口。
; 在这个例子中，文本控件的背景色会被更改成自定义的颜色。

TextBackgroundColor := 0xFFBBBB  ; BGR 格式的自定义颜色。
TextBackgroundBrush := DllCall("CreateSolidBrush", UInt, TextBackgroundColor)

Gui, Add, Text, HwndMyTextHwnd, 这里有一些带自定义背景色的文字。
Gui +LastFound
GuiHwnd := WinExist()

WindowProcNew := RegisterCallback("WindowProc", ""  ; 指定 "" 以避免为子类化使用快速模式。
    , 4, MyTextHwnd)  ; 当给出 EventInfo 参数时必须精确地指定 ParamCount。
WindowProcOld := DllCall("SetWindowLong", UInt, GuiHwnd, Int, -4  ; -4 是 GWL_WNDPROC
    , Int, WindowProcNew, UInt)  ; 返回值必须指定为 UInt 而不是 Int.

Gui Show
return

WindowProc(hwnd, uMsg, wParam, lParam)
{
    Critical
    global TextBackgroundColor, TextBackgroundBrush, WindowProcOld
    if (uMsg = 0x138 && lParam = A_EventInfo)  ; 0x138 是 WM_CTLCOLORSTATIC.
    {
        DllCall("SetBkColor", UInt, wParam, UInt, TextBackgroundColor)
        return TextBackgroundBrush  ; 返回 HBRUSH 以通知操作系统我们改变了 HDC。
    }
    ; 否则（如果上面的代码不返回），将所有不需要处理的消息传递给原先的 WindowProc.
    return DllCall("CallWindowProcA", UInt, WindowProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
}

GuiClose:
ExitApp


VarSetCapacity()

增大或释放一个变量所占据的内存空间。通常，这只在特殊情况才有必要，如 DllCall 。

GrantedCapacity := VarSetCapacity(UnquotedVarName [, RequestedCapacity, FillByte])

参数

GrantedCapacity | 现在变量所占据（可自由使用）的字符串长度，会大于等于 RequestedCapacity 。如果 VarName 不是一个合法的变量名（比如是一个原意的字符串或数字），将返回 0 。如果系统没有足够的内存完成更改（非常罕见），将显示一个错误框，随后 当前线程 会退出。
UnquotedVarName | 变量名（没有引号）。举个例子： VarSetCapacity(MyVar, 1000) 。这也可以是个动态变量例如 Array%i% 或一个 函数的引用(ByRef)参数。
RequestedCapacity

如果省略，将返回变量的当前容量且其内容不变。否则，变量内的所有内容将丢失（变量会变空）。

指定 RequestedCapacity 为变量在调整后应该能够占据的字符串长度。该长度不包括内部的零结束符。举个例子，指定 1 将允许变量占有最多一个字符外加零结束符。注：若以后脚本为该变量分配一个更大的值，它将自动扩展。

经常调用该函数可以简单地确保变量拥有一个最小容量，由于性能原因，该函数只在 RequestedCapacity 为 0 时缩小变量的容量。换句话说，如果变量的容量已经大于 RequestedCapacity ，则不会减小（不过为了保持一致，变量仍然会变空）。

因此，要明确地缩小一个变量，首先用 VarSetCapacity(Var, 0) 释放它的内存，然后用 VarSetCapacity(Var, NewCapacity) —— 或者简单地让它根据需要从零自动扩展。

由于性能原因，释放一个原先容量在 1 与 63 之间的变量可能没有效果，因为它的内存是永久性的。在这种情况下，函数将返回当前容量而不是 0 。

由于性能原因，将空字符串赋值给一个容量小于 4096 的变量将不会释放它的内存（如 Var := ""）。然而，VarSetCapacity(Var, 0) 会释放。

在 v1.0.44.03 及以后版本中，指定 RequestedCapacity 为 -1 可以将变量内部存储的长度更新为当前内容的长度。在变量会被间接修改的地方这很有用，例如通过 DllCall() 传入它的 地址。在这种模式下，VarSetCapacity() 会返回变量的长度而不是容量。
FillByte | 该参数通常省略，表示目标变量的内存不会被初始化（或者说，变量只是简单地像前面说的那样被置空）。否则，指定一个 0 到 255 之间的数。目标变量内存区域（它的当前容量）内的每一个字节都会被设为该数。0 是目前为止最常用的值，在将要存放原始二进制数据到变量里（比如一个 DllCall 结构体 ）的地方这是很有用的。

注意

关于它的用法除了在 DllCall 中所描述的以外，该函数还可以用于提升用逐步串联的方法构造一个字符串时的性能。这是因为当你可以确定字符串的最终大小时可以避免多次的自动大小调整。在这种情况下， RequestedCapacity 不必太精确：如果容量太小，仍然能够提升性能，并且当容量耗尽时变量会开始自动扩展。如果容量太大，会浪费一些内存，不过只是暂时的，因为在操作完成之后可以通过 VarSetCapacity(Var, 0) 或 Var := "" 等方法来释放所有的内存。

#MaxMem 只会限制一个变量主动地自动扩展。它不会影响 VarSetCapacity 。

相关命令

DllCall, #MaxMem

示例

VarSetCapacity(MyVar, 10240000)  ; ~10 MB
Loop
{
    ...
    MyVar = %MyVar%%StringToConcatenate%
    ...
}


GUI

创建和管理窗口和控件. 这种窗口可以用作数据输入窗体或自定义用户界面.

Gui, sub-command [, Param2, Param3, Param4]

目录

  • Add: 创建控件例如文本, 按钮或复选框.
  • Show: 显示窗体. 同时可以最小化, 最大化或移动窗体.
  • Submit: 保存用户的输入并可以隐藏窗体.
  • Cancel (或 Hide): 隐藏窗体.
  • Destroy: 销毁窗体.
  • Font: 为后续创建的控件文本设置文字的字体, 大小, 风格和颜色.
  • Color: 设置窗体和/或其控件的背景颜色.
  • Margin: 设置在没有为控件指定明确的位置时使用的边距/间隔.
  • 窗体的选项和风格: 为窗体的外观和行为设置各种选项.
  • Menu: 添加或移除菜单.
  • Minimize / Maximize / Restore: 对窗口执行指示的操作.
  • Flash: 闪烁窗口及其任务栏按钮.
  • Default: 改变当前线程的默认 GUI 窗体编号.
  • 控件的定位和大小设置
  • 保存和响应用户的输入: 变量和 g-label
  • 控件的选项和样式
  • 窗体事件: GuiClose | GuiEscape | GuiSize | GuiContextMenu | GuiDropFiles
  • 创建多个 GUI 窗体
  • GUI 事件, 线程和子过程
  • 其他操作: 键盘导航 | 窗体外观 | 一般说明
  • 示例: 包含演示 GUI 窗体和控件的有效脚本

Gui, Add, ControlType [, Options, Text]

添加控件到 GUI 窗体 (必要时首先创建 GUI 窗体).

ControlType 可以是下列的其中一个:

  • Text, Edit, UpDown, Picture
  • Button, Checkbox, Radio
  • DropDownList, ComboBox
  • ListBox, ListView, TreeView
  • Hotkey, DateTime, MonthCal
  • Slider, Progress
  • GroupBox, Tab, StatusBar, Internet Explorer Control

例如:

Gui, Add, Text,, Please enter your name:
Gui, Add, Edit, vName
Gui, Show

Gui, Show [, Options, Title]

如果没有在 Options 中明确指定, 此命令会让窗体以可见, 非最小化 (必要时), 激活 并设置它的标题的状态显示. 如果省略了 Title, 则保留原来的标题 (如果没有, 则使用脚本的文件名称).

省略后面的 X, Y, W 和 H 选项则让窗体保持原来的大小和位置. 如果没有原来的位置, 则在后面提到的 X 和/或 Y 选项没有指明的坐标上窗体将自动居中. 如果没有原来的大小, 则窗体会根据它所包含控件的大小和位置自动调整大小.

在 Options 中可以包含零或多个下列字符串 (规定其中的每个数字为十进制, 而不是十六进制):

Wn: 指定 n 为窗体客户区 (客户区指除窗体边框, 标题栏和 菜单栏 的区域) 的宽度 (单位为像素).

Hn: 指定 n 为窗体客户区的高度, 单位为像素.

Xn: 指定 n 为窗体在屏幕中的 X 坐标, 单位为像素. 0 表示屏幕最左边首列可见像素的位置.

Yn: 指定 n 为窗体在屏幕中的 Y 坐标, 单位为像素. 0 表示屏幕最上边首行可见像素的位置.

Center: 让窗体在屏幕上水平和垂直方向居中.

xCenter: 让窗体在屏幕上水平方向居中. 例如: Gui, Show, xCenter y0

yCenter: 让窗体在屏幕上垂直方向居中.

AutoSize: 根据窗体当前包含的可见控件调整窗体的大小. 这在添加一个新控件, 或重新设置现有控件的大小, 或隐藏/显示现有控件后调整窗体的大小很有用. 例如:
Gui, Show, AutoSize Center

还可以包含下列参数的其中一个:

Minimize: 最小化当前窗体并激活下一个窗口.

Maximize: 最大化并激活窗体.

Restore: 当窗体最小化或最大化时, 还原窗体. 当窗体隐藏和不活动时, 显示并激活窗体.

NoActivate: 当窗体最小化或最大化时, 还原窗体. 显示但不激活窗体.

NA: 显示但不激活窗体. 如果窗体处于最小化状态, 它将仍保持这种状态但可能提升其 z-order (这是在 alt-tab 选择器中看到的顺序). 如果窗体之前是隐藏的, 此参数可能会让它显示在当前仍处于活动状态的窗口上面.

Hide: 隐藏窗体并激活下一个窗口. 除了允许窗体被移动, 重设大小或在不显示的情况下设置新的标题外, 此参数与 Gui Cancel 的效果相同. 例如: Gui, Show, Hide x55 y66 w300 h200, New Title

Gui, Submit [, NoHide]

保存每个控件的内容到其 关联变量 中 (如果有的话) 并且在没有使用 NoHide 选项时隐藏窗体. 对于那些产生多个字段输出的控件, 例如 多选列表框, 输出结果会使用窗体的 当前分隔符 来分隔多个字段的内容. 如果由于之前使用 Gui Destroy 销毁了窗体或其他原因使得窗体不存在, 此命令没有效果.

Gui, Cancel

隐藏当前窗体, 并不保存控件的内容到其 关联变量 中. 如果由于之前使用 Gui Destroy 销毁了窗体或其他原因使得窗体不存在, 此命令没有效果.

Gui, Destroy

移除当前窗体 (如果它存在的话) 及其所有控件, 并释放其占用的内存和系统资源. 如果脚本之后再创建窗体, 那么窗体的所有属性例如颜色和字体初始都为默认值 (如同窗体从没有出现过). 如果没有使用 Gui Destroy, 则当脚本退出时会自动销毁所有的 GUI 窗体.

Gui, Font [, Options, FontName]

为在此处之后创建的控件设置字体字型, 大小, 样式和/或颜色. 例如:

gui, font, s10, Verdana  ; Set 10-point Verdana.

省略最后两个参数可以让字体恢复为系统默认的 GUI 字型, 大小和颜色.

FontName 可以是任意字体的名称, 例如 字体表 中的一个. 如果省略了 FontName 或此字体在系统中不存在, 则设置为之前的字体字型 (如果没有, 则为系统默认的 GUI 字型). 即使某些系统缺少首选字体, 这种特性也可以让窗体在多个系统上具有类似的字体. 例如, 按顺序执行下列命令, Verdana 字体优先于 Arial, 而 Arial 字体优先于 MS sans serif:

gui, font,, MS sans serif
gui, font,, Arial
gui, font,, Verdana  ; 首选字体.

如果 Options 参数为空, 则使用之前的字体属性. 或者可以在其中指定下列的一个或多个选项字母:

C: 颜色名称 (参见 颜色图表) 或 RGB 值 -- 或指定单词 Default 来使用系统默认的颜色 (大多数系统上默认颜色为黑色). 例如: cRed, cFFFFAA, cDefault. 注意: Buttons 不受自定义颜色的影响. 此外, 通过包含 C 选项创建带有字体颜色的一些控件时不会受到当前选项的影响. 例如: Gui, Add, Text, cRed, My Text

S: 字体大小 (单位为磅). 例如: s12 (规定为十进制, 而不是十六进制)

W: 字体粗细, 这是介于 1 和 1000 之间的数字 (400 为标准大小而 700 为粗体). 例如: w600 (规定为十进制而不是十六进制)

还支持使用下列单词: bold, italic, strike, underline 和 norm. 指定 Norm 则让字体恢复标准的粗细并去除斜体, 删除线和下划线效果 (但保持现有的颜色和大小). 可以使用 norm 去除所有属性然后有选择的设置其他属性. 例如, 指定 norm italic 将设置字体为标准然后增加斜体属性.

要指定多个选项, 在选项间使用空格分隔. 例如: cBlue s12 bold

如果一个脚本创建了 多个 GUI 窗体, 那么其中的每个窗体都会记住它自己的 "当前字体" 属性, 可以用于后面创建的控件.

相关提示, 操作系统提供了标准的对话框, 可以让用户选取字体, 颜色或图标. 通过 DllCall() 可以显示这些对话框, 演示例子参见 www.autohotkey.com/forum/topic17230.html.

Q: [AHK_L 19+]: 文本描绘品质. 例如: q3. Q 后应该跟着下面表格中的一个数字:

0 = DEFAULT_QUALITY | 保持字体外观.
1 = DRAFT_QUALITY | 字体外观没有使用 PROOF_QUALITY 值那么重要.
2 = PROOF_QUALITY | 字体的字符品质比准确符合逻辑字体属性更重要.
3 = NONANTIALIASED_QUALITY | 不对字体修边, 即不进行平滑处理.
4 = ANTIALIASED_QUALITY | 如果字体支持并且字体不会太小或太大时, 对字体进行修边或平滑.
5 = CLEARTYPE_QUALITY | Windows XP 或更高版本系统: 如果设置, 则使用 ClearType 抗锯齿方法描绘文本 (尽可能).

关于这些值的含义的更多细节, 参见 MSDN: CreateFont.

由于通常使用最好的品质作为默认设置, 此特性往往用于在特殊情况时禁用抗锯齿效果, 这样可以让文本更清晰.

Gui, Color [, WindowColor, ControlColor]

设置窗体和/或其控件的背景颜色. 设置 WindowColor 为 GUI 窗体自己的背景颜色. ControlColor 应用于窗体中所有现在的和将来的控件 (尽管某些类型的控件不支持自定义颜色). 尽管 ListViews 和 TreeViews 的初始背景颜色由当前的 ControlColor 决定, 但之后 ControlColor 颜色的改变不会影响它们. 这时应该使用 GuiControl +BackgroundFF9977, MyListView 来明确改变它们的背景颜色.

让两个参数中的某个留空可以保持当前的颜色设置. 否则, 指定 16 种 HTML 基础颜色 之一或一个 6 位的 RGB 颜色值 (0X 前缀可以省略), 或指定单词 Default 来恢复到默认的颜色. 例如: Silver, FFFFAA, 0xFFFFAA, Default

默认情况下, 窗体的背景颜色为系统按钮的颜色, 而控件的背景颜色为系统默认窗体颜色 (通常为白色).

菜单栏 及其子菜单的颜色这样可以改变, 例如: Menu, MyMenuBar, Color, White

在 Windows 2000/XP 或更高版本的系统中要使窗体的背景透明, 使用 WinSet TransColor. 然而, 如果在进行这样的操作前没有通过 "Gui, Color" 为窗体设置自定义的颜色, 那么按钮也将变成透明的. 要避免此问题, 应首先为窗体设置一个自定义的颜色然后让此颜色透明. 例如:

Gui, Color, EEAA99
Gui +LastFound  ; 让 GUI 窗体成为 最近找到的窗口 以用于下一行的命令.
WinSet, TransColor, EEAA99

此外如果要移除背景透明的窗体的边框和标题栏, 请在设置窗体为透明 后 使用下面的命令:

Gui -Caption  ; 如果是第二个窗体则使用 Gui, 2:-Caption, 等.

为了阐明上面的情况, 请参见此页面底部的屏幕显示 (OSD) 的例子.

Gui, Margin [, X, Y]

此命令用来为窗体上没有明确指定 X 或 Y 坐标 的控件设置在自动排列时距离窗体边界的距离, X 为控件距离窗体左/右边界的距离, Y 为控件距离窗体上/下边界的距离, 它们的单位为像素. 并且使用此边距设置自动排列控件彼此间在水平和垂直方向上的距离. 最后, 在首次使用 Gui Show 计算窗体的大小时也需要考虑此边距 (当没有明确指定窗体大小时).

如果没有使用此命令, 当添加首个控件到窗体时, 窗体会根据当前选择 字体 的大小按比例计算出默认的边距 (上下边距为字体高度的 0.75 倍, 而左右边距为字体高度的 1.25 倍).

尽管在添加控件的过程中可以改变边距, 但这仅影响后面添加的控件, 而不影响现有的. 最后, X 或 Y 的其中任意一个可以留空来保持相应的边距不变.

Gui, +/-Option1 +/-Option2 ...

在 GUI 命令后可以指定一个或多个选项. 考虑到效率的原因, 最好在创建窗体前 (即在使用任何其他子命令例如 Gui Add 之前) 使用一行语句指定所有的选项.

此命令的效果是累积的; 即它只改变那些明确指定的选项, 所有其他选项则保持不变.

在选项前指定一个加号表示增加此选项, 而减号表示移除它. 例如:

Gui +Resize -MaximizeBox  ; 改变 默认 GUI 窗体的设置.
Gui 2:+Resize -MaximizeBox  ; 改变第二个 GUI 窗体的设置.

AlwaysOnTop: 让窗体置顶, 和 "WinSet AlwaysOnTop" 的效果相同.

Border: 为窗体增加一个细边框. 此选项不常用.

Caption (默认具有此选项): 为窗体增加标题栏和一个粗边框. 如果要移除将使用 WinSet TransColor 设置透明的窗体的标题栏, 那么需要在设置 TransColor 后移除它.

Delimiter: 指定管道 (|) 外的其他字符作为窗体的字段分隔符, 每当通过 Gui Add 添加, 通过 GuiControl 修改或通过 Gui Submit 或 GuiControlGet 获取的控件内容含有多个字段时使用的分隔符. 在单词 Delimiter 后紧跟着单个字符. 例如, Gui +Delimiter`n 将使用换行符, 这可能特别适合于 字串分段. 同样, 使用 Gui +Delimiter| 将恢复为默认的分隔符. 要使用空格或 Tab, 指定 Gui +DelimiterSpace 或 Gui +DelimiterTab. 一旦改变数据分隔符, 它会影响作用于这个特殊窗体的所有现有和后续的 线程.

Disabled: 禁用窗体, 阻止用户和窗体中的控件交互. 此选项常用于含有子窗体的窗体 (参见 Owner).

Label [v1.0.44.09+]: 为当前窗体的 特殊标签 指定自定义名称. 例如, Gui 2:+LabelMyGui 将使用标签 MyGuiClose 和 MyGuiSize (如果它们存在的话) 代替 2GuiClose 和 2GuiSize. 换句话说, 在所有 特殊标签 的名称中字符串 "2Gui" 被替换为 "MyGui". 这样可以让多个窗体使用一套相同的标签 (此时脚本可以根据 A_Gui 变量确定运行的子程序的是哪个窗体).

LastFound: 设置窗体为 最近找到的窗口 (虽然对于 Gui 线程 这是多余的, 因为它自动设置了), 这样允许类似 WinSet 这样的命令对此窗口进行操作, 即使它当前为隐藏状态 (即不需要使用 DetectHiddenWindows). 需要在显示窗体之前改变其属性时, 这是非常有用的. 例如:

Gui +LastFound
WinSet, TransColor, %CustomColor% 150
Gui Show

LastFoundExist [v1.0.43.09+]: 和其他选项不同, LastFoundExist 选项只有在单独使用时才有效, 即在同一行中不能使用其他选项. +LastFoundExist 的效果与 +LastFound 相同, 除了如果窗口还不存在时不会创建窗口. 此选项的主要用途是判断指定的窗口是否存在. 例如:

Gui 2:+LastFoundExist
IfWinExist
    MsgBox GUI #2 already exists.

MaximizeBox: 启用标题栏上的最大化按钮. 下面的 Resize 选项也含有此效果.

MinimizeBox (默认含有此选项): 启用标题栏上的最小化按钮.

MinSize 和 MaxSize [v1.0.44.13+]: 限定窗体的最小尺寸和最大尺寸, 例如当用户拖动窗体边框改变其大小时. 指定不带后缀的单词 MinSize 和/或 MaxSize 来使用窗体当前尺寸作为限制大小 (如果没有窗体当前尺寸, 将使用首次 Gui Show 时显示的尺寸). 还可以在后面加上宽度, 后面跟着一个 X 和高度; 例如: Gui +Resize +MinSize640x480. 它们指定了以像素为单位的窗体客户区 (不包括边框, 标题栏和 菜单栏) 的大小. 指定每个数字为十进制, 而不是十六进制.

高度或宽度可以省略以保持不变 (例如 +MinSize640x 或 +MinSizex480). 而且可以多次指定 Min/MaxSize 以便在一个方向上使用窗体当前的尺寸而另一个则使用指定的大小. 例如, +MinSize +MinSize640x 表示最小高度限制为窗体当前的大小而最小宽度限制为 640.

如果从没使用 MinSize 和 MaxSize, 则使用操作系统的默认值 (同样地, 使用 Gui -MinSize -MaxSize 可以恢复为此默认值). 注意: 必须含有 +Resize 才能允许用户调节窗体的大小.

OwnDialogs: 在每个 线程 (例如 ButtonOK 子线程) 中指定 Gui +OwnDialogs, 这样所有后续的 MsgBox, InputBox, FileSelectFile 和 FileSelectFolder 对话框则会成为当前窗体的子窗体. 这时这些对话框成为模式对话框, 也就是说用户必须先关闭这些对话框才能和它们的父窗体进行交互. 与之相比, ToolTip, Progress 和 SplashImage 窗体即使成为其他窗体的子窗体也为非模式的; 它们仅仅是永远显示在其父窗体的上面. 在模式和非模式窗体两种情况中, 当它们的父窗体 销毁 时它们也会被自动销毁.

一般情况下打开这个设置后不需要再切换到关闭因为它不影响其他 线程. 但是, 如果一个线程需要同时显示从属和非从属对话框, 它可以通过 Gui -OwnDialogs 关闭此设置.

如果在前缀中没有指定窗体编号 -- 例如使用 Gui +OwnDialogs 而不是 Gui 2:+OwnDialogs -- 则当前 线程的默认窗体 将拥有这些从属的对话框.

Owner: 使用 +owner 可以让当前窗体从属于另一个窗体 (但一旦窗体创建后, -owner 则没有效果). 默认情况下一个从属的窗体不会显示在任务栏, 并且它总是显示在其父窗体的上面. 当其父窗体销毁时它也被自动销毁. 必须在父窗体创建 后 但在子窗体创建 前 (即在类似 Gui Add 这样的命令之前) 使用 +Owner. +owner 有两种使用方法, 如下所示:

gui, 2:+owner1  ; 让窗体 #2 成为窗体 #1 的子窗体.
gui, 2:+owner  ; 让窗体 #2 成为 脚本主窗口 的子窗体这样可以避免显示任务栏按钮.

当某个子窗体显示时要阻止用户与其父窗体交互, 请使用 Gui +Disabled 禁用父窗体. 之后 (当子窗体取消或销毁时), 通过 Gui -Disabled 重新启用父窗体. 在取消或销毁子窗体前这样做将使父窗体自动有效.

Resize: 此选项允许用户重新设置窗体的大小, 并启用标题栏上的最大化按钮. 要禁用最大化按钮, 请在选项中指定 +Resize -MaximizeBox.

SysMenu (默认含有此选项): 指定 -SysMenu (负 SysMenu) 可以删除点击窗体左上角时弹出的系统菜单和图标. 同时也删除标题栏上的最小化, 最大化和关闭按钮.

Theme: 指定 -Theme 可以让所有后续创建的控件在 Windows XP 以及更高版本的系统中使用经典主题外观. 之后要创建其他使用当前主题的控件时, 通过 +Theme 把设置切换回来. 注意: 此选项对 Windows XP 之前的操作系统无效, 如果 XP 系统当前使用经典主题则此选项也无效. 最后, 对于一些控件还可以通过在其选项中指定 +Theme 或 -Theme 来改变此设置.

ToolWindow: 让窗体显示细标题栏同时去除任务栏按钮.

(未命名样式): 在十进制或十六进制的 样式编号 前加上加号或减号表示添加或删除此样式.

(未命名扩展样式): 在字母 E 和十进制或十六进制的扩展样式编号前加上加号或减号表示添加或删除此扩展样式. 例如, +E0x40000 表示添加 WS_EX_APPWINDOW 样式, 此样式让窗体显示任务栏按钮. 尽管这里没有列出其他的扩展样式编号, 但可以通过在 www.microsoft.com 搜索 WS_EX_APPWINDOW 找到它们.

Gui, Menu [, MenuName]

为窗体增加一个菜单栏. 使用 Menu 命令可以创建一个普通的菜单. 例如:

Menu, FileMenu, Add, &Open    Ctrl+O, MenuFileOpen  ; 关于 Ctrl+O 参见后面说明.
Menu, FileMenu, Add, E&xit, MenuHandler
Menu, HelpMenu, Add, &About, MenuHandler
Menu, MyMenuBar, Add, &File, :FileMenu  ; 附加上面的两个子菜单.
Menu, MyMenuBar, Add, &Help, :HelpMenu
Gui, Menu, MyMenuBar

注意在首行中, &Open 后面跟着 Ctrl+O(它们之间用 Tab 分隔). 这表示用户可以按下快捷键代替选择菜单项来执行操作. 要在脚本中启用这样的快捷键, 请使用上下文相关热键:

#IfWinActive GUI Window's Title ahk_class AutoHotkeyGUI
^o::  ; 热键 Ctrl+O.
MenuFileOpen:
Gui +OwnDialogs  ; 强制用户在回到主界面前必须响应 FileSelectFile 对话框.
FileSelectFile, SelectedFile
MsgBox You selected the file %SelectedFile%.
return

; 如果脚本需要在 Windows 95/98/Me 系统上运行, 那么下面这部分是必须的:
#IfWinActive
$^o::Send ^o

要移除窗体当前的菜单栏, 请使用 Gui Menu (即省略最后一个参数).

一旦菜单被设置为窗体的菜单栏, 它就不能用于弹出菜单或子菜单. 这是因为在菜单栏内部使用了一种不同的格式 (不过这只限制菜单栏自身, 而不是其子菜单). 如果您一定要这样实现, 那么先创建一个菜单用于菜单栏, 再创建另一个相同的菜单用于其他目的.

对当前正用于菜单栏 (在某些情况下包括其子菜单) 的菜单使用某些破坏性的 菜单子命令 例如 Delete 和 DeleteAll 时, 这些命令会无效并显示出现错误对话框 (可以使用 UseErrorLevel 来避免). 可以使用下列步骤改变窗体菜单栏中的菜单: 1) 使用 Gui Menu (省略 MenuName) 让菜单从窗体中分离; 2) 改变菜单; 3) 通过 Gui, Menu, MyMenuBar 重新把菜单附加到窗体

Gui, Hide / Minimize / Maximize / Restore

"Gui Hide" 相当于 Gui Cancel. 其他三个命令则显示窗体 (必要时) 然后分别对窗体进行最小化/最大化/还原操作. 如果由于之前使用 Gui Destroy 销毁了窗体或其他原因使得窗体不存在, 这些命令没有效果.

Gui, Flash [, Off]

闪烁窗体的任务栏按钮. 这是通过反转窗体的标题栏和/或任务栏按钮 (如果有的话) 的颜色实现的. 可以加上选项 OFF 让标题栏和任务栏按钮恢复到它们最初的颜色 (但实际效果可能受操作系统版本影响). 在下面的例子中, 窗体将闪烁三次, 因为每对闪烁都会在对它们反转后恢复原来的外观:

Loop 6
{
    Gui Flash
    sleep, 500  ; 这个时间值十分敏感; 改变它可能引起异常.
}

Gui, 2:Default

改变 当前线程 的默认 GUI 窗体编号, 这是在没有指定窗体编号时用于 GuiControl, GuiControlGet 和 Gui 命令自身的默认窗体. 下面这个例子把默认窗体编号改为 2: Gui 2:Default. 参见 线程的默认窗体 了解关于默认窗体的更多细节.

通过 SmartGUI Creator 创建窗体布局

虽然下一段中描述了简单的布局选项, 但您会发现使用 Rajat 的 SmartGUI Creator 来创建会更简单因为它是完全可视化的; 即 "所见即所得". SmartGUI Creator 是免费的, 可以从 www.autohotkey.com/docs/SmartGUI/ 下载.

控件的位置和大小

如果在 Options 中省略了某些尺寸和/坐标, 则会根据前一个控件确定其位置, 根据控件的类型和内容确定大小.

支持下列选项:

R: 指定文本的行数 (可以为浮点数如 R2.5). 使用 R 通常比 H (高度) 更合适. 如果同时指定 R 和 H 选项, 则 R 优先考虑. 对于 GroupBox, 此选项设置在框中可以容纳的控件数量. 对于 DropDownList, ComboBox 和 ListBox, 此选项设置在控件的列表部分一次可以看见的项目数目 (但在 Windows XP 及更高版本系统中, 对于 DropDownList 和 ComboBox 控件常常同时省略 R 和 H 选项, 这样可以让弹出的列表自动设置为用户桌面的可用高度). 对于其他类型的控件, R 表示控件内可见的文本行数.

W: 宽度, 单位为像素. 如果省略, 对于某些控件则根据其内容自动计算宽度. 其他类型的控件具有下列默认的宽度值:
标签页控件: 30 倍的当前字体大小加上 3 倍的 X-margin (行边距).
垂直进度条: 两倍的当前字体大小.
水平进度条, 水平滑动条, DropDownList, ComboBox, ListBox, GroupBox, Edit, and Hotkey: 15 倍的当前字体大小 (GroupBoxe 例外, 其默认宽度为 18 倍这样可以显示内部的边距).

H: 高度, 单位为像素. 如果 H 和 R 选项同时省略, 则 DropDownList, ComboBox, ListBox 和初始内容为空的多行 Edit 控件默认为 3 行; GroupBox 默认为 2 行; 垂直滑动条和进度条默认为 5 行; 水平滑动条默认为 30 像素 (没有指定其厚度时); 水平进度条默认为 2 倍的当前字体大小; Hotkey 控件默认为 1 行; 而 Tab 控件默认为 10 行. 对于其他类型的控件, 则根据它们的内容自动计算高度. 请注意对于 DropDownList 和 ComboBox, H 为控件总是可见的部分 (大概指列表上面的框) 和其列表部分相加的高度 (但即使高度设置很小, 也会在下拉列表中至少显示一个项目). 同时对于所有类型的控件, 通过 R 选项指定行数比使用 H 更可取, 因为这样可以避免在控件中显示部分/不完整的文本行.

wp+n, hp+n, wp-n, hp-n (其中 n 可以为任意数字) 可以用来设置控件的宽度和/或高度等于前一个添加控件的宽度或高度, 可以使用加号或减号进行调整. 例如, wp 将设置控件的宽度等于之前的控件, 而 wp-50 则设置宽度为之前的控件宽度减去 50 像素.

X: 控件的 X 坐标. 例如, 指定 "x0 y0" 则把控件放置到窗体客户区的左上角, 窗体客户区是在标题栏和菜单栏 (如果有的话) 下面的区域. 如果省略了 X 但指定了 Y, 则控件将被放置在之前所有控件的右边 (即其 X 坐标为前一个控件的 X 坐标加上前一个控件的宽度, 即前一个坐标右边的位置), 可以理解为开始了一个新 "列".

Y: 控件的 Y 坐标. 如果省略了 Y 但指定了 X, 则控件将被放置在之前所有控件的下面 , 可以理解为开始了一个新 "行".

X, Y 的其中一个或同时省略时, 可以在您对控件的大小或字体进行改变时自动调整 GUI 布局. 与之相比, 如果为每个控件指定了绝对位置则当一个控件扩大或减小时需要为在此控件下面和/或右边的所有控件手动调整位置.

如果同时省略 X 和 Y, 则控件会放置在之前控件的下面, 中间加上标准的填充间距.

对于 X 和 Y, 还可以在后面加上一个加号来确定控件相对于前一个添加控件的右边或底部边缘 (分别地) 的位置. 例如, 指定 Y+10 将把控件放置在前一个控件底部下面 10 个像素的位置, 而不使用标准的填充间距. 同样地, 指定 X+10 将把控件放置在前一个控件右边缘的右边 10 个像素的位置. 由于负数例如 X-10 表示绝对的位置, 因此要使用一个负的位置偏移, 需要在前面加上一个加号. 例如: X+-10

xp+n, yp+n, xp-n, yp-n (其中 n 可以为任意数字) 可以用来指定控件相对于前一个控件左上角的位置, 此选项常用于 GroupBox 中的被封装控件.

xm 和 ym 分别可以把控件放置在窗体最左边和最上边的 边缘 (它们后面还可以跟着一个加号/减号和一个数字). 指定 ym 而省略 X 坐标, 将把控件放置在窗体的最上面但在之前所有控件的右边, 可以理解为开始了一个新 "列". 反之亦然.

xs 和 ys: 它们类似于 xm 和 ym , 区别在于它们是相对于前一个使用选项 Section 添加的控件坐标 (在窗体中创建首个控件时总是开始一个新列, 即使没有指定此选项). 指定 ys 而省略 X 坐标, 将把控件放置在之前保存的 Y 坐标 (即最近一次使用 Section 选项添加的控件的 Y 坐标) 但在最近一次使用 Section 后添加的所有控件右边; 这可以理解为在同一控件段中开始一个新列. 例如:

gui, add, edit, w600  ; 在窗体的顶部添加一个非常宽的编辑控件.
gui, add, text, section, First Name:  ; 保存此控件位置并定义一个新控件段.
gui, add, text,, Last Name:
gui, add, edit, ys  ; 在此控件段中开始一个新列.
gui, add, edit
gui, show

反过来 (指定 xs 但省略 Y 坐标) 也是一样的.

xs 和 ys 后面可以跟着一个加号/减号和一个数字. 并且还可以在控件的选项中同时指定单词 Section 和 xs/ys; 这样可以让当前控件使用之前的段, 但为后续控件定义一个新段.

储存和响应用户的输入

V: 变量. 为一个控件分配一个关联的变量. 在字母 V 后指定一个变量名, 此变量将为全局变量 (或一个指向全局变量的 ByRef 局部变量, 在 1.0.46.01+ 版本中还可能为 静态变量). 例如, 指定 vMyEdit 后, 每当执行 Gui Submit 命令时将把控件的内容保存到变量 MyEdit. 如果控件是不可输入类型 -- 例如 Text 控件或 GroupBox -- 为其分配的关联变量作为控件的唯一标识符仍可用于 GuiControl, GuiControlGet, and A_GuiControl. 注意: Gui Submit 不会改变不可输入型控件关联变量的内容 (例如 Text 和 GroupBox), 也不会改变其他某些控件的内容, 如同在这些控件描述部分注明的一样 (例如 ListView 和 TreeView).

G: Gosub (g-label). 当用户点击或改变控件内容时自动运行子程序. 在字母 G 后指定需要执行的标签名称. 指定 gCancel 暗示执行 Gui Cancel (但如果在脚本中存在名称为 "Cancel" 的标签, 则会执行此标签). 在子程序中可以引用下列的内置变量: A_Gui, A_GuiControl, A_GuiEvent 和 A_EventInfo.

控件: 一般样式和其他选项

注意: 选项前的符号省略时, 默认为加号; 例如, Wrap 等同于 +Wrap. 相反地, -Wrap 将去除自动换行属性.

AltSubmit: 使用备用的提交方法. 对于 DropDownList, ComboBox 和 ListBox 此选项会让 Gui Submit 命令保存选择的项目的位置而不是其文本. 如果没有选项项目, 则对于 ComboBox 控件会保存其编辑区域的文本; 同样地, 对于 DropDownList 或 ListBox 则它们的关联 输出变量 为空. 注意: AltSubmit 选项也会影响 GuiControlGet 获取这些控件内容时的行为.

C: 文本颜色 (对 按钮 控件无效). 指定字母 C 后面跟着一个颜色名称 (参见 颜色图表) 或 RGB 值 (0x 前缀可以省略). 示例: cRed, cFF2211, c0xFF2211, cDefault

Disabled: 让可输入型控件变为灰色禁用状态, 这样可以防止用户的焦点和输入. 以后可以使用 "GuiControl Enable" 启用控件. 注意: 要让编辑控件为只读状态, 请指定 ReadOnly 选项代替. 并且, 还可以在单词 Disabled 后紧跟着一个 0 或 1 来表示控件的初始状态 (0 为启用而 1 为禁用). 换句话说, Disabled 和 Disabled%VarContainingOne% 是一样的.

Hidden: 让控件初始为隐藏状态. 以后可以使用 "GuiControl Show" 让它显示. 可以在单词 Hidden 后紧跟着一个 0 或 1 来表示控件的初始状态 (0 为可见而 1 为隐藏). 换句话说, Hidden 和 Hidden%VarContainingOne% 是一样的.

Left: 在控件的可用宽度内左对齐控件的文本.

Right: 在控件的可用宽度内右对齐控件的文本. 对于复选框和单选按钮, 此选项也同时把方框放置在控件的右边而不是左边.

Center: 在控件的可用宽度内居中对齐控件的文本.

Section: 定义一个新的控件段并保存当前控件的位置以便在之后创建含有 xs 和 ys 选项的控件时使用, 参考 上文描述.

Tabstop: 使用 -Tabstop (即负 Tabstop) 可以在用户按 TAB 键导航时跳过输入型控件.

Wrap: 让控件的文本自动换行. 因为几乎所有类型的控件在开始时都是启用自动换行的, 所以需要在 Wrap 前加上一个负号来禁用它.

VScroll: 控件支持时为其提供一个垂直滚动条.

HScroll: 控件支持时为其提供一个水平滚动条. 这个段落的剩余部分仅适用于 ListBox. 可水平滚动的宽度默认为 ListBox 宽度的 3 倍. 要指定其他的滚动宽度, 请在单词 HScroll 后紧跟着一个数字表示. 例如, HScroll500 将在 ListBox 中使用 500 像素的滚动宽度. 但是, 如果指定的滚动宽度小于 ListBox 的宽度, 则不显示滚动条 (不过在这种含有 HScroll 的情况下, 可以在之后使用 GuiControl, +HScroll500, MyScrollBar 添加水平滚动条, 否则是没办法添加的).

控件: 特殊样式和选项

BackgroundTrans: 使用透明的背景, 这样可以让任何一个在 Text, Picture 或 GroupBox 后面的控件显示出来. 例如, 在 Picture 控件上显示一个透明背景的 Text 可以让文字看起来就像图片的一部分. 以后可以使用 "GuiControl +background" 移除此选项. 参见 Picture 控件的 AltSubmit 选项部分 来了解关于透明图像的更多细节. 已知限制: 对包含 ListView 的 Tab 控件 中的其他控件 BackgroundTrans 选项可能无法正确应用.

-Background (即负 Background): 使用标准的背景颜色代替 "Gui Color" 命令设置的那个颜色. 此选项常用于让 Tab 控件使用其标准颜色代替窗体颜色. 以后可以使用 "GuiControl +background" 移除此选项.

Border: 为控件增加一个细边框. 对于大多数控件不需要使用此选项因为它们已经含有特定于类型的边框. 添加一个边框到 现有 的控件时, 可能需要给控件的宽度和高度增加 1 个像素.

Hwnd OutputVar [v1.0.46.01+]: 在 Gui Add 中使用时, 此选项保存新创建的控件的窗口句柄 (HWND) 到 OutputVar 中. 例如: Gui, Add, Edit, vMyEdit HwndMyEditHwnd (如果在函数内部, MyEditHwnd 被视为 函数动态变量). 控件的 HWND 常用于 PostMessage, SendMessage 和 DllCall. 它也可以直接作为 ahk_id WinTitle 使用 (即使在 DetectHiddenWindows 为 Off 时这样也对隐藏的控件有效). 相关提示, 控件所在窗体的 HWND 可以在 Gui 2:+LastFoundExist 后执行 WinExist() 获取.

Theme: 使用此选项可以让控件忽略窗体当前的主题设置. 请参见 Gui +/-Theme 了解详情.

(未命名样式): 在十进制或十六进制的 样式编号 前加上加号或减号表示添加或删除此样式. 如果省略了符号, 则默认为加号.

(未命名扩展样式): 在字母 E 和十进制或十六进制的扩展样式编号前加上加号或减号表示添加或删除此扩展样式. 如果省略了符号, 则默认为加号. 例如, E0x200 表示添加 WS_EX_CLIENTEDGE 样式, 它可以为图片和其他控件增加一个下沉的边框样式. 尽管这里没有列出其他的扩展样式编号 (因为很少使用它们), 但可以通过在 www.microsoft.com 搜索 WS_EX_CLIENTEDGE 找到它们.

窗体事件

如果在脚本中存在下列的标签 (子程序) 时, 它们会自动和一个 GUI 窗体关联:

GuiClose: 使用下列其中一种方法关闭窗体时自动运行此子程序: 点击标题栏上的关闭按钮, 从标题栏中的系统菜单选择 "关闭" 或使用 WinClose 关闭. 如果此标签不存在, 则关闭窗体只是简单地隐藏窗体, 与 Gui Cancel 的效果一样. 在 GuiClose 中一个最常用的动作是 ExitApp; 例如:

GuiClose:
ExitApp

GuiEscape: 用户在 GUI 窗体活动时按下 Escape 后自动运行的子程序. 如果此标签不存在, 则按下 Escape 没有效果. 已知限制: 如果窗体中首个控件是禁用的 (可能与控件类型有关), 按下 Escape 时 GuiEscape 子程序不会运行. 产生这样的效果可能是受其他一些事件的影响.

GuiSize: 对窗体调整大小, 最小化, 最大化或还原时自动运行的子程序. 内置变量 A_GuiWidth 和 A_GuiHeight 分别包含了窗体客户区调整后的宽度和高度, 窗体客户区不包括标题栏, 菜单栏和边框. 此外, A_EventInfo 和 ErrorLevel 将同时包含下列数字的其中一个:

0: 还原窗体或通过像拖拉窗体边缘这样正常调节窗体大小时.
1: 最小化窗体.
2: 最大化窗体.

脚本中可以使用 GuiSize 调整控件的大小和位置来响应用户对窗体大小的改变. 通过 #Include 加载 Titan 的 "Anchor" 脚本 可以让这种处理更容易些.

GuiContextMenu: 当用户在窗体上除标题栏和菜单栏外的其他地方点击右键时自动运行此子程序. 当用户按下 Apps 键或 Shift-F10 时也会运行. 和其他多数的 GUI 标签不同, GuiContextMenu 可以含有多个并发 线程. 在 GuiContextMenu 子程序中可以引用下列内置变量:

  1. A_GuiControl, 其包含了接收到事件 (如果没有则为空) 的控件的 文本或变量名称.
  2. A_EventInfo: 当右键点击 ListBox, ListView 或 TreeView 控件时 (可以由上面的 A_GuiControl 得到), A_EventInfo 包含了右键点击的控件项目:
    ListBox 或 ListView: A_EventInfo 包含了当前焦点行号 (如果没有则为 0).
    TreeView: 右击时, A_EventInfo 包含了右击项目的 ID 编号 (如果用户点击到项目外的其他地方则为 0). 对于 AppsKey 和 Shift-F10, A_EventInfo 包含了选择的项目的 ID 编号.
  3. A_GuiX 和 A_GuiY, 包含了菜单显示位置的 X 和 Y 坐标 (例如 Menu, MyContext, Show, %A_GuiX%, %A_GuiY%). 这里的坐标相对于窗体的左上角.
  4. A_GuiEvent, 当用户右击时包含单词 RightClick, 当用户按下 Apps 或 Shift-F10 时包含单词 Normal.

注意: 由于 Edit 和 MonthCal 控件有它们自己的右键菜单, 所以点击这些控件时不会运行 GuiContextMenu.

GuiDropFiles: 拖放文件/文件夹到窗体上时运行此子程序 (如果此子程序已经在运行中, 则拖放事件被忽略). 在 GuiDropFiles 中可以引用下列内置变量:

  1. A_GuiControl, 其包含了接收到释放文件 (如果没有则为空) 的控件的 文本或变量名称.
  2. A_EventInfo 和 ErrorLevel, 包含了释放文件的数目.
  3. A_GuiX 和 A_GuiY, 包含了释放文件时的 X 和 Y 坐标 (相对于窗体的左上角).
  4. A_GuiEvent, 包含了被释放文件的名称, 文件名之间使用换行符 (`n) 分隔.

要获取每个文件的名称, 请使用 解析循环, 如下所示:

; 示例 #1:
Loop, parse, A_GuiEvent, `n
{
    MsgBox, 4,, File number %A_Index% is:`n%A_LoopField%.`n`nContinue?
    IfMsgBox, No, Break
}

; 示例 #2: 要获取首个文件的名称, 参照此例:
Loop, parse, A_GuiEvent, `n
{
    FirstFile = %A_LoopField%
    break
}

; 示例 #3: 要按照文件名称的字母排序处理文件, 参照此例:
FileList = %A_GuiEvent%
Sort, FileList
Loop, parse, FileList, `n
    MsgBox File number %A_Index% is:`n%A_LoopField%.

要临时禁用窗体的拖放功能, 请使用 Gui -E0x10 移除窗体的 WS_EX_ACCEPTFILES 属性. 后面要启用拖放, 请使用 Gui +E0x10.

检测和响应其他事件: 其他 GUI 事件可以使用 OnMessage() 检测和响应. 例如, 当用户把鼠标移动到特殊的控件时脚本可以通过 ToolTip 显示相关帮助. 参见演示 GUI ToolTip 示例.

创建多个 GUI 窗体

对于非首个窗体, 需要在上面描述的特殊标签前加上窗体的编号作为前缀; 例如, 2GuiEscape 和 2GuiClose 为第二个窗体的默认标签. 要使用自定义的标签名称, 请参见 Gui +Label.

每个脚本最多可以同时创建 99 个 GUI 窗体. 要对非 默认 窗体进行操作, 需要在子命令前加上窗体编号和一个冒号, 例如:

Gui, 2:Add, Text,, Text for about-box.
Gui, 2:Show

执行 Gui 2:Default 可以把第二个窗体设为默认窗体, 这样在上述语句中可以去除 "2:" 前缀. 此外, 在由窗体运行的 GUI 线程 中对此窗体进行操作时可以不加前缀.

脚本的性能会随着窗体数量的增多而下降.

GUI 事件, 线程 和子程序

GUI 线程 是由 GUI 动作启动的. GUI 动作包括从 GUI 窗体的 菜单栏 中选择一个项目或触发其某个 g-label (例如按下按钮).

GUI 线程的 默认窗体编号 是运行此线程的窗体编号. 非 GUI 线程的默认窗体编号为 1.

当运行一个 GUI 线程 时, 此线程的 最近找到的窗口 初始为此 GUI 窗体自身. 这样可以让窗体和控件操作命令 -- 例如 WinMove, WinHide, WinSet, WinSetTitle 和 ControlGetFocus -- 对当前的 GUI 窗体 (即使窗体处于隐藏状态) 进行操作时省略 WinTitle 和 WinText.

当一个控件的 g-label 由于之前的点击还在运行时, 点击此控件不会有效果并且此事件被丢弃. 想要避免此问题, 在子程序的首行使用 Critical (不过, 这样也将缓冲/延迟其他 线程 例如按下的热键).

内置变量 A_Gui 和 A_GuiControl 包含了运行当前线程的窗体编号和控件 ID. 更多细节参见 A_Gui 和 A_GuiControl.

要让多个事件执行相同的子程序, 则在子程序上面连续指定这些标签. 例如:

GuiEscape:
GuiClose:
ButtonCancel:
ExitApp  ; 上面的所有标签都会执行这个语句.

所有的 GUI 线程 都会以脚本设置的默认值启动, 例如 SendMode. 这些默认值可以在 自动执行段 改变.

键盘导航

可以使用 TAB 键在 GUI 窗体中导航, 它可以移动键盘焦点到下一个可输入型控件中 (移除了 Tabstop 样式的控件被跳过). 导航的顺序由控件添加的顺序决定. 当首次显示一个窗体时, 键盘焦点将在首个具有 Tabstop 样式 (默认情况下大多数类型的控件都具有) 的可输入型控件上.

某些控件的名称中可以包含一个符号 (&) 来创建此控件的键盘快捷键, 在控件名称中的快捷键字母会加上下划线显示 (取决于系统设置). 用户可以通过按下 ALT 和相应的字符来触发这样的快捷键. 对于按钮, 复选框和单选按钮, 按下相应的快捷键等于点击了按钮. 对于 GroupBox 和 Text 控件, 按下相应的快捷键则移动键盘焦点到此控件后 (不是指位置, 是创建顺序) 首个具有 tabstop 样式的可输入型控件中. 但是, 如果多个控件含有相同的快捷键, 按下此快捷键则键盘焦点会在这些控件中交替.

要在上面提及的类型的控件中显示一个原义的符号 (&), 请指定两个连续的符号 (&), 例如: Save && Exit

窗体外观

当 GUI 窗体创建时, 它使用创建时的托盘图标作为其窗体图标. 因此, 如果要使用不同的图标, 需要在创建窗体前改变托盘图标. 例如: Menu, Tray, Icon, MyIcon.ico. 还可以让窗体拥有一个不同的大图标而不用这个小图标 (大图标显示在 alt-tab 任务切换器中). 这个功能可以通过 DllCall 和 SendMessage 实现; 例如:

hIcon32 := DllCall("LoadImage", uint, 0
    , str, "My Icon.ico"  ; 图标文件 (此文件中可以包含多种尺寸图标).
    , uint, 1  ; 图像类型: IMAGE_ICON
    , int, 32, int, 32  ; 想要的高度和宽度 (可以让 LoadImage 确定哪个是最佳图标).
    , uint, 0x10)  ; 标志: LR_LOADFROMFILE
Gui +LastFound
SendMessage, 0x80, 1, hIcon32  ; 0x80 是 WM_SETICON; 而 1 表示 ICON_BIG (而 0 表示 ICON_SMALL).
Gui Show

由于操作系统的限制, 在 Windows XP 及更高版本的系统中, Checkbox, Radio button 和 GroupBox 控件中的文本不是使用默认颜色时将显示为经典主题外观.

相关主题: 窗体边距.

一般说明

可以使用 GuiControl 和 GuiControlGet 单独对 GUI 窗体中的控件进行操作.

每个 GUI 窗体最多可以包含 11,000 控件. 然而, 当控件数量超过 5000 时需要谨慎, 因为此时某些类型的控件可能让系统不稳定.

使用 GUI 命令的任何脚本会自动变成 持续运行的 (即使 GUI 命令实际上从未执行过). 同时也会单实例运行, 除非使用 #SingleInstance 覆盖了默认设置.

相关

GuiControl, GuiControlGet, Menu, 控件类型, ListView, TreeView, Control, ControlGet, SplashImage, MsgBox, FileSelectFile, FileSelectFolder

示例

; 示例: Achieve an effect similar to SplashTextOn:

Gui, +AlwaysOnTop +Disabled -SysMenu +Owner ; +Owner avoids a taskbar button.
Gui, Add, Text,, Some text to display. Gui, Show, NoActivate, Title of Window ; NoActivate avoids deactivating the currently active window.

; 示例: A simple input-box that asks for first name and last name:

Gui, Add, Text,, First name: Gui, Add, Text,, Last name: Gui, Add, Edit, vFirstName ym ; The ym option starts a new column of controls.
Gui, Add, Edit, vLastName Gui, Add, Button, default, OK ; The label ButtonOK (if it exists) will be run when the button is pressed.
Gui, Show,, Simple Input Example return ; End of auto-execute section. The script is idle until the user does something.

GuiClose: ButtonOK: Gui, Submit ; Save the input from the user to each control's associated variable.
MsgBox You entered "%FirstName% %LastName%". ExitApp

; 示例: Tab control:

Gui, Add, Tab2,, First Tab|Second Tab|Third Tab ; Tab2 vs. Tab requires v1.0.47.05.
Gui, Add, Checkbox, vMyCheckbox, Sample checkbox Gui, Tab, 2 Gui, Add, Radio, vMyRadio, Sample radio1 Gui, Add, Radio,, Sample radio2 Gui, Tab, 3 Gui, Add, Edit, vMyEdit r5 ; r5 means 5 rows tall.
Gui, Tab ; i.e. subsequently-added controls will not belong to the tab control.
Gui, Add, Button, default xm, OK ; xm puts it at the bottom left corner.
Gui, Show return ButtonOK: GuiClose: GuiEscape: Gui, Submit ; Save each control's contents to its associated variable.
MsgBox You entered:`n%MyCheckbox%`n%MyRadio%`n%MyEdit% ExitApp

; 示例: ListBox containing files in a directory:

Gui, Add, Text,, Pick a file to launch from the list below.`nTo cancel, press ESCAPE or close this window. Gui, Add, ListBox, vMyListBox gMyListBox w640 r10 Gui, Add, Button, Default, OK Loop, C:\*.* ; Change this folder and wildcard pattern to suit your preferences.
{ GuiControl,, MyListBox, %A_LoopFileFullPath% } Gui, Show return MyListBox: if A_GuiEvent <> DoubleClick return
; Otherwise, the user double-clicked a list item, so treat that the same as pressing OK. ; So fall through to the next label.
ButtonOK: GuiControlGet, MyListBox ; Retrieve the ListBox's current selection.
MsgBox, 4,, Would you you like to launch the file or document below?`n`n%MyListBox% IfMsgBox, No return
; Otherwise, try to launch it:
Run, %MyListBox%,, UseErrorLevel if ErrorLevel = ERROR MsgBox Could not launch the specified file. Perhaps it is not associated with anything. return GuiClose: GuiEscape: ExitApp

; 示例: Display context-senstive help (via ToolTip) whenever the user moves the mouse over a particular control:

Gui, Add, Edit, vMyEdit
MyEdit_TT := "This is a tooltip for the control whose variable is MyEdit." Gui, Add, DropDownList, vMyDDL, Red|Green|Blue
MyDDL_TT := "Choose a color from the drop-down list." Gui, Add, Checkbox, vMyCheck, This control has no tooltip. Gui, Show
OnMessage(0x200, "WM_MOUSEMOVE") return WM_MOUSEMOVE() { static CurrControl, PrevControl, _TT ; _TT is kept blank for use by the ToolTip command below.
 CurrControl := A_GuiControl If (CurrControl <> PrevControl and not InStr(CurrControl, " ")) { ToolTip ; Turn off any previous tooltip.
 SetTimer, DisplayToolTip, 1000 PrevControl := CurrControl } return DisplayToolTip: SetTimer, DisplayToolTip, Off ToolTip % %CurrControl%_TT ; The leading percent sign tell it to use an expression.
 SetTimer, RemoveToolTip, 3000 return RemoveToolTip: SetTimer, RemoveToolTip, Off ToolTip return } GuiClose: ExitApp

; 示例: On-screen display (OSD) via transparent window:

CustomColor = EEAA99 ; Can be any RGB color (it will be made transparent below).
Gui +LastFound +AlwaysOnTop -Caption +ToolWindow ; +ToolWindow avoids a taskbar button and an alt-tab menu item.
Gui, Color, %CustomColor% Gui, Font, s32 ; Set a large font size (32-point).
Gui, Add, Text, vMyText cLime, XXXXX YYYYY ; XX & YY serve to auto-size the window. ; Make all pixels of this color transparent and make the text itself translucent (150):
WinSet, TransColor, %CustomColor% 150 SetTimer, UpdateOSD, 200 Gosub, UpdateOSD ; Make the first update immediate rather than waiting for the timer.
Gui, Show, x0 y400 NoActivate ; NoActivate avoids deactivating the currently active window.
return UpdateOSD: MouseGetPos, MouseX, MouseY GuiControl,, MyText, X%MouseX%, Y%MouseY% return

; 示例: A moving progress bar overlayed on a background image.

Gui, Color, White Gui, Add, Picture, x0 y0 h350 w450, %A_WinDir%\system32\ntimage.gif Gui, Add, Button, Default xp+20 yp+250, Start the Bar Moving Gui, Add, Progress, vMyProgress w416 Gui, Add, Text, vMyText wp ; wp means "use width of previous".
Gui, Show return ButtonStartTheBarMoving: Loop, %A_WinDir%\*.* { if A_Index > 100 break GuiControl,, MyProgress, %A_Index% GuiControl,, MyText, %A_LoopFileName% Sleep 50 } GuiControl,, MyText, Bar finished. return GuiClose: ExitApp

; 示例: Simple image viewer:

Gui, +Resize Gui, Add, Button, default, &Load New Image Gui, Add, Radio, ym+5 x+10 vRadio checked, Load &actual size Gui, Add, Radio, ym+5 x+10, Load to &fit screen Gui, Add, Pic, xm vPic Gui, Show return ButtonLoadNewImage: FileSelectFile, file,,, Select an image:, Images (*.gif; *.jpg; *.bmp; *.png; *.tif; *.ico; *.cur; *.ani; *.exe; *.dll) if file = return Gui, Submit, NoHide ; Save the values of the radio buttons.
if Radio = 1 ; Display image at its actual size.
{ Width = 0 Height = 0 } else ; Second radio is selected: Resize the image to fit the screen.
{ Width := A_ScreenWidth - 28 ; Minus 28 to allow room for borders and margins inside.
 Height = -1 ; "Keep aspect ratio" seems best.
} GuiControl,, Pic, *w%width% *h%height% %file% ; Load the image.
Gui, Show, xCenter y0 AutoSize, %file% ; Resize the window to match the picture size.
return GuiClose: ExitApp

; 示例: Simple text editor with menu bar.

; Create the sub-menus for the menu bar:
Menu, FileMenu, Add, &New, FileNew Menu, FileMenu, Add, &Open, FileOpen Menu, FileMenu, Add, &Save, FileSave Menu, FileMenu, Add, Save &As, FileSaveAs Menu, FileMenu, Add ; Separator line.
Menu, FileMenu, Add, E&xit, FileExit Menu, HelpMenu, Add, &About, HelpAbout

; Create the menu bar by attaching the sub-menus to it:
Menu, MyMenuBar, Add, &File, :FileMenu Menu, MyMenuBar, Add, &Help, :HelpMenu

; Attach the menu bar to the window:
Gui, Menu, MyMenuBar

; Create the main Edit control and display the window:
Gui, +Resize ; Make the window resizable.
Gui, Add, Edit, vMainEdit WantTab W600 R20 Gui, Show,, Untitled CurrentFileName = ; Indicate that there is no current file.
return FileNew: GuiControl,, MainEdit ; Clear the Edit control.
return FileOpen: Gui +OwnDialogs ; Force the user to dismiss the FileSelectFile dialog before returning to the main window.
FileSelectFile, SelectedFileName, 3,, Open File, Text Documents (*.txt) if SelectedFileName = ; No file selected.
 return Gosub FileRead return FileRead: ; Caller has set the variable SelectedFileName for us.
FileRead, MainEdit, %SelectedFileName% ; Read the file's contents into the variable.
if ErrorLevel { MsgBox Could not open "%SelectedFileName%". return } GuiControl,, MainEdit, %MainEdit% ; Put the text into the control.
CurrentFileName = %SelectedFileName% Gui, Show,, %CurrentFileName% ; Show file name in title bar.
return FileSave: if CurrentFileName = ; No filename selected yet, so do Save-As instead.
 Goto FileSaveAs Gosub SaveCurrentFile return FileSaveAs: Gui +OwnDialogs ; Force the user to dismiss the FileSelectFile dialog before returning to the main window.
FileSelectFile, SelectedFileName, S16,, Save File, Text Documents (*.txt) if SelectedFileName = ; No file selected.
 return CurrentFileName = %SelectedFileName% Gosub SaveCurrentFile return SaveCurrentFile: ; Caller has ensured that CurrentFileName is not blank.
IfExist %CurrentFileName% { FileDelete %CurrentFileName% if ErrorLevel { MsgBox The attempt to overwrite "%CurrentFileName%" failed. return } } GuiControlGet, MainEdit ; Retrieve the contents of the Edit control.
FileAppend, %MainEdit%, %CurrentFileName% ; Save the contents to the file. ; Upon success, Show file name in title bar (in case we were called by FileSaveAs):
Gui, Show,, %CurrentFileName% return HelpAbout: Gui, 2:+owner1 ; Make the main window (Gui #1) the owner of the "about box" (Gui #2).
Gui +Disabled ; Disable main window.
Gui, 2:Add, Text,, Text for about box. Gui, 2:Add, Button, Default, OK Gui, 2:Show return 2ButtonOK: ; This section is used by the "about box" above.
2GuiClose: 2GuiEscape: Gui, 1:-Disabled ; Re-enable the main window (must be done prior to the next step).
Gui Destroy ; Destroy the about box.
return GuiDropFiles: ; Support drag & drop.
Loop, parse, A_GuiEvent, `n { SelectedFileName = %A_LoopField% ; Get the first file only (in case there's more than one).
 break } Gosub FileRead return GuiSize: if ErrorLevel = 1 ; The window has been minimized. No action needed.
 return
; Otherwise, the window has been resized or maximized. Resize the Edit control to match.
NewWidth := A_GuiWidth - 20 NewHeight := A_GuiHeight - 20 GuiControl, Move, MainEdit, W%NewWidth% H%NewHeight% return FileExit: ; User chose "Exit" from the File menu.
GuiClose: ; User closed the window.
ExitApp


GUI Control Types

GUI 控件类型

目录

  • Text, Edit, UpDown, Picture
  • Button, Checkbox, Radio
  • DropDownList, ComboBox
  • ListBox, ListView, TreeView
  • Hotkey, DateTime, MonthCal
  • Slider, Progress
  • GroupBox, Tab2, StatusBar, Internet Explorer Control

Text

描述: 一个不包含边界的文本区域, 用户不能编辑其中的文本. 常用来标识其他控件。

例如: Gui, Add, Text,, Please enter your name:

此时, 最后一个参数为需要显示的字符串. 它可以包含换行符 (`n) 来开始新行. 此外, 一个长行可以使用 字串分段 的方法分成较短的几行.

如果 选项 中指定了宽度 (W) 而没有指定 行数 (R) 或 高度 (H), 需要时文本将自动换行, 同时将自动设置控件的高度.

因为控件的内容是 Gui 命令的最后一个参数, 所以可以直接使用逗号而不需要转义. 对于所有其他命令的最后一个参数也是如此.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户点击文本时 MySubroutine 标签会自动运行. 这可以用来模仿带下划线的蓝色超级链接, 如下面的工作脚本所示:

Gui, Font, underline
Gui, Add, Text, cBlue gLaunchGoogle, Click here to launch Google.
Gui, Font, norm
Gui, Show
return

LaunchGoogle:
Run www.google.com
return

通过检查 A_GuiEvent 是否包含单词 DoubleClick 可以检测到双击事件.

在文本中使用符号 (&) 可以给一个字母加下划线. 例如:

Gui, Add, Text,, &First Name:
Gui, Add, Edit

在上述示例中, 字母 F 将被添加下划线, 这允许用户按下 快捷键 Alt+F 将键盘焦点设置到此文本控件后添加的首个可输入型控件中. 要显示一个原义的 (&) 符号, 请指定两个连续的 (&&) 符号. 要取消控件中对 & 符号的特殊处理, 请在控件的选项中包含 0x80.

请参看 常规选项 来了解其他选项例如 Right, Center, 和 Hidden. 也请参见: 控件的位置和大小.

Edit

描述: 用户可以输入自由格式的文本区域.

例如: Gui, Add, Edit, r9 vMyEdit, Text to appear inside the edit control (omit this parameter to start off empty).

如果控件中有多行的文本, 则它将是多行的. 例如, 在 选项 中指定 r3 将创建一个拥有后面那些默认属性的 3 行编辑控件: 一个垂直滚动条, 启用自动换行, 并且捕获的回车键作为输入的一部分而不触发窗口的 默认按钮.

要在多行编辑控件中开始一个新行, 最后一个参数中 (内容) 可以包含一个单独的换行符 (`n) 或一个回车换行符 (`r`n). 这两种方法都会在 Edit 控件中产生原义的 `r`n 对. 然而, 当控件通过 Gui Submit 或 GuiControlGet 把内容保存到其变量中时, 文本中的每对 `r`n 总是被转换成单独的换行符 (`n). 要把文本写入到文件中, 请参照此例: FileAppend, %MyEdit%, C:\Saved File.txt

如果控件启用了自动换行 (对于多行编辑控件默认是启用的), 用户输入时任何自动换行的地方不会产生换行字符 (仅回车键才会).

虽然在 Windows 95/98/Me 系统中多行编辑控件最多包含 64 KB 的文本, 但在 Windows NT/2k/XP 或更高版本的系统中它们可以包含多达 4G 的文本. 当用户输入文本时, 根据需要分配更多的内存.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户或脚本改变控件的内容时 MySubroutine 标签会自动运行.

提示: 要加载一个文本文件到 Edit 控件中, 请使用 FileRead 和 GuiControl. 例如：

Gui, Add, Edit, R20 vMyEdit
FileRead, FileContents, C:\My File.txt
GuiControl,, MyEdit, %FileContents%

Edit 选项 (要移除而不是添加一个选项, 请在选项前加上一个负号):

Limit: 限制用户的输入在编辑区域的可见宽度内. 另外, 要限制输入指定数目的字符, 请在选项后跟着一个数字. 例如, Limit10 将允许输入不超过 10 个字符.

Lowercase: 用户输入的字符自动转换成小写.

Multi: 使控件可以含有多行的文本. 然而, 通常没必要指定此选项因为它会根据高度 (H), 行数 (R), 或内容 (Text) 自动判断.

Number: 阻止用户输入非数字的其他字符到编辑区域 (然而, 还是有可能粘贴非数字的字符到里面). 强制数字输入的另一种方法是添加一个 UpDown 控件到此 Edit 编辑控件中.

Password: 通过将用户的输入替代为屏蔽字符来隐藏用户的输入 (例如对于密码输入). 如果想使用非默认的屏蔽字符, 请在单词 Password 后加上此符号. 例如, Password* 将使用星号而不是黑色圆 (项目符号) 作为屏蔽符号, 这是 Windows XP 中的默认屏蔽符号. 注: 对于多行编辑控件此选项无效.

ReadOnly: 阻止用户改变控件的内容. 然而, 仍然可以滚动, 选择文本或将文本复制到剪贴板.

Tn: 字母 T 可以用来设置 多行编辑控件 的制表位 (因为制表位决定了原义的 TAB 符号将跳转的列位置, 它们可以把文本格式成列). 如果没有使用字母 T, 则每 32 个对话框单位设置一次制表位 (每个对话框单位的宽度由操作系统决定). 如果仅使用一次字母 T, 每 n 个单元设置一次制表位横跨整个控件的宽度. 例如, Gui, Add, Edit, vMyEdit r16 t64 将设置制表位之间的距离为默认的两倍. 要自定义制表位, 请多次指定字母 T, 如后面的例子所示: Gui, Add, Edit, vMyEdit r16 t8 t16 t32 t64 t128. 在列表中每个绝对的列位置设置一个制表位, 制表位数目最大可达 50 个. 注: 制表位适用于多行编辑控件.

Uppercase: 用户输入的字符自动转换成大写.

WantCtrlA [v1.0.44+]: 指定 -WantCtrlA (负 WantCtrlA) 可以阻止用户按下 Control-A 来选择编辑控件中的所有文本.

WantReturn: 指定 -WantReturn (即一个负号跟着 WantReturn) 以避免多行编辑控件捕获 Enter 键击. 此时按下 Enter 键相当于按了窗口的 默认按钮 (如果有的话). 在这种情况下, 用户可以按下 Control-Enter 组合键开始一个新行.

WantTab: 使得一个 tab 键击产生一个制表符而不是导航到下一个控件. 如果没有这个选项, 在多行编辑控件中用户可以按下 Control-Tab 来产生一个制表符. 注: 虽然 WantTab 也可以用于单行编辑控件, 但此时每个制表符显示为一个空框字符 (尽管其保存为真正的 tab).

-Wrap (负 wrap): 关闭多行编辑控件中的自动换行属性. 由于在控件创建后不能改变此样式, 请使用下列方法的其中一个来改变它: 1) 销毁 后重新创建窗口和其中的控件; 或 2) 创建两个重叠的编辑控件, 其中一个启用自动换行而另一个禁用. 当前没有使用的那个可以保持空的和/或隐藏.

请参看 常规选项 来了解其他选项例如 Right, Center, 和 Hidden.也请参见: 控件的位置和大小.

一个更强大的编辑控件: HiEdit 是一个免费, 多标签页, 支持大文件而消耗很少内存的编辑控件. 它可以编辑文本和二进制文件.需要了解详情和演示, 请参见 www.autohotkey.com/forum/topic19141.html

UpDown

描述: 一对箭头组成的按钮, 用户点击后会增加或减少值. 默认情况下, 一个 UpDown 控件自动依附于前一个添加的控件上. 这里的前一个控件被称为 UpDown 的 伙伴控件. 最常见的例子是 "旋转器", 这是 UpDown 依附到一个 Edit 控件. 例如：

Gui, Add, Edit
Gui, Add, UpDown, vMyUpDown Range1-10, 5

在上面的例子中, Edit 控件是 UpDown 的伙伴控件. 每当用户按下了增减按钮的其中一个, Edit 控件中的数字会自动增加或减少.

一个 UpDown 的伙伴控件也可以是一个 Text 控件 或 ListBox. 然而, 由于操作系统的限制, 除了这些以外的其他控件类型 (例如 ComboBox 和 DropDownList) 可能无法和 g-label 以及其他的特性一起正常工作.

在最后一个参数中可以指定 UpDown 的初始位置 (如果省略, 初始为 0 或允许的范围中最接近 0 的数字).

使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到 UpDown 当前的数字位置. 如果 UpDown 依附于一个编辑控件而您不想确认用户的输入, 此时最好使用 UpDown 的值而不是编辑控件的. 这是因为 UpDown 将总是产生一个允许范围内的数字, 即使用户在编辑控件中输入了非数字或超出范围的内容. 相关提示, 默认情况下超过三位的数字会添加 千位分隔符 (例如逗号). 这些分隔符保存在编辑控件的输出变量中, 但不在 UpDown 的变量中.

如果 UpDown 有一个 g-label, 当用户点击增减按钮的其中一个或按下了键盘上的方向键时它将会运行. 每个运行的 g-label 都会保存 UpDown 的位置到其 关联的输出变量 (如果有的话).

UpDown 选项:

Horz: 使控件的按钮点指向左/右而不是上/下. 默认情况下, Horz 也使得控件孤立的 (没有伙伴控件). 通过在控件的选项中指定 Horz 16 可以覆盖此特性.

Left: 把 UpDown 放在其伙伴控件的左边而不是右边.

Range: 设置 0 到 100 外的其他范围. 在单词 Range 后指定最小值, 一个破折号和最大值.例如, Range1-1000 将允许选择一个介于 1 和 1000 之间的数字; Range-50-50 将允许一个介于 -50 和 50 之间的数字; 而 Range-10--5 将允许一个介于 -10 和 -5 之间的数字.交换最小值和最大值会导致箭头往与正常方向相反的方向移动. 最大的允许范围是 -2147483648-2147483647. 然而, Windows 95 和 NT4 需要安装 Internet Explorer 5.0 或更高版本才能支持超出 -32767-32767 的范围. 最后, 如果伙伴控件是一个 ListBox, 垂直的默认范围是 32767-0 而水平的则反向 (Horz).

Wrap: 当用户试图超出最小值或最大值时使得控件返回到其范围的另一端. 如果没有 Wrap, 当达到最小值或最大值时控件会停止.

-16 (负 16): 让垂直的 UpDown 孤立; 即它没有伙伴控件. 这也使得控件符合任何指定的宽度, 高度和位置而不是适应于其伙伴控件的大小. 此外, 一个孤立的 UpDown 内部跟踪其自己的位置. 通过如 Gui Submit 命令可以正常获取此位置.

0x80: 在 选项 中包含 0x80 来省略伙伴控件中正常出现在每三位十进制数间的千位分隔符. 然而, 通常不使用此样式因为当脚本从 UpDown 控件 (而不是其伙伴控件) 获取的数字中分隔符是省略的 .

使用 1 以外的其他增量: 在 此脚本 中, NumEric 演示了如何改变一个 UpDown 增量为 1 以外的其他值(例如 5 或 0.1).

也请参见: 控件的位置和大小.

Picture (或 Pic)

描述: 包含图像的一个区域 (关于支持的文件类型请参见最后两段). 最后一个参数是图像的文件名, 如果没有指定一个绝对路径则假定在 A_WorkingDir 中.

示例: Gui, Add, Picture, w300 h-1, C:\My Pictures\Company Logo.gif

为了保持图像的实际宽度和/或高度, 请省略 W 和/或 H 选项. 否则, 调整图像的尺寸到指定的宽度和/或高度 (此宽度和高度也决定了从多图标的的 .ICO 文件中加载哪个图标). 要保持高宽比放大缩小图像, 请在其中一个尺寸指定 -1 而在另一个中指定正数. 例如, 指定 "w200 h-1" 将使得图像缩放成 200 像素的宽度同时自动设置其高度. 如果无法加载图片或无法显示 (例如找不到文件), 则控件被留空并且其宽度和高度设置为 0.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得用户点击图片时 MySubroutine 标签会自动运行. 通过检查 A_GuiEvent 是否包含单词 DoubleClick 可以检测到双击事件.

要使用图片作为其他控件的背景, 应该在其他控件之前正常添加图片. 然而, 如果这些控件是可输入型控件并且此图片有 g-label, 那么在其他控件后创建图片控件并在其 选项 中包含 0x4000000 (这是 WS_CLIPSIBLINGS). 此技巧也可以让一个图片成为 Tab 控件 或 ListView 的背景.

图标, 光标和动画光标: 图标和光标可以从下列文件的类型中加载: ICO, CUR, ANI, EXE, DLL, CPL, SCR, 和包含图标资源的其他类型. 要使用图标组而不是文件中首个图标, 请在 选项 中包含单词 Icon 和图标组编号. 在下面的例子中, 将使用第二个图标组中的默认图标: Gui, Add, Picture, Icon2, C:\My Application.exe

在 选项 中指定单词 AltSubmit 告诉程序使用微软的 GDIPlus.dll 来加载图像, 这可能让 GIF, BMP, 和图标图像产生不同的外观. 例如, 它可以加载一个背景透明的 ICO/GIF 作为透明的位图, 此时 BackgroundTrans 选项才生效. 如果 GDIPlus 不可用 (见下段), AltSubmit 选项被忽略而使用常规方法加载图像.

在所有的操作系统中都支持 GIF, JPG, BMP, ICO, CUR, 和 ANI 图像. 在 Windows XP 或更高版本的系统中, 还支持其他图像格式例如 PNG, TIF, Exif, WMF, 和 EMF. 通过复制微软的免费 GDI+ DLL 到 AutoHotkey.exe 文件夹中可以让 XP 之前的操作系统提供支持 (但如果是 已编译脚本, 则需要复制 DLL 到脚本的文件夹). 要下载此 DLL, 请在 www.microsoft.com 中搜索下列短语: gdi redistributable

由于操作系统漏洞, 尺寸大于 90x90 的动画光标在 Windows 95/98/Me 中可能让脚本崩溃.

GIF 动画: 虽然 GIF 动画文件可以显示在图片控件中, 但它们实际上并不会动起来. 为了解决此问题, 请使用 AniGIF DLL (对非商业用途免费), 观看演示请到 www.autohotkey.com/forum/topic19264.html

Button

描述: 一个按钮, 按下它可以触发一个动作. 此时最后一个参数为按钮的名称 (显示在按钮上), 其中可以包含换行符 (`n) 来开始新行.

例如: Gui, Add, Button, Default, OK

上面的例子在其 选项 中包含单词 Default 让 "OK" 成为默认按钮. 每当用户按下 ENTER 时默认按钮的动作会自动触发, 除非此时键盘焦点在另一个按钮上或含有 WantReturn 样式的多行编辑控件中. 要在以后改变默认按钮为另一个按钮, 请参照此例, 这让 Cancel 按钮成为默认按钮: GuiControl, +default, Cancel. 要在以后让窗口没有默认按钮, 请参照此例: GuiControl, -default, OK

在按钮名称中使用符号 (&) 可以给一个字母加下划线. 例如:

Gui, Add, Button,, &Pause

在上述示例中, 字母 P 将被添加下划线, 这可以让用户按下 Alt+P 作为其 快捷键. 要显示一个原义的 (&) 符号, 请指定两个连续的 (&&) 符号.

如果一个按钮没有明确的 g-label, 则使用一个自动标签. 例如, 如果首个 GUI 窗口包含一个 OK 按钮, 则当按下此按钮时将运行 ButtonOK 标签 (如果存在). 对于 非首个 GUI 窗口, 需要在按钮的自动标签前加上窗口编号; 例如: 2ButtonOK.

如果按钮上文字包含空格或 &`r`n`t` 集合中任意一个字符, 其自动标签会忽略这些字符. 例如, 一个名为 "&Pause" 的按钮其自动标签的名称将为 ButtonPause. 同样, 一个名为 "Save && Exit" 的按钮其自动标签的名称将为 ButtonSaveExit (两个连续的 (&&) 符号用来显示单个原义的符号 (&)).

已知的限制: 某些桌面主题可能无法正确的显示按钮文本. 如果遇到此情况, 请尝试在按钮的选项中包含 -Wrap (负 Wrap). 不过, 这也使得按钮名称无法含有多行文本.

Checkbox

描述: 一个小方框, 可以选中或取消选中来表示 On/Off, Yes/No, 等.

例如: Gui, Add, Checkbox, vShipToBillingAddress, Ship to billing address?

最后一个参数是紧跟着方框显示的标注, 这通常是关于复选框起什么作用的提示或描述. 它可以包含换行符 (`n) 来开始新的一行.如果 选项 中指定了宽度 (W) 而没有指定 行数 (R) 或高度 (H), 需要时控件的文本将自动换行, 同时将自动设置控件的高度. 在选中时复选框的 关联输出变量 (如果有的话) 接收到数字 1, 未选中时为 0, 而灰色/不确定时为 -1.

在 选项 中指定单词 Check3 来启用第三种状态即显示灰色的选中标记而不是黑色的 (灰色状态表示复选框既不处于选中状态也不处于未选中状态). 在 选项 中指定单词 Checked 或 CheckedGray 可以让复选框初始状态分别为黑色选中状态或灰色状态. 在单词 Checked 后面可选跟着一个 0, 1, 或 -1 来表示初始状态. 换言之, "Checked" 和 "Checked%VarContainingOne%" 是一样的.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得用户点击或改变复选框状态时 MySubroutine 标签会自动运行.

已知的限制: 某些桌面主题可能无法正确的显示按钮文本.如果遇到此情况, 请尝试在按钮的选项中包含 -Wrap (负 Wrap).不过, 这也使得按钮名称无法含有多行文本.

Radio

单选按钮是一个小空圆, 可以被选中 (打开) 或不选中 (关闭).

例如: Gui, Add, Radio, vMyRadioGroup, Wait for all items to be in stock before shipping.

此控件通常出现在 单选按钮组, 每组包含两个或多个单选按钮. 当用户点击一个单选按钮打开时, 其所在的单选按钮组中其他所有的单选按钮会自动关闭 (在单选按钮组中用户也可以使用方向键导航). 在所有连续添加的单选按钮周围会自动创建一个单选按钮组. 要开始一个新组, 请在新组的首个单选按钮的 选项 中指定单词 Group -- 或在新组和之前的组之间简单的添加一个非单选按钮控件, 因为这会自动开始一个新组.

在最后一个参数中指定的标注会显示在单选按钮的右侧. 此标注通常作为提示或描述, 它可以包含换行符 (`n) 来开始新的一行. 如果 选项 中指定了宽度 (W) 而没有指定 行数 (R) 或高度 (H), 需要时控件的文本将自动换行, 同时将自动设置控件的高度.

在 选项 指定单词 Checked 可以让按钮初始为选中状态. 在单词 Checked 后面可选跟着一个 0 或 1 来表示初始状态: 0 表示未选中而 1 表示选中. 换言之, "Checked" 和 "Checked%VarContainingOne%" 是一样的.

选中时单选按钮的 关联输出变量 (如果有的话) 接收到数字 1而未选中时为 0.但是, 如果单选组中仅有一个按钮含有关联变量, 此变量将接收当前选择按钮的编号: 首个单选按钮为 1 (根据原来创建的顺序), 第二个为 2, 依此类推. 如果没有选择的按钮, 则保存 0.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得用户选中按钮时 MySubroutine 标签会自动运行. 与之前段中的单变量模式不同, 必须为单选按钮组中每个按钮指定 g-label 这样选中某个按钮时相应的标签才会运行. 这样可以灵活的忽略某些按钮的点击. 最后, 通过检查 A_GuiEvent 是否包含单词 DoubleClick 可以检测到双击事件.

已知的限制: 某些桌面主题可能无法正确的显示按钮文本.如果遇到此情况, 请尝试在按钮的选项中包含 -Wrap (负 Wrap).不过, 这也使得按钮名称无法含有多行文本.

DropDownList (或 DDL)

描述: 一个选择列表, 当按下一个小按钮时显示. 此时最后一个参数是管道分隔的选择列表例如 Choice1|Choice2|Choice3.

例如: Gui, Add, DropDownList, vColorChoice, Black|White|Red|Green|Blue

要在窗口初次出现时预选其中的某项, 请在此项后包含两个管道符. 或者, 在 选项 中包含单词 Choose 接着预选的项编号. 例如, Choose5 将预选第五项 (和其他选项一样, 它也可以是一个变量例如 Choose%Var%). 要在控件创建后改变选择或添加/移除列表中的条目, 请使用 GuiControl.

在 选项 指定单词 Uppercase 或 Lowercase 会把列表中的所有项目自动转换成大写字母或小写字母. 指定单词 Sort 会按字母顺序自动排列列表的内容 (这也影响后面通过 GuiControl 添加的所有项目). Sort 选项同时启用了每当弹出下拉列表时的增量搜索; 这使得可以通过输入一个项目名称的前几个字符来选择此项.

当使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到当前选择项目的文本. 但是, 如果控件含有 AltSubmit 属性, 输出变量将接收到项目的位置编号 (首个项目为 1, 第二个为 2, 依此类推).

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户选择新项目时 MySubroutine 标签会自动运行.

使用 R 或 H 选项 来控制弹出列表的高度. 例如, 指定 R5 将使列表 5 行高. 如果同时省略 R 和 H 选项, 列表将自动扩展到用户桌面的有效高度 (但是, Windows XP 之前的操作系统默认将显示 3 行).

字段间的分隔符可以改变为管道符 (|) 外的其他符号. 例如 Gui +Delimiter`n 将改变分隔符为换行符而 Gui +DelimiterTab 将改变分隔符为制表符 (`t).

ComboBox

描述: 和 DropDownList 一样, 除了还允许输入自由格式的文本作为列表中可选的项目.

例如: Gui, Add, ComboBox, vColorChoice, Red|Green|Blue|Black|White

除了允许像上面的 DropDownList 的所有选项外, 选项 中还可以包含单词 Limit 来限制用户的输入在 ComboBox 编辑区域的可见宽度内. 此外, 指定单词 Simple 可以使 ComboBox 表现的像一个下方带有 ListBox 的 Edit 区域.

当使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到当前选择项目的文本.但是, 如果控件含有 AltSubmit 属性, 输出变量将接收到项目的位置编号 (首个项目为 1, 第二个为 2, 依此类推).在这两种情况下, 如果没有选择项目, 输出变量将被设置为 ComboBox 编辑区域的内容.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户选择新项目时 MySubroutine 标签会自动运行.

ListBox

描述: 一个包含一个选择列表的较高的框, 列表中的项目可以被选择. 此时最后一个参数是管道分隔的选择列表例如 Choice1|Choice2|Choice3.

例如: Gui, Add, ListBox, vColorChoice, Red|Green|Blue|Black|White

要在窗口初次出现时预选其中的某个或某些项目, 请在这些项目中的每个后面包含两个管道符 (如果要预选多个项目, 需要 Multi 选项). 或者, 在 选项 中包含单词 Choose 接着预选的单个项目编号. 例如, Choose5 将预选第五项. 要在控件创建后改变选择或添加/移除列表中的条目, 请使用 GuiControl.

当使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到当前选择项目的文本.但是, 如果控件含有 AltSubmit 属性, 输出变量接收的是项目的位置编号 (首个项目为 1, 第二个为 2, 依此类推).

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户选择新项目时 MySubroutine 标签会自动运行.如果用户双击一个项目, 内置变量 A_GuiEvent 将包含字符串 DoubleClick 而不是 Normal. 此外, 变量 A_EventInfo 将包含被双击项目的位置 (首个项目为 1, 第二个为 2, 依此类推).

当添加大量项目到 ListBox 时, 在操作前使用 GuiControl, -Redraw, MyListBox 并且在操作后使用 GuiControl, +Redraw, MyListBox 也许会提高性能.

ListBox 选项:

Choose: 参见 上面.

Multi: 允许通过 shift-click 和 control-click 同时选择多个项目(如果想不使用 shift/control-click, 请指定 数字 8 代替单词 Multi). 此时 Gui Submit 保存管道分隔的项目字符串列表到控件的 输出变量. 但是, 如果 AltSubmit 选项存在, Gui Submit 保存管道分隔项目编号列表. 例如, 1|2|3 将表明开始的三个项目被选中. 要从字符串中提取个别项目, 请使用 parsing loop, 例如:

Loop, parse, MyListBox, |
{
    MsgBox Selection number %A_Index% is %A_LoopField%.
}

字段间的分隔符可以改变为管道符 (|) 外的其他符号.例如 Gui +Delimiter`n 将改变分隔符为换行符而 Gui +DelimiterTab 将改变分隔符为制表符 (`t).

ReadOnly: 当项目被选择时避免它们被高亮显示 (但 Gui Submit 仍将保存选择的项目).

Sort: 按字母顺序自动排列列表的内容 (这也影响后面通过 GuiControl 添加的所有项目). Sort 选项同时启用了增量搜索, 这使得可以通过输入一个项目名称的前几个字符来选择此项.

Tn: 字母 T 可以用来设置制表位, 它可以把文本格式成列. 如果没有使用字母 T, 则每 32 个对话框单位设置一次制表位 (每个对话框单位的宽度由操作系统决定).如果仅使用一次字母 T, 每 n 个单元设置一次制表位横跨整个控件的宽度units across the entire width of the control.例如, "Gui, Add, ListBox, vMyListBox t64" 将设置制表位之间的距离为默认的两倍. 要自定义制表位, 请多次指定字母 T, 如后面的例子所示: Gui, Add, ListBox, vMyListBox t8 t16 t32 t64 t128. 在列表中每个绝对的列位置设置一个制表位, 制表位数目最大可达 50 个.

0x100: 在选项中包含 0x100 来打开 LBS_NOINTEGRALHEIGHT 样式. 此选项强制 ListBox 准确符合指定的高度而不是适应于避免部分行显示在底部的高度. 此选项也避免了其字体改变时 ListBox 缩小的情况.

要指定文本的行数 (或高度和宽度), 请参见 控件的位置和大小.

ListView 和 TreeView

请参见单独的页面 ListView 和 TreeView.

Hotkey

描述: 一个看起来像单行编辑控件的框, 但它接受用户按下的按键组合. 例如, 在英语键盘布局的系统中如果用户按下 Control+Alt+C, 此框将显示 "Ctrl + Alt + C".

例如: Gui, Add, Hotkey, vChosenHotkey

当使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 接收到热键修饰符和按键名称, 它们兼容于 Hotkey 命令. 示例: ^!C, +!Home, +^Down, ^Numpad1, !NumpadEnd.如果控件中没有热键, 输出变量被置空. 注: 一些按键即使它们作为不同的名称获取也显示为相同的名称. 例如, ^Numpad7 和 ^NumpadHome 都可能显示为 Ctrl + Num 7.

默认情况下, 开始时控件中不含有热键. 要让控件含有一个默认的热键, 请在最后一个参数中指定热键修饰符和按键名称, 例如: Gui, Add, Hotkey, vChosenHotkey, ^!p
被支持的修饰符仅包括 ^ (Control), ! (Alt), 和 + (Shift). 请参见 按键列表 了解可用的按键名称.

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得用户改变热键时 MySubroutine 标签会自动运行. g-label 的每次运行都会保存热键到控件的 关联输出变量 (如果有的话). 注: 控件中存在一个不完整的热键时 g-label 也会运行. 例如, 如果用户按住 Control 键, g-label 会运行一次, 此时输出变量仅包含一个重音符 (^). 当用户按完热键后, g-label 再次运行, 此时输出变量包含完整的热键.

为了限制用户可以输入的热键类型, 请在选项中包含单词 Limit 接着下列数字的一个或多个的总和:

1: 阻止不含修饰符的键
2: 阻止修饰符仅含 Shift 的键
4: 阻止修饰符仅含 Control 的键
8: 阻止修饰符仅含 Alt 的键
16: 阻止修饰符含 Shift-Control 的键
32: 阻止修饰符含 Shift-Alt 的键
64: 不支持此值 (它不会正确执行).
128: 阻止修饰符含 Shift-Control-Alt 的键.

例如, Limit1 将阻止输入不含修饰符的热键例如字母和数字, 而 Limit15 则至少需要两个修饰键. 如果用户输入了一个被禁止的修饰键组合, 则自动使用 Control+Alt 组合代替.

Hotkey 控件对热键的支持有限. 例如, 它不支持鼠标/游戏杆热键或 Windows 键 (LWin 和 RWin). 解决的方法之一是提供一个或多个 checkbox 作为为用户启用额外的修饰键的工具例如 Windows 键.

DateTime

描述: 一个看起来像单行编辑控件的框, 但它接受一个日期或时间. 同时提供一个下拉日历.

例如: Gui, Add, DateTime, vMyDateTime, LongDate

最后一个参数可以是下列的其中一个:

(omitted): 省略时, 使用区域设置的短日期格式. 例如, 在某些区域设置中它看起来像这样: 6/1/2005

LongDate: 使用区域设置的长日期格式. 例如, 在某些区域设置中它看起来像这样: Wednesday, June 01, 2005

Time: 仅显示时间, 使用区域设置的时间格式. 尽管不显示日期, 它仍然存在于控件中并且与 YYYYMMDDHH24MISS 格式的时间一起被获取.

(custom format): 指定 日期和时间格式 的任意组合. 例如, M/d/yy HH:mm 格式显示的时间看起来像 6/1/05 21:37. 同样, dddd MMMM d, yyyy hh:mm:ss tt 格式显示的时间看起来像 Wednesday June 1, 2005 09:37:45 PM. 想要原义显示的字母和数字应该包围在一对单引号中中, 例如: 'Date:' MM/dd/yy 'Time:' hh:mm:ss tt. 相比之下, 非字母数字字符, 如空格, 制表符, 斜杠, 冒号, 逗号和其他标点不需要包围在单引号中. 例外情况是单引号字符本身: 要产生原义的单引号, 请使用四个连续的单引号 (''''), 或仅使用两个引号如果它们已经包含在外部的一对引号中.

DateTime 用法

要预选今天外的其他日期, 请在 选项 中包含单词 Choose 接着一个 YYYYMMDD 格式的日期. 例如, Choose20050531 将预选 May 31, 2005 (和其他选项一样, 它也可以是一个变量例如 Choose%Var%). 要不选择日期/时间, 请指定 ChooseNone. ChooseNone 也在控件中创建一个复选框, 只要控件中不含日期此复选框则是未选中状态. 当控件中不含日期时, Gui Submit 和 GuiControlGet 命令将获取到一个空值 (空字符串).

日期的时间部分是可选的. 但是, 当进入或离开控件时它必须总是在日期之前. 时间部分的格式为 HH24MISS (小时数, 分钟数, 秒数), 其中 HH24 含义是用 24 小时格式表示; 例如, 09 为 9am 而 21 为 9pm. 因此, 一个完整的日期时间字符串的格式应为 YYYYMMDDHH24MISS.

当在 YYYYMMDDHH24MISS 格式中指定日期时, 可以仅包含主要部分. 其他任何省略的元素将使用下列默认值代替:
MM: 月份 01
DD: 日期 01
HH24: 小时 00
MI: 分钟 00
SS: 秒 00

在下拉日历中, 点击底部的今日字符串可以选择今天的日期. 此外, 还可以点击年份和月份名称, 这样可以方便的导航到一个新的月份或年份.

键盘导航: 使用上/下箭头键, Numpad+/Numpad-, 和 Home/End 来增加或减少控件的值. 使用左右箭头键可以在控件中的区域间移动. 在下拉日历中, 使用箭头键可以在日期间移动; 使用 PageUp/Down 可以在月份间往后/往前移动; 使用 Ctrl-PageUp/Down 可以在年份间移动; 使用 Home/End 可以选择当月的第一天/最后一天.

当使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 接收到所选择的 YYYYMMDDHH24MISS 格式的日期和时间. 日期和时间都存在不论控件中它们是否实际可见.

如果控件有 g-label, 每当用户改变日期或时间时此标签会运行. 每次运行时, 控件的 关联输出变量 (如果有的话) 会自动更新为当前选择的日期/时间.

Windows 95 和 NT4 需要和随 Internet Explorer 3.0 一起发布的 DLL 版本或更高的版本才能支持 DateTime 控件.

DateTime 选项:

Choose: 参见 上面.

Range: 限制可以选择的日期范围. 在单词 Range 后指定以 YYYYMMDD 格式表示的最小和最大的日期 (它们之间使用破折号连接). 例如, Range20050101-20050615 将限制可选择的日期为 2005 年开始的 5 个半月. 最小或最大的日期可以省略, 此时控件中的日期在这个方向上不受限制. 例如, Range20010101 将禁止选择早于 2001 年的日期而 Range-20091231 (由破折号前导) 将禁止选择迟于 2009 年的日期. 如果不含 Range 选项, 介于 1601 和 9999 年份之间的任何日期都可以选择. 无法对日期的时间部分进行限制.

Right: 使得下拉日历在控件的右边而不是左边拉下.

1: 在 选项 中指定数字 1 在控件的右边提供一个增减控件来修改日期和时间的值, 这会取代其他地方可用的下拉月历的修改.

2: 在 选项 中指定数字 2 在控件中提供一个复选框, 用户可以取消此复选框选择来表示没有选择日期/时间. 控件创建后无法改变此选项.

MonthCal

描述: 一个又高又宽的控件, 其中以日历的格式显示一个月中的所有日子. 用户可以选择单个日期或日期范围.

例如: Gui, Add, MonthCal, vMyCalendar

要预选今天外的其他日期, 请在最后一个参数中以 YYYYMMDD 格式指定它 (例如 20050531). 通过在两个日期间包含破折号可以预选一个日期范围 (例如 20050525-20050531).

通常最好忽略 MonthCal 的宽度 (W) 和高度 (H) 这样它自动调整大小来准确适应一个月份. 要垂直的显示多个月份, 请在 选项 中指定 R2 或更高. 要水平的显示多个月份, 请指定 W-2 (W 负 2) 或更高. 这些选项可以同时出现, 此时在两个方向上扩展.

点击控件底部今日字符串可以选择今天的日期. 此外, 还可以点击年份和月份的名称来方便的选择一个新的年份或月份.

与 DateTime 的下拉日历不同, 在 MonthCal 中一般不支持键盘导航.

当使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到所选择的 YYYYMMDD 格式表示的日期 (不含任何时间部分). 但是, 当 multi-select 选项存在时, 会得到以破折号连接的最小和最大日期 (例如 20050101-20050108). 在可以多选的日历中如果仅选择单个日期, 最小和最大日期会同时出现但它们是相同的. StringSplit 可以把日期分离开来. 例如, 后面的命令将把最小日期保存在 Date1 而最大日期保存在 Date2: StringSplit, Date, MyMonthCal, -

如果 MonthCal 含有 g-label, 其每次运行时会更新控件的 关联输出变量 (如果有的话) 为当前选择的日期或范围. 默认情况下, 仅当出现下列情况时标签才运行: 1) 用户改变了选择; 或 2) 每隔两分钟, 以防新的一天到来 (此行为是操作系统的怪癖). 但是, 如果控件的 选项 中含有单词 AltSubmit, g-label 会运行的更频繁, 此时内置变量 A_GuiEvent 当改变日期时包含单词 Normal, 点击一个日期时包含数字 1, 而当 MonthCal 释放 "鼠标捕获" 时包含数字 2. 例如, 如果用户双击一个新日期, 标签将运行五次: 其中一次为 Normal, 两次为 1, 还有两次为 2. 通过 计算两次数字 1 实例之间的时间间隔 可以检测双击.

当以 YYYYMMDD 格式指定日期时, MM 和/或 DD 部分可以省略, 此时它们默认为 1. 例如, 200205 被看作是 20020501, 而 2005 被看作是 20050101.

Windows 95 和 NT4 需要和随 Internet Explorer 3.0 一起发布的 DLL 版本或更高的版本才能支持 MonthCal 控件.

MonthCal 选项:

Multi: 多选. 允许用户使用 shift-click 或 click-drag 来选择一个连续的日期范围 (用户仍然可以选择单个日期). 可以明确指定此选项或在创建控件时通过指定一个选择范围的方法来使此选项自动生效. 例如: Gui, Add, MonthCal, vMyCal, 20050101-20050108. 控件创建后无法改变此选项.

Range: 限制日历中可以选择的时间范围. 在单词 Range 后指定以 YYYYMMDD 格式表示的最小和最大的日期 (它们之间使用破折号连接). 例如, Range20050101-20050615 将限制选区为 2005 年开始的 5 个半月.最小或最大的日期可以省略, 此时日历在这个方向上不受限制.例如, Range20010101 将禁止选择早于 2001 年的日期而 Range-20091231 (由破折号前导) 将禁止选择迟于 2009 年的日期.如果不含 Range 选项, 介于 1601 和 9999 年份之间的任何日期都可以选择.

4: 在 选项 中指定数字 4 可以在每行日期的左边显示周数 (1-52). Week 1 被定义为至少包含四天的第一周.

8: 在 选项 中指定数字 8 可以避免控件中当前日期往复循环.

16: 在 选项 中指定数字 16 可以禁止在控件的底部显示今天的日期.

Slider

描述: 一个滑动栏, 用户可以沿着垂直或水平轨道移动. 在任务栏的托盘中的标准音量控件是滑动栏的一个例子.

例如: Gui, Add, Slider, vMySlider, 50

请在最后一个参数中指定滑动栏的初始位置. 如果最后一个参数省略, 滑动栏初始位置为 0 或允许的范围中最接近 0 的数字.

用户可以通过下列方法滑动控件: 1) 用鼠标拖拉滑动栏; 2) 用鼠标在滑动栏的轨道区域点击; 3) 当焦点在控件上时转动鼠标滚轮; 或 4) 当焦点在控件上时按下下列按键: 方向键, 向上翻页键, 向下翻页键, Home, 和 End.

使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到滑动栏当前的数字位置. 每当控件的 g-label 运行时也将此位置保存到输出变量中.

如果滑动栏含有 g-label, 默认情况下仅当用户停止移动滑块时它才将运行 (例如在拖拉滑块后释放了鼠标按钮). 但是, 如果在控件的 选项 中指定了单词 AltSubmit, 所有滑动栏事件发生 g-label 都会运行而内置变量 A_GuiEvent 将包含下列数字或字符串的其中一个:

0: 用户按下了左方向键或上方向键.
1: 用户按下了右方向键或下方向键.
2: 用户按下了向上翻页键.
3: 用户按下了向下翻页键.
4: 用户用鼠标滚轮移动了滑块, 或已完成把滑块拖放到新位置的操作.
5: 用户正用鼠标拖动滑块即鼠标按钮当前是按下的.
6: 用户按下了 Home 键来移动滑块到左端或顶部.
7: 用户按下了 End 键来移动滑块到右端或底部.
Normal: 用户已经使用鼠标或键盘完成滑块移动. 注: 鼠标滚轮移动的例外情况是 (#4), 即使对于上面的数字事件其中之一 g-label 已经运行了一次, 对于 "normal" 事件它还会再次运行.

Slider 选项:

Buddy1 和 Buddy2: 最多可以指定两个现有的控件来自动定位到滑动条的两侧. Buddy1 显示在左边或顶部 (取决于是否存在 Vertical 选项). Buddy2 显示在右侧或底部. 在单词 Buddy1 或 Buddy2 后指定一个现有控件的 变量名称 . 例如, Buddy1MyTopText 将分配一个变量名称为 MyTopText 的控件. Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此选项.

Center: 滑块 (用户移动滑动栏) 两端将是钝的而不是指向其中一端.

Invert: 反转控件使得较低值被视为右边/底端而不是左边/顶端. 此选项常用来让垂直滑动栏在惯例的音量控件方向上移动. 注: 下面描述的 ToolTip 选项将不会服从反转因此不应在此时使用.

Left: 滑块 (用户移动滑动栏) 将指向上方而不是下方(原文中为顶端和底端,这里用上/下方是为了避免和滑动栏的顶端/底端混了). 但如果存在 Vertical 选项, 滑块将指向左边而不是右边.

Line: 指定当用户按下其中一个方向键时移动位置的数字. 在单词 Line 后指定移动位置的数字. 例如: Line2

NoTicks: 不显示轨道旁边的刻度标记.

Page: 指定当用户按下向上或向下翻页键时移动位置的数字. 在单词 Page 后指定移动位置的数字. 例如: Page10

Range: 指定 0 到 100 外的其他范围.在单词 Range 后指定最小值, 一个破折号和最大值.例如, Range1-1000 将允许选择一个介于 1 和 1000 之间的数字; Range-50-50 将允许一个介于 -50 和 50 之间的数字; 而 Range-10--5 将允许一个介于 -10 和 -5 之间的数字.

Thick: 指定滑块 (用户移动滑动栏) 的长度. 在单词 Thick 后指定以像素为单位的厚度 (例如 Thick30). 在 Windows XP 或更高版本的系统中要超过一定的厚度, 或者指定 Center 选项或者移除控件的主题或许是必要的 (通过在控件的选项中指定 -Theme 可以移除控件的主题).

TickInterval: 提供显示在轨道旁边指定间隔的刻度标记. 在单词 TickInterval 后指定间隔, 在间隔上显示另外的刻度标记 (如果省略间隔, 其默认值为 1). 例如, TickInterval10 将每隔 10 位置显示一个刻度标记.

ToolTip: 创建一个 tooltip 当用户拖动滑动栏时显示其数字位置. 要使 tooltip 不显示在默认位置, 请指定下列单词的其中一个代替: ToolTipLeft 或 ToolTipRight (对于水平滑动条); ToolTipTop 或 ToolTipBottom (对于垂直滑动条). Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此选项.

Vertical: 使控件上下滑动而不是左右滑动.

在控件创建后可以通过 GuiControl 改变上面的选项.

Progress

描述: 一个双彩条, 通常用来指示一个操作接近完成的程度.

例如: Gui, Add, Progress, w300 h20 cBlue vMyProgress

在最后一个参数中指定进度条的初始位置 (如果省略, 进度条初始位置为 0 或允许的范围中最接近 0 的数字). 要在以后改变进度条的位置, 请参照这些例子, 它们都是对 关联变量名 为 MyProgress 的进度条进行操作:

GuiControl,, MyProgress, +20  ; Increase the current position by 20.
GuiControl,, MyProgress, 50  ; Set the current position to 50.

对于水平进度条, 进度条的厚度等于控件的高度. 对于垂直进度条它等于控件的宽度.

Progress 选项:

Cn: 改变进度条的颜色. 指定 n 为 16 种 HTML 基础颜色 之一或 6 位的 RGB 颜色值. 例如: cRed, cFFFF33, cDefault. 如果从没有使用过 C 选项 (或指定 cDefault), 将使用系统默认的进度条颜色.

BackgroundN: 改变进度条的背景颜色. 指定 n 为 16 种 HTML 基础颜色 之一或 6 位的 RGB 颜色值.例如: BackgroundGreen, BackgroundFFFF33, BackgroundDefault. 如果从没有使用过 Background 选项 (或指定 BackgroundDefault), 将使用窗口的或进度条后 标签控件 的颜色作为背景颜色.

Range: 指定 0 到 100 外的其他范围.在单词 Range 后指定最小值, 一个破折号和最大值.例如, Range0-1000 将允许一个介于 0 和 1000 之间的数字; Range-50-50 将允许介于 -50 和 50 之间的数字; 而 Range-10--5 将允许介于 -10 和 -5 之间的数字. 在 Windows 95 和 NT4 系统中, 只有安装了Internet Explorer 3.0 或更高版本后, 含有负数或超过 65535 数字的区间才能正确的执行.

-Smooth (负 Smooth): 显示一段段的长度而不是一个平滑连续的进度条. 指定 -Smooth 也是在 Windows XP 或更高版本的系统中显示含主题的进度条的要求之一. 其他的要求是没有使用自定义的颜色即 C 和 Background 选项都省略了. Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此选项.

Vertical: 使进度条垂直上升或下降而不是水平移动.Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此选项.

在控件创建后可以通过 GuiControl 改变上面的选项.

GroupBox

描述: 一个矩形的框, 常用来封装一组相关的控件. 此时最后一个参数为组合框的标题, 其(如果存在)显示在组合框的左上角.

例如: Gui, Add, GroupBox, w400 h300, Geographic Criteria

默认情况下 GroupBox 的标题可以只有一行文本. 在选项中指定 Wrap 可以覆盖此特性.

要指定控件中的行数 (或高度和宽度), 请参见 控件的位置和大小.

Tab2

描述: 一个大的包含多个页面的控件, 其中的每个包含其他控件. 从此以后, 这些页面被称为 "标签".

Tab2 vs. Tab: v1.0.47.05 添加了 "Tab2" 控件, 其中修复了原 "Tab" 控件中很少出现的重绘问题 (例如通过点击 GUI 窗口中控件的某个部分来激活窗口时, 如滚动条, 可能无法正确重绘). 为了向后兼容保留了原 Tab 控件, 因为 Tab2 在 tab 键导航顺序中把其标签页控件放在它所包含的控件之后. 新脚本应尽可能使用 Tab2.

例如: Gui, Add, Tab2,, General|View|Appearance|Settings

上述的最后一个参数是管道分隔的标签名称列表. 要在窗口初次出现时预选其中的某个标签, 请在此项后包含两个管道符.或者, 在 选项 中包含单词 Choose 接着预选的项编号.例如, Choose5 将预选第五个标签 (和其他选项一样, 它也可以是一个变量 Choose%Var%). 要在控件创建后改变选择的标签, 添加标签或移除标签, 请使用 GuiControl.

创建一个 Tab 控件后, 随后添加的控件自动属于其首个标签. 这在任何时候都可以改变, 请参照这些例子:

Gui, Tab  ; Future controls are not part of any tab control.
Gui, Tab, 3  ; Future controls are owned by the third tab of the current tab control.
Gui, Tab, 3, 2  ; Future controls are owned by the third tab of the second tab control.
Gui, Tab, Name  ; Future controls are owned by the tab whose name starts with Name (not case sensitive).
Gui, Tab, Name,, Exact  ; Same as above but requires exact match (case sensitive too).

使用上面的每一个例子分配控件到一个还不存在的标签页或标签控件也是可能的 (除了使用 Name 方法的情况). 但在此情况下, 不支持下面描述的相对位置选项.

Positioning: 当一个标签控件的每个标签页接收到其首个子控件, 此子控件在下列情况下将有特殊的默认位置: 1) X 和 Y 坐标同时省略, 此时首个子控件放在标签控件内部的左上角 (拥有标准的 margin), 而首个子控件后的其他子控件放在前面控件的下面; 2) 指定了 X+n 和/或 Y+n 位置选项, 此时子控件被放在相对于标签控件内部的左上角的位置. 例如, 指定 "x+10 y+10" 将控件放置在左上角往右往下各 10 个像素的位置.

子控件不一定要在它们 Tab 控件边界的内部: 每当选择或取消选择它们的标签页时它们仍会被隐藏和显示. 此行为特别适合于下面描述的 "buttons" 样式.

使用 Gui Submit 命令后, 控件的 关联输出变量 (如果有的话) 会接收到当前选择的标签页名称. 但是, 如果控件含有 AltSubmit 属性, 输出变量将接收到标签页位置编号 (首个标签页为 1, 第二个为 2, 等).

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户切换到一个新标签页时 MySubroutine 标签会自动运行. 如果标签控件同时有 g-label 和 输出变量, 每当用户切换到一个新标签页, 输出变量将被设置为原来选择的标签页名称 (在含有 AltSubmit 属性时则为编号).

键盘导航: 用户按下 Control-PageDown/PageUp 可以在标签控件的页面间导航; 如果键盘焦点在不属于标签控件的控件上, 将导航到窗口的首个标签控件. 也可以使用 Control-Tab 和 Control-Shift-Tab, 除非当前焦点控件在多行编辑控件此时它们不起作用.

每个窗口可能不能含有超过 255 个的标签控件.每个标签控件可能不能含有超过 256 个标签 (页). 此外, 一个标签控件中可能不能包含其他的标签控件.

Tab 选项:

Choose: 参见 上面.

-Background (负号接着单词 background): 取消 窗口自定义背景色 而使用系统默认的 Tab 控件颜色. 指定 +Theme -Background 使得 Tab 控件适应于当前桌面主题. 然而, 在这样标签控件内的大多数控件类型将看起来很奇怪因为它们的背景颜色不匹配标签控件的背景颜色. 对于某些控件类型这种情况通过在它们的选项中添加 BackgroundTrans 可以修复 (例如 Text).

Buttons: 在控件的顶部创建一系列按钮而不是一系列标签页 (此时在默认下将没有边界因为显示的区域实际并不包含控件).

Left/Right/Bottom: 指定这些单词的其中一个让标签页在左边, 右边或底部而不是顶部. 参见 TCS_VERTICAL 了解对于 Left 和 Right 的限制.

-Wrap: 禁止标签页占用多行 (此时为了适应于过多的标签页, 会显示箭头按钮以允许用户滑动来查看更多标签页).

要指定控件中文本的行数 (或高度和宽度), 请参见 控件的位置和大小.

Icons in Tabs: 通过 SendMessage 可以在每个标签的名称/文本旁边显示一个图标. 演示的例子参见论坛主题 Icons in tabs.

StatusBar [v1.0.44+]

描述: 附加到窗口底部的一行文本和/或图标, 通常用来报告状态的变化.

; Example:
Gui, Add, StatusBar,, Bar's starting text (omit to start off empty).
SB_SetText("There are " . RowCount . " rows selected.")

状态栏最简单的用法是每当应该报告给用户的一些状态改变时调用 SB_SetText(). 要报告多片的信息, 通过 SB_SetParts() 把状态栏分成多段. 要在状态栏中显示图标, 请调用 SB_SetIcon().

下列所有的 StatusBar 函数操作于当前线程的 默认 GUI 窗口 (这可以通过 Gui, 2:Default 改变). 如果默认窗口不存在或不含有状态栏, 所有 SB 函数返回 0 来表明此问题.

SB_SetText(NewText [, PartNumber, Style]): 在状态栏指定部分显示 NewText. 如果 PartNumber 省略, 默认值为 1. 否则, 请指定一个介于 1 和 256 之间的整数.如果 Style 省略, 默认值为 0, 此时使用让状态栏那部分看起来凹陷的传统边界. 否则, 指定 1 则不含边界, 而指定 2 则含有让状态栏看起来是高出的边界. 最后, 在 NewText 中任意地方最多可以使用两个制表符 (`t): 在首个制表符右边的任何内容显示在此部分中心, 而第二个制表符右边的内容显示为右对齐. SB_SetText() 成功时返回 1 而失败返回 0.

SB_SetParts([Width1, Width2, ... Width255]): 根据指定的宽度 (单位为像素) 把状态栏分成多个部分. 如果省略所有参数, 状态栏恢复为单个很长的唯一一个部分. 否则, 指定除了最后一部分外其余每部分的宽度 (最后一部分将填充状态栏的剩余宽度). 例如, SB_SetParts(50, 50) 将创建三个部分: 前两个部分的宽度都为 50 而最后一部分占据所有剩余的宽度. 注: SB_SetParts() "删除" 的任何部分下次显示时初始不含文本 (而且, 其中的图标被自动销毁). 执行成功时, SB_SetParts() 返回一个非零值 (状态栏的 HWND). 失败时返回 0.

SB_SetIcon(Filename [, IconNumber, PartNumber]): 在指定部分的文本左边显示一个小图标 (如果 PartNumber 省略, 默认值为 1). Filename 为图标 (.ICO), 光标 (.CUR), 或动画光标 (.ANI) 文件的名称 (动画光标在状态栏上实际将不会动). 图标的其他来源包括下列文件类型: EXE, DLL, CPL, SCR, 和包含图标资源的其他类型. 要使用文件中的图标组而不是首个图标, 请在 IconNumber 中指定其编号. 例如, SB_SetIcon("Shell32.dll", 2) 将使用第二个图标组中的默认图标. SB_SetIcon() 成功时返回图标的 HICON 而失败返回 0. HICON 是一个可以被大多数脚本安全忽略的系统资源因为当状态栏所在窗口销毁时它被自动销毁. 同样, 当 SB_SetIcon() 用一个新的图标替换旧图标时旧图标被销毁. 这种情况可以使用以下方法避免:

Gui +LastFound
SendMessage, 0x40F, part_number - 1, my_hIcon, msctls_statusbar321  ; 0x40F is SB_SETICON.

SB_SetProgress(): 创建和控制状态栏里的进度条. 此函数可以从 www.autohotkey.com/forum/topic37754.html 获取.

G-Label Notifications: 一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户点击状态栏时 MySubroutine 标签自动运行. 此子程序中可参考使用内置变量 A_Gui 和 A_GuiControl. 更重要的是, 它可以参考 A_GuiEvent, 其包含下列字符串的其中一个 (考虑到和未来版本的兼容性, 一个脚本不应假定这些字符串是唯一可能的值):

  • Normal: 用户左键单击状态栏. 变量 A_EventInfo 包含目标部分编号 (然而, 如果用户点击状态栏右边靠近大小调整手柄的地方时目标部分编号可能是一个很大的整数).
  • RightClick: 用户右键单击状态栏. 变量 A_EventInfo 包含目标部分编号. 注: 如果状态栏含有 g-label 将不会调用 GuiContextMenu. 此外, 当脚本需要知道用户点击的是哪个部分编号 (A_EventInfo) 时应该使用 g-label 的 RightClick 事件代替 GuiContextMenu.
  • DoubleClick: 用户双击状态栏. 变量 A_EventInfo 包含目标部分编号.
  • R: 用户 右键双击状态栏. 变量 A_EventInfo 包含目标部分编号.

Font and Color: 尽管字体大小, 外观和样式可以通过 "Gui Font" 设置 (像普通控件一样), 文本颜色不能改变. 此外, 不服从 "Gui Color" 的颜色设置; 代替的方法是, 状态栏的背景颜色可以通过在 选项 中指定单词 Background 接着一个颜色名称 (参见 颜色图表) 或 RGB 值 (0x 前缀可以省略) 来改变. 例如: BackgroundSilver, BackgroundFFDD99, BackgroundDefault.

Hiding the StatusBar: 创建时可以通过 Gui, Add, StatusBar, Hidden vMyStatusBar 隐藏状态栏. 要在创建后某个时候隐藏它, 请使用 GuiControl, Hide, MyStatusBar. 要显示, 请使用 GuiControl, Show, MyStatusBar. 注: 隐藏状态栏不会降低窗口的高度. 如果期望这样, 一个简便的方法是 Gui, Show, AutoSize.

Styles (很少使用): 参见 状态栏样式表.

已知的限制: 1) 如果某个控件的位置和状态栏重叠, 那么它有可能会被绘制在状态栏的上方. 避免这种情况的一个方法是通过 GuiSize label 动态的缩小这样的控件. 2) 每个窗口只允许有一个状态栏控件.

Example: TreeView 页面 底部演示了一个多部分的状态栏.

Internet Explorer Control

MSIE 浏览器控件可以通过 DllCall 嵌入到 GUI 窗口中. 控件中可以显示网页或其他浏览器兼容的内容. 演示的例子参见 www.autohotkey.com/wiki/index.php? title=Internet_Explorer_Control

相关

ListView, TreeView, Gui, GuiControl, GuiControlGet, Menu


GuiControl

对一个图形用户界面窗口的控件做出种种改变。

GuiControl, Sub-command, ControlID [, Param3]

参数

Sub-command | 参见下面的列表。
ControlID

如果目标控件有一个关联的变量，那么将变量名指定为 ControlID (这个方法优先于后面描述的方法)。由于这个原因，通常最好给每一个之后要被 GuiControl 或者 GuiControlGetit 存取的控件指定一个变量名，即使那个控件没有输入功能(例如 GroupBox 或者 Text)。

如若不然，ControlID 可以是 ClassNN (控件的类名和实例号) 或者控件的名字/文本，这两者都可以通过 Window Spy(窗体侦探) 来决定。当使用名字/文本时，匹配的行为可以由 SetTitleMatchMode 决定。注意：一个图片控件的文件名字 (和控件创建时指定的一样) 可以当做 ControlID 使用。
Param3 | 除了下面 sub-commands 列表中说明的，这个参数是被省略的。

ErrorLevel

如果指定的窗体/控件不存在或者其他一些错误导致命令不能工作，ErrorLevel 被设为 1 。否则，它被设为 0 。

Sub-commands

(Blank) (空白): 将 Sub-command 留空，然后通过 Param3 给予控件新的内容。比如：

Picture: Param3 应当是要加载的图片的文件名 (支持的文件类型参见 Gui Picture)。在文件名的前面可以指定零个或多个下面的参数：*wN (宽度 N), *hN (高度 N), 和 *IconN (DLL 或者 EXE 文件中的图标的组号)。下面的例子中，第二个图标组中的默认的图标载入的宽度是 100 ，通过 "keep aspect ratio" 设置自动高度: GuiControl,, MyPic, *icon2 *w100 *h-1 C:\My Application.exe。指定 *w0 *h0 来使用图像的实际高度和宽度。如果 *w 和 *h 被省略，图像将被缩放来适应当前控件的尺寸。当从多图标的 .ICO 文件载入图标的时候，指定宽度和高度可以决定哪个图标将被载入。注意：在最后一个选择项和文件名之间只能使用一个空格或者制表符；其他任何空格或者制表符将被当做文件名的一部分。

Text/Button/GroupBox/StatusBar: 对于 Param3 指定控件的新文本。因为控件不能自动改变大小，所以如果控件需要变宽，请使用 GuiControl, Move, MyText, W300 。对于 StatusBar，这个选项仅设置第一部分的文本。(想要更灵活的实现请使用 SB_SetText() )。

Edit: 为了正常显示 Param3 中缺少之前回车 (`r) 的换行 (`n)，它被自动的转换为 CR+LF (`r`n)。然而，这在通常情况下无需考虑，因为 "Gui Submit" 和 "GuiControlGet OutputVar" 命令能自动撤销这一替换，使 CR+LF 变回 LF (`n)。

Hotkey: Param3 可以为空来清除控件，或者一组有键名的修改器。例如：^!c, ^Numpad1, +Home。支持的修改器仅有 ^ (Control), ! (Alt), 和 + (Shift)。可用键名请参见 key list。

Checkbox: Param3 可以为 0 来不选择按钮，1 来选择，或者 -1 来给它一个灰色的检查标志。另外，Param3 默认是控件的新标题/文本。关于如何重写这一行为，参考下面的 Text 。

Radio: 和上面的 Checkbox 类似。但是，如果单选按钮是选中的 (开启) 而且它是一个单选按钮组中的一项，那么组中其他的单选按钮自动即为未选中的。想要选中一个只有一个变量的单选按钮组中的一个新的按钮并且此按钮不是那个变量直接联系的，请指定按钮的 ControlID 为它的 名字/文本 。

DateTime/MonthCal: 为 Param3 指定一个格式为 YYYYMMDDHH24MISS 的日期-时间标记。指定 %A_Now% 来使用当前的日期和时间 (当天)。对于日期时间控件，Param3 可以省略来使控件不选中日期/时间 (如果它在创建时有 that ability (这一能力))。对于 MonthCal 控件，如果它是 multi-select (多选择的)，那么可以指定一个范围。

UpDown/Slider/Progress: Param3 应当是控件的新位置。如果 Param3 的第一个符号是加号，这个数字就被认为是相对当前位置的偏移值，例如，+10 把位置增加10，而 +-10 (加负十) 把位置减去10。如果新位置在控件的范围之外，控件通常被设置在最近的合法值处。

Tab/DropDownList/ComboBox/ListBox: Param3 应当包含一个管道符分隔的要加在控件后的条目的列表。要替换 (重写) 这个列表，在第一个字符前加上一个管道符 (例如 |Red|Green|Blue)。要将控件置空，只需指定一个管道符 (|)。要预先选定其中一个条目，在它之后加上两个管道符 (例如 Red|Green||Blue)。条目之间的分隔符可以为其他字符，不一定是管道符。比如 Gui +Delimiter`n 可以将它改为换行而 Gui +DelimiterTab 将它改为制表符。

Tab controls: 除了以上段落描述的行为，一个标签页的子控件和它们原始的标签编号相关联；也就是说，它们永远不与它们的标签页的名字关联。因此，重命名或者删除一个标签页不会改变子控件所属的标签页的编号。例如，有三个标签页 "Red|Green|Blue"，第二个标签页通过 "GuiControl,, MyTab, |Red|Blue" 被移除，原来和 Green 标签页联系的子控件不会和 Blue 标签页关联。因为这一行为，通常情况下只有最后一个标签页才能被移除。用这种方法移除的标签随后还可以再被加进来，那时它们会重新声明原来的控件。

ListView 和 TreeView: 当 Sub-command 为空时不支持这两个参数。做为替代，请使用内建的 ListView functions 和 TreeView functions。

GuiControl, Text: 除了下面这几个，效果和上面的一样：
Checkbox/Radio: Param3 被当做新的文本/标题，即使它是 -1, 0, 或 1。
DateTime: Param3 被当做控件中显示的新的 date/time format (日期/时间 格式)。如果 Param3 被省略，任何自定义格式将被移除，短日期格式被使用。
ComboBox: Param3 被当做文本而直接放在下拉列表框的编辑控件中。

GuiControl, Move: 移动 和/或 缩放控件。在 Param3 中指定下面一个或几个可选字母：X (相对于窗口中用户区域的 x 坐标，即不包括标题栏，菜单栏和边框的区域); Y (y 坐标), W (宽度), H (高度)。例如:

GuiControl, Move, MyEdit, x10 y20 w200 h100
GuiControl, Move, MyEdit, % "x" VarX+10 "y" VarY+5 "w" VarW*2 "h" VarH*1.5 ; 通过 "% " 前缀使用 expression (表达式) 。

GuiControl, MoveDraw: 除了上面 "Move" 的功能，它还重画控件占据的窗口位置。尽管当重复和快速调用时可能会产生闪烁，它解决了在特定控件中绘画的问题，比如在 GroupBoxes 中。

GuiControl, Focus: 将键盘的焦点设置在控件上。要使有效，窗口通常不能被最小化或者被隐藏。

GuiControl, Enable / Disable: 使控件有效或者失效(灰化)。对于标签页控件，此选项还会使标签的子控件有效或失效。然而，任何通过 "GuiControl Disable" 显示禁止的控件在它的标签页被重新生效后仍然保持失效状态。单词 Disable 或者 Enable 后面可以可选的紧跟着 Zero 或 One。Zero 产生相反的效果。例如，Enable 和 Enable%VarContainingOne% 都使控件生效，但是 Enable%VarContainingZero% 将使它失效。

GuiControl, Hide / Show: 隐藏或者显示控件。对于标签页控件将会隐藏或显示标签下所有的子控件。另外如果你还想同时禁用控件的快捷键 (加下线字母)，通过 "GuiControl Disable" 禁用控件。单词 Hide 或者 Show 后面可以可选的紧跟着 0 or 1。产生相反的效果。例如，Show 和 Show%VarContainingOne% 都显示控件，但是 Show%VarContainingZero% 将隐藏它。

GuiControl, Delete (还没有实现): 这个子命令现在还不存在。对于一个工作区，使用上面的 Hide 和/或 Disable，或者通过 Gui Destroy 销毁或重建整个窗口。

GuiControl, Choose, ControlID, N: 设置列表框，下拉列表，复选框或者标签页中的选区为第 N 个入口。第一个入口 N 对应为 1，第二个入口对应为 2，依次类推 (如果 N 不是整数，下面描述的 ChooseString 方法将被作为替代使用)。与 Control Choose 不同，这个子命令不会触发任何与控件关联的 g-label ，除非 N 之前有一个管道符 (即使这样，g-label 仅在新的选区和旧选区不同的情况下被触发，至少对 Tab controls 是这样)。例如：GuiControl, Choose, MyListBox, |3.

此外要产生一个结束的事件，(例如在列表框中的双击)，请包含两个管道符而不是一个(不支持标签页)。

要选择或者取消选择 multi-select ListBox (多选列表框)中的所有 选项，参考下面的例子：

Gui +LastFound  ; 避免指定下面的 WinTitle 的需要。
PostMessage, 0x185, 1, -1, ListBox1  ; 选择所有选项。0x185 表示 LB_SETSEL。
PostMessage, 0x185, 0, -1, ListBox1  ; 取消选择所有选项。

GuiControl, ChooseString, ControlID, String: 设置列表框，下拉列表，复选框或者标签页中主要部分和 String 匹配的选区(选择)为入口。搜索不区分大小写。例如，如果一个控件包含项 "UNIX Text"，指定单词 unix (小写) 就足以选中它了。支持管道符和双管道符 (详细请参考上面的 "Choose" )。

GuiControl, Font: 把控件的字体改变为它所在窗口的当前使用的字体，字号，颜色和样式。例如：

Gui, Font, s18 cRed Bold, Verdana  ; 如果需要，使用类似这样的排列方式给窗口指定一个新的默认字体。
GuiControl, Font, MyEdit  ; 使上面的字体对控件生效。

GuiControl, +/-Option1 +/-Option2 ... : 增加或者删除不同的选项或样式。所有的 GUI 选项 (control-specific 和 general) 都将被识别。下面的例子中， AltSubmit 选项被启用但是控件的 g-label 被删除： GuiControl, +AltSubmit -g, MyListBox

下个例子中，OK 按钮被设为新的默认按钮：
GuiControl, +Default, OK

尽管 styles (样式) 和 extended styles (扩展的样式) 也会被识别，它们中一些在控件创建以后不能被应用或者被删除。如果被指定的改变中至少一个被成功应用，ErrorLevel 被设为 0 。否则，它被设为 1 来指示没有应用任何改变。即使一个改变被成功应用，控件仍然可能选择忽视它。

注意

想要根据窗口号码而不是默认窗口进行操作(参加下面)，在子命令前面加上数字和一个冒号，如下面的例子所示：
GuiControl, 2:Show, MyButton
GuiControl, 2:, MyListBox, Item1|Item2

当任何作为 GUI 操作结果的线程被启动时，一个 GUI thread (线程) 被定义。GUI 操作包括选择 GUI 窗口的菜单栏的一项，或者触发它的 g-labels 中的一项(比如按下一个按钮)。

GUI 线程的默认窗口号码是启动线程的窗口号码。非GUI 线程使用 1 做为它们的默认窗口号码。

相关命令

Gui, GuiControlGet, Control

示例

GuiControl,, MyListBox, |Red|Green|Blue  ; 用新列表替换当前列表。
GuiControl,, MyEdit, New text line 1.`nNew text line 2.
GuiControl,, MyRadio2, 1  ; 选择这一单选按钮，不选择组中其他的。
GuiControl, Move, OK, x100 y200  ; 移动 OK 按钮到一个新位置。
GuiControl, Focus, LastName  ; 把键盘焦点设置在变量或者文本为 "LastName" 的控件上。


GuiControlGet

获取 GUI 窗体中控件的各种类型的信息.

GuiControlGet, OutputVar [, Sub-command, ControlID, Param4]

参数

OutputVar | 用于保存结果的变量名称.如果命令无法完成 (请参看下面的 ErrorLevel), 此变量被置空.
Sub-command | 见下表.
ControlID

如果省略或为空, 则假定此变量和输出变量的名称相同. 例如, GuiControlGet, MyEdit 等同于 GuiControlGet, MyEdit,, MyEdit.

如果目标控件有一个关联变量, 请将变量名指定为 ControlID (此方法优先于后面描述的方法). 由于这个原因, 最好给每个之后需要由 GuiControl 或 GuiControlGet 命令访问的控件指定一个变量, 即使此控件是非输入型控件 (例如 GroupBox 或 Text).

否则, ControlID 可以为 ClassNN (控件的类名和实例号) 或控件的名称/文本, 它们都可以使用 Window Spy 来确定. 当使用名称/文本时, 匹配模式由 SetTitleMatchMode 决定.注: 一个图片控件的文件名 (在控件创建时指定的) 也可以作为其 ControlID.
Param4 | 除非在下面的子命令列表中有特别注明, 否则此参数被忽略.

ErrorLevel

如果指定的窗口/控件不存在或其他一些错误导致命令无法工作, ErrorLevel 被设置为 1.否则, 它被设置为 0.

Sub-commands

(Blank): 把 Sub-command 留空来获取控件的内容. 除了下面的控件类型, 其他都是无须解释的:

Picture: 获取控件创建时最初指定的图片文件名. 即使指定一个新的图片文件名, 此名称也不会改变.

Edit: 获取编辑控件的内容, 但在文本中任何换行的地方将表示为简单的换行符 (`n) 而不是非 GUI 命令像 ControlGetText 和 ControlSetText 所使用的传统的 CR+LF (`r`n).

Hotkey: 如果控件中没有热键则获取的值为空. 否则它获取的是按键修饰符和键名. 例如: ^!C, ^Home, +^NumpadHome.

Checkbox/Radio: 如果控件被选中则返回 1, 未选中则返回 0, 而如果它含有灰色的复选标记则返回 -1.要获取控件的文本/标题而不是选择状态, 请在参数 Param4 中指定单词 Text.注: 不同于 Gui Submit 命令, 单选框按钮总是个别的获取, 不论它们是否在一个单选框的组中.

UpDown/Slider/Progress: 获取控件的当前位置.

Tab/DropDownList/ComboBox/ListBox: 获取当前选择的项目/标签的文本 (如果控件有 AltSubmit 属性时则获取它的位置). 对于组合框, 如果没有选择项目, 则获取控件编辑区域的文本.对于 多选列表框, 输出的内容中使用窗口的 当前分隔符.

ListView 和 TreeView: 当 Sub-command 为空时不支持这两种控件. 作为替代, 请使用内置的 ListView 函数 和 TreeView 函数.

StatusBar: 仅获取第一部分的文本.

注: 要明确的获取获取任何控件的文本/标题而不是其内容, 请在参数 Param4 中指定单词 Text.

GuiControlGet, OutputVar, Pos: 获取控件的位置和大小. 位置是相对于 GUI 窗口的客户区, 这是不包括标题栏, 菜单栏和边框的区域. 控件的信息保存在名称以 OutputVar 开始的四个变量中. 例如:

GuiControlGet, MyEdit, Pos
MsgBox The X coordinate is %MyEditX%. The Y coordinate is %MyEditY%. The width is %MyEditW%. The height is %MyEditH%.

在 函数 中, 要创建一组全局变量而不是局部变量, 请在使用此命令前 声明 OutputVar 为全局变量 (相反在 assume-global 函数中同样如此).

GuiControlGet, OutputVar, Focus: 获取当前拥有键盘焦点的控件的控件标识符 (ClassNN). 因为指定的 GUI 窗口为 活动 时其中的一个控件才拥有焦点, 所以如果其不活动则设置 OutputVar 为空. 用法示例: GuiControlGet, focused_control, focus

GuiControlGet, OutputVar, FocusV [v1.0.43.06+]: 与 Focus (上面的) 相同, 除了它获取的是焦点控件 关联变量 的名称. 如果目标控件没有关联变量, 则获取控件的文本/标题中开始的 63 个字符 (这常用来避免给每个按钮一个变量名).

GuiControlGet, OutputVar, Enabled: 如果控件是启用的则返回 1, 禁用的则返回 0.

GuiControlGet, OutputVar, Visible: 如果控件是可见的则返回 1, 隐藏的则返回 0.

GuiControlGet, OutputVar, Hwnd [v1.0.46.16+]: 获取控件的窗口句柄 (HWND). 控件的 HWND 通常使用于 PostMessage, SendMessage, 和 DllCall 命令中.注: HwndOutputVar 通常是获取 HWND 的一种较简洁的方式.

备注

要根据窗口编号而不是对默认的窗口进行操作 (见下文), 在子命令前加上数字和一个冒号, 例如:
GuiControlGet, MyEdit, 2:
GuiControlGet, MyEdit, 2:Pos
GuiControlGet, Outputvar, 2:Focus

一个 GUI 线程 被定义为一个 GUI 操作结果启动的任意线程. GUI 操作包括在 GUI 窗口的菜单栏选择一个项目, 或触发 GUI 窗口中某个 g-label (例如按下一个按钮).

一个 GUI 线程的默认窗口编号是启动此线程的窗口编号. 非 GUI 线程使用 1 作为默认窗口编号.

相关

Gui, GuiControl, ControlGet

示例

GuiControlGet, MyEdit
GuiControlGet, CtrlContents,, MyEdit  ; Same as the above except uses a non-default output variable.
GuiControlGet, MyCheckbox1 ; Retrieves 1 if it is checked, 0 if it is unchecked.
GuiControlGet, MyCheckbox1,,, Text  ; Retrieves the caption/text of the checkbox.
GuiControlGet, Pic, Pos, Static4  ; The position/size will be stored in PicX, PicY, PicW, and PicH


ListView (GUI)

ListView

目录

  • 入门和简单示例
  • 选项和样式
  • 视图模式: Report (默认), Icon, Tile, Small-Icon, 和 List.
  • 内置函数:
    • 行函数 (添加, 修改, 和删除行)
    • 列函数
    • 从 ListView 中获取数据
  • G-Label 通告
  • ImageLists (通过它把图标添加到 ListView 的方法)
  • ListView 备注
  • 示例

入门和简单示例

List-View 是由操作系统提供的最精心设计的控件之一. 在其最容易识别的形式中, 它显示一个多行多列组成的表格视图, 最常见的例子是资源管理器的文件和文件夹列表 (详细信息视图).

尽管它可能是精细的, ListView 的基本特性也易于使用. 创建 ListView 的语法为:

Gui, Add, ListView, Options, ColumnTitle1|ColumnTitle2|...

这里是一个工作的脚本, 它创建和显示包含用户 "我的文档" 目录中文件的列表的 ListView:

; Create the ListView with two columns, Name and Size:
Gui, Add, ListView, r20 w700 gMyListView, Name|Size (KB)

; Gather a list of file names from a folder and put them into the ListView:
Loop, %A_MyDocuments%\*.*
    LV_Add("", A_LoopFileName, A_LoopFileSizeKB)

LV_ModifyCol()  ; Auto-size each column to fit its contents.
LV_ModifyCol(2, "Integer")  ; For sorting purposes, indicate that column 2 is an integer.

; Display the window and return. The script will be notified whenever the user double clicks a row.
Gui, Show
return

MyListView:
if A_GuiEvent = DoubleClick
{
    LV_GetText(RowText, A_EventInfo)  ; Get the text from the row's first field.
    ToolTip You double-clicked row number %A_EventInfo%. Text: "%RowText%"
}
return

GuiClose:  ; Indicate that the script should exit automatically when the window is closed.
ExitApp

用于 "Gui, Add, ListView, Options" 的样式和选项

AltSubmit: 通知脚本有比正常更多的 ListView 事件类型. 换言之, g-label 运行的更频繁. 参见 ListView 通告 获取详情.

Background: 指定单词 Background 接着一个颜色名称 (参见 颜色图表) 或 RGB 值 (0x 前缀是可选的). 例如: BackgroundSilver, BackgroundFFDD99. 如果此选项不存在, ListView 最初默认的背景颜色由 Gui Color (或者如果没有, 则使用系统默认的背景颜色) 的最后一个参数设置. 指定 BackgroundDefault 应用系统的默认背景颜色 (通常为白色). 例如, 通过 GuiControl, +BackgroundDefault, MyListView 可以把 ListView 恢复为默认的颜色.

C: 文本颜色. 指定字母 C 接着一个颜色名称 (参见 颜色图表) 或 RGB 值 (0x 前缀是可选的).例如: cRed, cFF2211, c0xFF2211, cDefault

Checked: 在每行的左侧提供一个复选框. 当 添加 一行时, 在其选项中指定单词 Check 使复选框初始为选中而不是未选中状态. 用户可以点击复选框或按下空格键来选中或取消选中一行.

Count: 指定单词 Count 接着 ListView 最后将包含的总行数. 这不是限制: 超过此数目后仍然可以添加行. 相反, 此选项给控件一个暗示, 允许它一次性的分配内存而不是每次添加一行时, 这样极大的提高添加行时的性能 (这也可以提高排序性能). 为了提升更多的性能, 请在添加大量行前使用 GuiControl, -Redraw, MyListView. 随后, 使用 GuiControl, +Redraw, MyListView 来重新启用重绘 (这样也重绘了控件).

Grid: 提供水平的和垂直的线以形象的显示出行与行和列与列之间的边界.

Hdr: 指定 -Hdr (minus Hdr) 来隐藏包含列标题的特殊顶行. 后来要使它可见, 请使用 GuiControl, +Hdr, MyListView.

LV: 指定字符串 LV 接着 扩展的 ListView 样式 中的数字. 这些样式完全独立于通用扩展样式. 例如, 指定 -E0x200 将移除通用扩展样式 WS_EX_CLIENTEDGE 来去除控件的默认边框. 相比之下, 指定 -LV0x20 将移除 LVS_EX_FULLROWSELECT.

LV0x10: 指定 -LV0x10 防止用户通过拖动列标题到左边或右边来对它们重新排序. 然而, 通常没必要这么做因为列的实际重排不会影响脚本看到的列顺序. 例如, 从脚本的观点看第一列将总是 column 1, 即使用户实际已经把它移动到其他列的右边.

LV0x20: 指定 -LV0x20 来要求点击一行的第一个区域才可以选择它 (正常情况下点击在 任一 区域都将选择它). 这样的好处是用户可以更方便的绕着一组行拖动矩形来选择他们.

Multi: 指定 -Multi (负 Multi) 禁止用户一次选择多行.

NoSortHdr: 禁止点击标题. 此时将显示平坦的外观而不是正常的类似按钮的外观. 与其他大多数 ListView 样式不同, 此样式在 ListView 创建后无法改变.

NoSort: 关闭当用户点击列标题时发生的自动排序. 然而, 标题的外观看提来仍像按钮 (除非指定了 NoSortHdr).此外, g-label 仍将接收到 ColClick 通告, 对此它可以用自定义排序或其他操作来响应.

ReadOnly: 指定 -ReadOnly (负 ReadOnly) 来允许编辑每行首列的文本. 要编辑某行, 选择它接着按下 F2 键. 或者, 你可以对一行点击一次来选择它, 至少等待半秒钟, 然后再次点击同一行进行编辑.

R: 行高 (创建时). 指定字母 R 接着为行在控件中留出空间的数目. 例如, R10 将使控件 10 行的高度. 如果 ListView 使用报告视图外的其他 视图模式 创建, 控件会调整大小以适应含图标的行而不是文本行. 注: 添加 图标 到 ListView 的行中将增加每行的高度, 这将使得此选项不准确.

Sort: 控件根据首列的内容保持按字母顺序排列.

SortDesc: 和上面一样, 除了按降序排列.

WantF2 [v1.0.44+]: 指定 -WantF2 (负 WantF2) 来禁止使用 F2 键击 编辑 当前焦点行. 仅当 -ReadOnly 也有效时此设置才不会被忽略. 不论此设置如何, g-label 仍会接收到 F2 通告.

(未命名的数字样式): 由于上述以外的其他样式很少使用, 它们没有名称. 参见 ListView 样式表 了解这些样式.

视图模式

ListView 有五种视图模式, 其中最常见的是报告视图 (这是默认模式). 要使用一种其他视图, 请在选项列表中指定其名称. 也可以在控件创建后改变视图模式; 例如: GuiControl, +IconSmall, MyListView

Icon: 显示大图标视图. 在此视图和除 Report 外的所有其他视图中, 仅首列中的文本才可见. 要在此模式中显示图标, ListView 必须分配有一个含有大图标 ImageList.

Tile: 显示大图标视图但具有人体工学差异, 例如显示每项的文本在图标的右边而不是下面. Checkboxe 不能使用于此视图中. 此外, 尝试在比 Windows XP 更低版本的操作系统中显示此视图没有效果.

IconSmall: 显示小图标视图.

List: 以列表格式显示小图标视图, 其中图标显示在列中. 列的数目取决于控件的宽度和控件中最宽文本项目的宽度.

Report: 切换回报告视图, 这是最初的默认模式. 例如: GuiControl, +Report, MyListView

ListView 中的内置函数

所有的 ListView 函数操作于当前线程的 默认 GUI 窗口 (这可以通过 Gui, 2:Default 改变). 如果默认窗口不存在或不含有 ListView 控件, 所有函数返回 0 来表明此问题.

如果窗口含有多个 ListView 控件, 默认情况下函数操作于最近添加的那个. 要改变这种情况, 请指定 Gui, ListView, ListViewName, 此处 ListViewName 为 ListView 的 关联变量 的名称或 Window Spy 中显示的其 ClassNN. 一旦改变后, 所有现有和将来的 线程 将使用指定的 ListView.

当在此页面使用短语 "row number", 它指的是 ListView 中行的当前位置. 最上面一行为 1, 第二行为 2, 依此类推. 添加一行后, 其行号会因为排序, 删除和插入其他行而发生变化. 因此, 要根据内容查找特定的一行或多行, 通常最好在循环中使用 LV_GetText().

行函数

LV_Add([Options, Field1, Field2, ...]): 添加一个新行到列表底部. 参数 Field1 和其后的字段是新行的列内容, 可以是文本或数字 (包括数值的 表达式 结果). 要使任何字段为空, 请指定 "" 或等价物. 如果参数中太少字段而无法填满所有列, 后面剩下的列被留空. 如果太多字段, 后面多出的字段被忽略.

失败时, LV_Add() 返回 0. 成功时, 它返回新 行号, 如果 ListView 含有 Sort 或 SortDesc 样式则此行不一定是最后一行.

行选项: Options 参数是一个包含零个或多个下面列表中单词的字符串 (不区分大小写). 单词间使用空格或制表符分隔. 要移除一个选项, 请在选项前加上一个负号. 要添加一个选项, 可以在选项前加上一个正号但不是必需的.

Check: 在行中显示一个选中标记 (需要 ListView 含有 复选框). 要在以后取消选中它, 请使用 LV_Modify(RowNumber, "-Check").

Col: 指定单词 Col 接着列号, 从此列开始往后应用参数 Col1 和其后参数的内容. 此选项通常和 LV_Modify() 一起使用来修改行中个别字段, 不会影响它们左边的那些字段.

Focus: 设置键盘焦点到此行 (通常和 Select 一起使用). 要在以后取消它的焦点, 请使用 LV_Modify(RowNumber, "-Focus").

Icon: 指定单词 Icon 接着这行图标的编号, 这行图标显示在首列的左侧. 如果此选项不存在, 则使用 ImageList 中的首个图标. 要显示一个空白图标, 指定一个大于 ImageList 中图标编号的数字. 如果控件没有小图标 ImageList, 则 报告视图 中既不显示图标也不为其保留空间.

Select: 选择行. 要在以后取消选择, 请使用 LV_Modify(RowNumber, "-Select"). 当选择行时, 通常最好确保至少有一行总含有 焦点属性 因为这样允许 Appskey 在焦点行附近显示其 上下文菜单 (如果有的话).在单词 Select 后面可选跟着一个 0 或 1 来表示初始状态. 换言之, "Select" 和 "Select" . VarContainingOne 是相同的 (这里中间使用的是 连接运算符). 此方法也适用于上面的 Focus 和 Check.

Vis [1.0.44+]: 必要时通过滚动 ListView 确保指定行完全可见. 此参数仅对 LV_Modify() 有效; 例如: LV_Modify(RowNumber, "Vis")

LV_Insert(RowNumber [, Options, Col1, Col2, ...]): 与 LV_Add() 行为一样, 除了其首个参数的不同, 它指定了新插入行的行号. 任何在 RowNumber 上或其下方的行往下移来为新行腾出空间. 如果 RowNumber 大于列表中行的数目 (甚至可以高达 2147483647), 新行被添加到列表的底部. 想了解 选项, 请参见 行选项.

LV_Modify(RowNumber, Options [, NewCol1, NewCol2, ...]): 修改行的属性和/或文本, 成功时返回 1 而失败时返回 0. 如果 RowNumber 为 0, 则修改控件中 所有 行 (此时如果操作完全成功返回 1 而部分失败时返回 0). 当只存在前两个参数时, 仅修改行的属性而不改变其文本. 同样, 如果参数太少无法覆盖所有列, 后面剩下的列保持不变. ColN 选项 可以用来更新指定的列而不影响其他列. 关于其他选项, 请参见 行选项.

LV_Delete([RowNumber]): 如果省略参数, 则删除 ListView 中 所有 行. 否则, 仅删除指定 RowNumber 所在的行. 成功时返回 1 而失败返回 0.

列函数

LV_ModifyCol([ColumnNumber, Options, ColumnTitle]): 修改指定列的属性和/或文本和它的标题. 首列编号为 1 (不是 0). 如果省略所有参数, 则调整所有列的宽度以适应行的内容. 如果仅存在首个参数, 则仅自动调整指定列的大小. 只有在报告(详细信息)视图中时自动调整大小才有效果. 此函数成功时返回 1 而失败时返回 0.

列选项: Options 参数是一个包含零个或多个下面列表中单词的字符串 (不区分大小写). 单词间使用空格或制表符分隔.要移除一个选项, 请在选项前加上一个负号.要添加一个选项, 可以在选项前加上一个正号但不是必需的.

列选项: 常规

N: 指定 N 为列的新宽度, 单位为像素. 如果是唯一的选项, 此数字可以不带引号. 例如, 后面的两种形式都是有效的: LV_ModifyCol(1, 50) .... LV_ModifyCol(1, "50 Integer").

Auto: 调整列宽来适应其内容. 只有在报告(详细信息)视图中此选项才有效果.

AutoHdr: 调整列宽来适应其内容和列标题文本, 以较宽的为准. 当应用于最后一列时, 它将被设置为至少和 ListView 中剩余空间的宽度一样. 通常最好仅在行已经添加后才应用此设置, 因为这样允许当调整最后一列的大小时考虑到可能新增加的垂直滚动栏. 只有在报告(详细信息)视图中此选项才有效果.

Icon: 指定单词 Icon 接着 ImageList 中图标的编号然后是列标题文本. 指定 -Icon (负 icon) 来移除任何现有的图标. 在 Windows 95/NT4 系统中, 需要与 Internet Explorer 3.0 或更高版本一起发布的 DLL 文件才能支持列图标.

IconRight: 把图标放在列的右边而不是左边.

列选项: 数据类型

Float: 用于排序的目的, 指明此列包含浮点数 (不支持十六进制格式). 浮点数和文本列的排序性能最多可能比整数列的慢 25 倍.

Integer: 用于排序的目的, 指明此列包含整数. 为了能正确的排序, 每个整数必须是 32 位的; 即在范围 -2147483648 到 2147483647 内. 任何非整数的值在排序时将被视为零 (除非这些值以一个数字开始, 此时使用这个数字). 数字格式可以为十进制或十六进制 (例如 0xF9E0).

Text: 更改列返回到文本模式排序, 这是每列初始默认的排序方式. 在排序时仅有文本开始的 8190 个字符是有意义的 (除非使用了 Logical 选项, 此时限制为 4094).

列选项: 对齐 / 字距调整

Center: 让文本居于列中央. 要让整数或浮点数列居中, 请在单词 Integer 或 Float 后指定单词 Center.

Left: 让列文本左对齐, 这是每列初始默认的对齐方式. 在较旧版本的操作系统上, 首列可能会强制进行左对齐.

Right: 让列文本右对齐. 对于整数和浮点数列不需要指定此属性因为它们默认是右对齐的. 通过指定例如 "Integer Left" or "Float Center" 的字符串可以覆盖此默认的对齐方式.

列选项: 排序

Case: 列排序区分大小写 (仅影响 文本 列). 如果选项 Case, CaseLocale, 和 Logical 都省略, 在排序中大写字母 A-Z 被视为等同于它们相应的小写形式.

CaseLocale [v1.0.43.03+]: 列排序基于当前用户的区域设置并且不区分大小写 (仅影响 文本 列). 例如, 大多数英语和西欧地区把字母 A-Z 和 ANSI 字母例如 ? 和 ü 等同于它们的小写形式.这种方法也使用"单词排序", 它把单词中的连字符和撇号例如 "coop" 和 "co-op" 保持在一起.

Desc: 降序排列. 用户首次对此列排序时使用下降的顺序.

Logical [v1.0.44.12+]: 与 CaseLocale 相同, 除了把文本中的任何数字位序列看成真正的数字而不仅仅字符. 例如, 字符串 T33 将被视为大于 T4. Logical 需要 Windows XP 或更高版本的系统才支持 (在较旧的操作系统中, 自动使用 CaseLocale 代替). 此外, Logical 和 Case 是互斥的: 只有最近指定的那个才有效.

NoSort: 防止用户点击此列而对自动排序产生任何的影响.要禁用所有列的排序而不仅是其中的子集, 请在 ListView 的选项中包含 NoSort. 如果 ListView 含有 g-label, 当用户点击 no-sort 的列时仍将接收到 ColClick 通告.

Sort: 立即对列按升序排列 (即使含有 Desc 选项).

SortDesc: 立即对列按降序排列.

Uni: 单向排序. 此选项防止在相同列进行第二次点击来反转排序方向.

LV_InsertCol(ColumnNumber [, Options, ColumnTitle]): 创建一个新列, 以指定的 ColumnNumber 插入 (转移其他的列到右边来腾出空间). 首列编号为 1 (不是 0). 如果 ColumnNumber 大于当前控件中列的数目, 新列被添加到列表的底部. 新插入的列开始时内容是空的除非它是首列, 此时它继承原来首列的内容, 而原来首列的内容变为空的. 新列的属性 -- 例如是否使用 整数排序 -- 开始时总为它们的默认值除非使用了 选项 改变. 此函数返回新列的位置编号 (当失败时返回 0). ListView 中的最大列数是 200.

LV_DeleteCol(ColumnNumber): 删除指定的列和其中的所有内容. 成功时返回 1 而失败返回 0.当一个列被删除后, 在此列右边的任何列的编号减 1. 因此, 调用 LV_DeleteCol(2) 两次将删除第二列和第三列. 在比 Windows XP 老的操作系统中, 试图删除原始的首列可能会失败并返回 0.

从 ListView 中获取数据

LV_GetCount(["Selected | Column"]): 省略参数时, 函数返回控件中总行数. 当参数为 "S" 或 "Selected" 时, 计数仅包括选择的/高亮的行.当参数为 "Col" 或 "Column", 函数返回控件中的列数.此函数总是即时的因为控件跟踪这些计数.

此函数常用于一个循环的顶行, 此时将仅调用一次函数 (在首次循环前).例如:

Loop % LV_GetCount()
{
    LV_GetText(RetrievedText, A_Index)
    if InStr(RetrievedText, "some filter text")
        LV_Modify(A_Index, "Select")  ; Select each row whose first field contains the filter-text.
}

为了获取 ListView 的列宽 -- 用于例如保存它们到 INI 文件来在会话间保持一致 -- 请参照此例:

Gui +LastFound
Loop % LV_GetCount("Column")
{
    SendMessage, 4125, A_Index - 1, 0, SysListView321  ; 4125 is LVM_GETCOLUMNWIDTH.
    MsgBox Column %A_Index%'s width is %ErrorLevel%.
}

LV_GetNext([StartingRowNumber, "Checked | Focused"]): 返回下一个选择的, 选中的或焦点行的行号. 如果没有找到, 则返回零.如果 StartingRowNumber 省略或小于 1, 则从列表顶部开始搜索.否则, 从 StartingRowNumber 行后开始搜索.如果省略第二个参数, 则函数搜索下一个选择的/高亮的行.否则, 指定 "C" 或 "Checked" 来寻找下一个选中的行; 或指定 "F" 或 "Focused" 来寻找焦点行 (在整个列表中不可能有多个焦点行, 而有时可能没有).下面的示例报告 ListView 中所有选择的行:

RowNumber = 0  ; This causes the first loop iteration to start the search at the top of the list.
Loop
{
    RowNumber := LV_GetNext(RowNumber)  ; Resume the search at the row after that found by the previous iteration.
    if not RowNumber  ; The above returned zero, so there are no more selected rows.
        break
    LV_GetText(Text, RowNumber)
    MsgBox The next selected row is #%RowNumber%, whose first field is "%Text%".
}

判断一个特定的行是否被选中的另一种方法如下:

Gui +LastFound
SendMessage, 4140, RowNumber - 1, 0xF000, SysListView321  ; 4140 is LVM_GETITEMSTATE.  0xF000 is LVIS_STATEIMAGEMASK.
IsChecked := (ErrorLevel >> 12) - 1  ; This sets IsChecked to true if RowNumber is checked or false otherwise.

LV_GetText(OutputVar, RowNumber [, ColumnNumber]): 获取在指定 RowNumber 和 ColumnNumber 上的文本并保存到 OutputVar 中. 如果省略 ColumnNumber, 默认值为 1 (首列的文本).如果 RowNumber 为 0, 则获取列标题文本.如果文本长于 8191, 则仅获取开始的 8191 个字符.此函数成功时返回 1 而失败时返回 0.失败时 OutputVar 也被置空.

用户可能已经完成的拖放操作不会修改脚本看到的列编号.例如, 最初的首列仍是 number 1 即使用户已经把它拖到其他列的右边.

G-Label 通告 (主要)

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户在控件中执行一个动作时 MySubroutine 标签会自动运行.此子程序中可参考使用内置变量 A_Gui 和 A_GuiControl 来找出哪个窗口和 ListView 产生的事件. 更重要的是, 它可以参考 A_GuiEvent, 其包含下列字符串或字母的其中一个 (考虑到和未来版本的兼容性, 一个脚本不应假定这些字符串或字母是唯一可能的值):

DoubleClick: 用户双击了一行. 变量 A_EventInfo 包含目标行号.

R: 用户在控件内 双击了右键. 变量 A_EventInfo 包含了焦点行号.

ColClick: 用户点击了一个列标题. 变量 A_EventInfo 包含列编号, 这是当列创建时分配的原始编号; 即它不会反映任何用户对列完成的拖放操作. 列点击的一种可能的响应是通过一个包含排序友好格式 (例如一个 YYYYMMDD 整数日期) 数据的隐藏列 (零宽度) 进行排序. 这样的隐藏列可以境像其他列, 在那些列中使用更友好的格式显示相同的数据 (例如 MM/DD/YY). 例如, 一个脚本可以通过 LV_ModifyCol(3, 0) 隐藏 column 3, 接着通过 LV_ModifyCol(2, "NoSort") 关闭可见的 column 2 的自动排序. 然后响应 column 2 的 ColClick 通告, 脚本将使用隐藏的列通过 LV_ModifyCol(3, "Sort") 对 ListView 进行排序.

D: 用户尝试开始拖动行或图标 (目前还没有内置对拖动行或图标的支持). 变量 A_EventInfo 包含了焦点行号.在高于 1.0.44 的版本中, 即使不含 AltSubmit 选项此通告也会产生.

d (小写的 D): 和上面相同, 除了指右键拖动而不是左键拖动.

e (小写的 E): 用户完成编辑一行的首个字段 (只有当 ListView 选项中含有 -ReadOnly 时用户才可以编辑它). 变量 A_EventInfo 包含目标行号.

G-Label 通告(次要)

如果 ListView 的 选项 中含有单词 AltSubmit, 其 g-label 会运行的更频繁并且 A_GuiEvent 可能包含下列附加的值:

Normal: 用户左键单击了一行. 变量 A_EventInfo 包含了焦点行号.

RightClick: 用户右键单击了一行. 变量 A_EventInfo 包含了焦点行号.在大多数情况下, 最好不要显示一个菜单响应此通告. 而是使用 GuiContextMenu 标签 因为它还能识别 Appskey. 例如:

GuiContextMenu:  ; Launched in response to a right-click or press of the Apps key.
if A_GuiControl <> MyListView  ; This check is optional. It displays the menu only for clicks inside the ListView.
    return
; Show the menu at the provided coordinates, A_GuiX and A_GuiY.  These should be used
; because they provide correct coordinates even if the user pressed the Apps key:
Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
return

A: 激活了一行, 这种情况默认发生于双击一行时. 变量 A_EventInfo 包含目标行号.

C: ListView 释放了鼠标捕获.

E: 用户开始编辑一行的首个字段 (只有当 ListView 选项中含有 -ReadOnly 时用户才可以编辑它). 变量 A_EventInfo 包含目标行号.

F: ListView 接收到键盘焦点.

f (小写的 F): ListView 失去了键盘焦点.

I:项目变化了. 通过变成选择的/未选择的, 选中的/未选中的等让一行改变了. 如果用户选择了一个新行, 至少会接收到两个这样的通告: 一个是取消选择之前的行, 而另一个是选择了新行. 在高于 1.0.44 的版本中, 变量 A_EventInfo 包含新行行号. 在高于 1.0.46.10 的版本中, ErrorLevel 包含零或多个下列字母以指出项目发生的变化: S (选择了) 或 s (取消选择), 和/或 F (成为焦点) 或 f (失去焦点), 和/或 C (选中了) 或 c (取消选中). 例如, SF 表示此行被选择了并且成为焦点. 要检查一个特定的字母是否存在, 请使用 解析循环 或 InStr() 的区分大小写选项; 例如: InStr(ErrorLevel, "S", true). 注: 考虑到和未来版本的兼容性, 一个脚本不应假定 "SsFfCc" 包含了所有可能的字母或字母组合. 此外, 指定 Critical 作为 g-label 子程序的首行来确保接收到所有的 "I" 通告 (否则, 如果脚本无法跟上它们其中一些可能丢失).

K: 当 ListView 拥有焦点时用户按下了一个键. A_EventInfo 包含此键的虚拟按键代码, 它是介于 1 和 255 之间的一个数字. 如果此键是字母键, 在大多数键盘布局中可以通过 Chr(A_EventInfo) 把它转换成相应的字符. 不论 WantF2 如何都会接收到 F2 键击. +/-Lines. 然而, 不会接收到 Enter 键击; 要接收它, 像 下面 描述的那样使用一个默认按钮.

M: 选取框. 用户开始在一组行或图标周围拖动一个矩形选区.

S: 用户开始滚动 ListView.

s (小写的 S): 用户完成滚动 ListView.

ImageList (通过它把图标添加到 ListView 的方法)

一个图像列表是保存在内存中的一组大小相同的图标. 创建后每个 ImageList 是空的. 脚本重复调用 IL_Add() 来添加图标到列表中, 并且每个图标分配到一个序号, 序号从 1 开始. 脚本引用此号码在一行中或列标题中显示一个特定的图标. 这里是一个有效的例子, 演示了如何让图标显示在 ListView 的行中:

Gui, Add, ListView, h200 w180, Icon & Number|Description  ; Create a ListView.
ImageListID := IL_Create(10)  ; Create an ImageList to hold 10 small icons.
LV_SetImageList(ImageListID)  ; Assign the above ImageList to the current ListView.
Loop 10  ; Load the ImageList with a series of icons from the DLL.
    IL_Add(ImageListID, "shell32.dll", A_Index)  ; Omits the DLL's path so that it works on Windows 9x too.
Loop 10  ; Add rows to the ListView (for demonstration purposes, one for each icon).
    LV_Add("Icon" . A_Index, A_Index, "n/a")
LV_ModifyCol("Hdr")  ; Auto-adjust the column widths.
Gui Show
return

GuiClose:  ; Exit the script when the user closes the ListView's GUI window.
ExitApp

IL_Create([InitialCount, GrowCount, LargeIcons?]): 创建一个新的 ImageList, 初始为空, 并且返回 ImageList 的唯一 ID (失败时返回 0). InitialCount 为希望马上放入列表的图标数 (如果省略, 默认为 2). GrowCount 为列表每次将增长时超出当前列表容量的图标数 (如果省略, 默认为 5). LargeIcons 应该是一个数值: 如果不为零, ImageList 将包含大图标. 如果为零, 它将包含小图标 (这是省略时的默认情况). 添加到列表中的图标会按比例自动缩放以符合系统中大小图标的尺寸.

LV_SetImageList(ImageListID [, 0|1|2]): 此函数一般在添加行到 ListView 之前调用. 它设置 ImageList 的关联, 其中的图标将显示在 ListView 的行中 (同时可选的, 它的列). ImageListID 为前面调用 IL_Create() 返回的数字. 如果省略第二个参数, 则自动检测 ImageList 中的图标作为大图标或小图标. 否则, 对于大图标指定 0, 小图标指定 1, 而状态图标指定 2 (还不能直接支持状态图标, 但可以通过 SendMessage 使用).

一个 ListView 最多可以关联两个 ImageList: 小图标和/或大图标. 当脚本允许用户在大图标视图和其他视图之间切换时这很有用. 为了再关联一个 ImageList 到 ListView, 再次调用 LV_SetImageList(), 其中指定第二个列表的 ImageListID. 同时关联有大图标和小图标 ImageList 的 ListView 应该确保在两个列表中包含的图标顺序相同. 这是因为使用一个指定图标的大小版本时引用相同的 ID 编号.

尽管除了 Icon 和 Tile 显示小图标外对于其他的 视图模式 这是惯例, 但通过传递一个大图标列表到 LV_SetImageList 并且在第二个参数中指定 1 (小图标) 可以覆盖此行为. 这也增加了 ListView 中每行的高度以适合大图标.

如果成功, LV_SetImageList() 返回之前与 ListView 关联的 ImageListID (如果没有则为 0). 任何分离的 ImageList 一般应该通过 IL_Destroy(ImageListID) 销毁.

IL_Add(ImageListID, Filename [, IconNumber, ResizeNonIcon?]): 添加一个图标或图片到指定的 ImageListID 并且返回新图标的索引 (首个图标索引为 1, 第二个为 2, 依此类推). Filename 是一个图标 (.ICO), 光标 (.CUR), 或动画光标 (.ANI) 文件的名称 (动画光标显示在 ListView 中时实际将不会动). 图标的其他来源包括下列文件类型: EXE, DLL, CPL, SCR, 和包含图标资源的其他类型.要使用文件中的图标组而不是首个图标, 请在 IconNumber 中指定其编号.在后面的例子中, 将使用第二个图标组中的默认图标: IL_Add(ImageListID, "C:\My Application.exe", 2).

非图标图像例如 BMP, GIF 和 JPG 也可以加载. 但是, 此时应该指定最后两个参数以确保正确的行为: IconNumber 应该为屏蔽的/透明的颜色编码 (对于大多数图片 0xFFFFFF [白色] 也许是最好的); 而 ResizeNonIcon 应该为非零值来缩放图片为单个图标, 或者为零来分割图像为多个可以匹配实际宽度的图标.

在所有的操作系统中都支持 GIF, JPG, BMP, ICO, CUR, 和 ANI 图像.在 Windows XP 或更高版本的系统中, 还支持其他图像格式例如 PNG, TIF, Exif, WMF, 和 EMF.通过复制微软的免费 GDI+ DLL 到 AutoHotkey.exe 文件夹中可以让 XP 之前的操作系统提供支持 (但如果是 已编译脚本, 则需要复制 DLL 到脚本的文件夹).要下载此 DLL, 请在 www.microsoft.com 中搜索下列短语: gdi redistributable

IL_Destroy(ImageListID): 删除指定的 ImageList, 成功时返回 1 而失败返回 0. 通常没必要销毁 ImageList, 因为一旦附加到 ListView, 当 ListView 或其父窗口销毁时它们会被自动销毁. 但是, 如果一个 ListView 和其他的 ListView 共享 ImageList (通过在选项中包含 0x40), 在所有使用此 ImageList 的 ListView 销毁后脚本应该明确的销毁它. 同样, 如果脚本使用一个新的 ImageList 代替 ListView 中原来的, 它应该明确的销毁原来的.

ListView 备注

Gui Submit 命令对 ListView 控件没有效果. 因此, 脚本可以使用 ListView 的 关联变量 (如果有的话) 来保存其他数据而不用担心它会被覆盖.

在对一个列排序后 -- 通过用户点击其标题的方法或脚本调用 LV_ModifyCol(1, "Sort") -- 任何随后添加的行将出现在列表的底部而不会服从排序顺序. 例外情况是 Sort 和 SortDesc 样式, 它们会把新行移到正确的位置.

当 ListView 拥有焦点时如果要检测到用户按下的回车键, 请使用一个 默认按钮 (如果需要可以隐藏它). 例如:

Gui, Add, Button, Hidden Default, OK
...
ButtonOK:
GuiControlGet, FocusedControl, FocusV
if FocusedControl <> MyListView
    return
MsgBox % "Enter was pressed. The focused row number is " . LV_GetNext(0, "Focused")
return

为了用键盘在行与行之间导航, 用户还可以通过输入首列中一个项目名称的前几个字符来执行增量搜索. 这使得选择对象跳转到最近匹配的行.

尽管 ListView 中的每个字段可以存储任何长度的文本, 但仅显示开始的 260 个字符.

尽管 ListView 中可以使用的最大行数仅受系统可用内存的限制, 但参照 Count 选项中所描述的方法可以极大提高添加行的性能.

可以使用一个图片作为 ListView 周围的背景 (即作为 ListView 的框架). 要做到这点, 在 ListView 后创建 图片控件 并且在图片控件的 选项 中包含 0x4000000 (这是 WS_CLIPSIBLINGS).

一个脚本可以在每个窗口中创建多个 ListView. 要对非默认的 ListView 进行操作, 请参见 内置函数.

最好不要使用 SendMessage 直接插入或删除列. 这是因为程序为每列维护一个 排序参数 集, 这将使它们无法同步. 作为替代, 请使用 内置列函数.

要执行一些操作例如调整大小, 隐藏或改变 ListView 的字体, 请使用 GuiControl.

要从外部的 ListView (不属于脚本的那些) 提取文本, 请使用 "ControlGet List".

Windows 95 和 NT4: 如果系统缺少后面这些文件的 4.70 或更高版本: Comctl32.dll, Shell32.dll, and Shlwapi.dll -- 它们随各种更新和应用程序例如 Internet Explorer 3.0 或更高版本一起发布 -- ListView 的功能受到更多限制并且某些特性可能不会和预期一样.

相关

TreeView, 其他控件类型, Gui, GuiContextMenu, GuiControl, GuiControlGet, ListView 样式表

示例

; Select or de-select all rows by specifying 0 as the row number:
LV_Modify(0, "Select")   ; Select all.
LV_Modify(0, "-Select")  ; De-select all.
LV_Modify(0, "-Check")  ; Uncheck all the checkboxes.

; Auto-size all columns to fit their contents:
LV_ModifyCol()  ; There are no parameters in this mode.

?

; MAIN EXAMPLE
; The following is a working script that is more elaborate than the one near the top of this page.
; It displays the files in a folder chosen by the user, with each file assigned the icon associated with
; its type. The user can double-click a file, or right-click one or more files to display a context menu.

; Allow the user to maximize or drag-resize the window:
Gui +Resize

; Create some buttons:
Gui, Add, Button, Default gButtonLoadFolder, Load a folder
Gui, Add, Button, x+20 gButtonClear, Clear List
Gui, Add, Button, x+20, Switch View

; Create the ListView and its columns:
Gui, Add, ListView, xm r20 w700 vMyListView gMyListView, Name|In Folder|Size (KB)|Type
LV_ModifyCol(3, "Integer")  ; For sorting, indicate that the Size column is an integer.

; Create an ImageList so that the ListView can display some icons:
ImageListID1 := IL_Create(10)
ImageListID2 := IL_Create(10, 10, true)  ; A list of large icons to go with the small ones.

; Attach the ImageLists to the ListView so that it can later display the icons:
LV_SetImageList(ImageListID1)
LV_SetImageList(ImageListID2)

; Create a popup menu to be used as the context menu:
Menu, MyContextMenu, Add, Open, ContextOpenFile
Menu, MyContextMenu, Add, Properties, ContextProperties
Menu, MyContextMenu, Add, Clear from ListView, ContextClearRows
Menu, MyContextMenu, Default, Open  ; Make "Open" a bold font to indicate that double-click does the same thing.

; Display the window and return. The OS will notify the script whenever the user
; performs an eligible action:
Gui, Show
return

ButtonLoadFolder:
Gui +OwnDialogs  ; Forces user to dismiss the following dialog before using main window.
FileSelectFolder, Folder,, 3, Select a folder to read:
if not Folder  ; The user canceled the dialog.
    return

; Check if the last character of the folder name is a backslash, which happens for root
; directories such as C:\. If it is, remove it to prevent a double-backslash later on.
StringRight, LastChar, Folder, 1
if LastChar = \
    StringTrimRight, Folder, Folder, 1  ; Remove the trailing backslash.

; Ensure the variable has enough capacity to hold the longest file path. This is done
; because ExtractAssociatedIconA() needs to be able to store a new filename in it.
VarSetCapacity(Filename, 260)
sfi_size = 352
VarSetCapacity(sfi, sfi_size)

; Gather a list of file names from the selected folder and append them to the ListView:
GuiControl, -Redraw, MyListView  ; Improve performance by disabling redrawing during load.
Loop %Folder%\*.*
{
    FileName := A_LoopFileFullPath  ; Must save it to a writable variable for use below.

    ; Build a unique extension ID to avoid characters that are illegal in variable names,
    ; such as dashes.  This unique ID method also performs better because finding an item
    ; in the array does not require search-loop.
    SplitPath, FileName,,, FileExt  ; Get the file's extension.
    if FileExt in EXE,ICO,ANI,CUR
    {
        ExtID := FileExt  ; Special ID as a placeholder.
        IconNumber = 0  ; Flag it as not found so that these types can each have a unique icon.
    }
    else  ; Some other extension/file-type, so calculate its unique ID.
    {
        ExtID = 0  ; Initialize to handle extensions that are shorter than others.
        Loop 7     ; Limit the extension to 7 characters so that it fits in a 64-bit value.
        {
            StringMid, ExtChar, FileExt, A_Index, 1
            if not ExtChar  ; No more characters.
                break
            ; Derive a Unique ID by assigning a different bit position to each character:
            ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1)))
        }
        ; Check if this file extension already has an icon in the ImageLists. If it does,
        ; several calls can be avoided and loading performance is greatly improved,
        ; especially for a folder containing hundreds of files:
        IconNumber := IconArray%ExtID%
    }
    if not IconNumber  ; There is not yet any icon for this extension, so load it.
    {
        ; Get the high-quality small-icon associated with this file extension:
        if not DllCall("Shell32\SHGetFileInfoA", "str", FileName, "uint", 0, "str", sfi, "uint", sfi_size, "uint", 0x101)  ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON
            IconNumber = 9999999  ; Set it out of bounds to display a blank icon.
        else ; Icon successfully loaded.
        {
            ; Extract the hIcon member from the structure:
            hIcon = 0
            Loop 4
                hIcon += *(&sfi + A_Index-1) << 8*(A_Index-1)
            ; Add the HICON directly to the small-icon and large-icon lists.
            ; Below uses +1 to convert the returned index from zero-based to one-based:
            IconNumber := DllCall("ImageList_ReplaceIcon", "uint", ImageListID1, "int", -1, "uint", hIcon) + 1
            DllCall("ImageList_ReplaceIcon", "uint", ImageListID2, "int", -1, "uint", hIcon)
            ; Now that it's been copied into the ImageLists, the original should be destroyed:
            DllCall("DestroyIcon", "uint", hIcon)
            ; Cache the icon to save memory and improve loading performance:
            IconArray%ExtID% := IconNumber
        }
    }

    ; Create the new row in the ListView and assign it the icon number determined above:
    LV_Add("Icon" . IconNumber, A_LoopFileName, A_LoopFileDir, A_LoopFileSizeKB, FileExt)
}
GuiControl, +Redraw, MyListView  ; Re-enable redrawing (it was disabled above).
LV_ModifyCol()  ; Auto-size each column to fit its contents.
LV_ModifyCol(3, 60) ; Make the Size column at little wider to reveal its header.
return

ButtonClear:
LV_Delete()  ; Clear the ListView, but keep icon cache intact for simplicity.
return

ButtonSwitchView:
if not IconView
    GuiControl, +Icon, MyListView    ; Switch to icon view.
else
    GuiControl, +Report, MyListView  ; Switch back to details view.
IconView := not IconView             ; Invert in preparation for next time.
return

MyListView:
if A_GuiEvent = DoubleClick  ; There are many other possible values the script can check.
{
    LV_GetText(FileName, A_EventInfo, 1) ; Get the text of the first field.
    LV_GetText(FileDir, A_EventInfo, 2)  ; Get the text of the second field.
    Run %FileDir%\%FileName%,, UseErrorLevel
    if ErrorLevel
        MsgBox Could not open "%FileDir%\%FileName%".
}
return

GuiContextMenu:  ; Launched in response to a right-click or press of the Apps key.
if A_GuiControl <> MyListView  ; Display the menu only for clicks inside the ListView.
    return
; Show the menu at the provided coordinates, A_GuiX and A_GuiY.  These should be used
; because they provide correct coordinates even if the user pressed the Apps key:
Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
return

ContextOpenFile:  ; The user selected "Open" in the context menu.
ContextProperties:  ; The user selected "Properties" in the context menu.
; For simplicitly, operate upon only the focused row rather than all selected rows:
FocusedRowNumber := LV_GetNext(0, "F")  ; Find the focused row.
if not FocusedRowNumber  ; No row is focused.
    return
LV_GetText(FileName, FocusedRowNumber, 1) ; Get the text of the first field.
LV_GetText(FileDir, FocusedRowNumber, 2)  ; Get the text of the second field.
IfInString A_ThisMenuItem, Open  ; User selected "Open" from the context menu.
    Run %FileDir%\%FileName%,, UseErrorLevel
else  ; User selected "Properties" from the context menu.
    Run Properties "%FileDir%\%FileName%",, UseErrorLevel
if ErrorLevel
    MsgBox Could not perform requested action on "%FileDir%\%FileName%".
return

ContextClearRows:  ; The user selected "Clear" in the context menu.
RowNumber = 0  ; This causes the first iteration to start the search at the top.
Loop
{
    ; Since deleting a row reduces the RowNumber of all other rows beneath it,
    ; subtract 1 so that the search includes the same row number that was previously
    ; found (in case adjacent rows are selected):
    RowNumber := LV_GetNext(RowNumber - 1)
    if not RowNumber  ; The above returned zero, so there are no more selected rows.
        break
    LV_Delete(RowNumber)  ; Clear the row from the ListView.
}
return

GuiSize:  ; Expand or shrink the ListView in response to the user's resizing of the window.
if A_EventInfo = 1  ; The window has been minimized.  No action needed.
    return
; Otherwise, the window has been resized or maximized. Resize the ListView to match.
GuiControl, Move, MyListView, % "W" . (A_GuiWidth - 20) . " H" . (A_GuiHeight - 40)
return

GuiClose:  ; When the window is closed, exit the script automatically:
ExitApp


TreeView (GUI)

TreeView [v1.0.44+]

目录

  • 入门和简单示例
  • 选项和样式
  • 内置函数: 1) 添加/修改/删除项目; 2) 从 TreeView 中获取数据
  • G-Label 通告
  • 备注
  • 更长的范例

入门和简单示例

Tree-View 通过在父项目下缩进它们的子项目来显示出项目的层级关系. 最常见的例子是资源管理器的驱动器和文件夹树.

创建 TreeView 的语法为:

Gui, Add, TreeView, Options

这里是一个创建和显示一个简单项目层次结构的有效脚本:

Gui, Add, TreeView
P1 := TV_Add("First parent")
P1C1 := TV_Add("Parent 1's first child", P1)  ; Specify P1 to be this item's parent.
P2 := TV_Add("Second parent")
P2C1 := TV_Add("Parent 2's first child", P2)
P2C2 := TV_Add("Parent 2's second child", P2)
P2C2C1 := TV_Add("Child 2's first child", P2C2)

Gui, Show  ; Show the window and its TreeView.
return

GuiClose:  ; Exit the script when the user closes the TreeView's GUI window.
ExitApp

用于 "Gui, Add, TreeView, Options" 的样式和选项

AltSubmit: 通知脚本有比正常更多的 TreeView 事件类型. 换言之, g-label 运行的更频繁.参见 TreeView 通告 获取详情.

Background: 指定单词 Background 接着一个颜色名称 (参见 颜色图表) 或 RGB 值 (0x 前缀是可选的).例如: BackgroundSilver, BackgroundFFDD99. 如果此选项不存在, TreeView 最初默认的背景颜色由 Gui Color (或者如果没有, 则使用系统默认的背景颜色) 的最后一个参数设置. 指定 BackgroundDefault 应用系统的默认背景颜色 (通常为白色).例如, 通过 GuiControl, +BackgroundDefault, MyTreeView 可以把 TreeView 恢复为默认的颜色.

Buttons: 指定 -Buttons (负 Buttons) 以避免在每个含有子项目的项目左边显示一个加号或减号按钮.

C: 文本颜色. 指定字母 C 接着一个颜色名称 (参见 颜色图表) 或 RGB 值 (0x 前缀是可选的).例如: cRed, cFF2211, c0xFF2211, cDefault

Checked: 在每项的左边提供一个复选框. 当 添加 一项时, 在其选项中指定单词 Check 使复选框初始为选中而不是未选中状态. 用户可以点击复选框或按下空格键来选中或取消选中一项. 要找出 TreeView 中当前选中了哪些项目, 请调用 TV_GetNext() 或 TV_Get().

HScroll: 指定 -HScroll (负 HScroll) 来禁用控件中的水平滚动 (此外, 控件将不显示水平滚动条). 在比 Windows 2000/Me 老的操作系统中, 此选项没有效果除非系统中有 Comctl32.dll 5.8 或更高版本 (随应用程序例如 Internet Explorer 5 或更高版本一起发布).

ImageList: 这是通过它把图标添加到 TreeView 的方法. 指定单词 ImageList 接着之前调用 IL_Create() 返回的 ImageListID. 此选项仅当创建 TreeView 时才有效果. 这里是一个有效的示例:

ImageListID := IL_Create(10)  ; Create an ImageList with initial capacity for 10 icons.
Loop 10  ; Load the ImageList with some standard system icons.
    IL_Add(ImageListID, "shell32.dll", A_Index)  ; Omits the DLL's path so that it works on Windows 9x too.
Gui, Add, TreeView, ImageList%ImageListID%
TV_Add("Name of Item", 0, "Icon4")  ; Add an item to the TreeView and give it a folder icon.
Gui Show

Lines: 指定 -Lines (负 Lines) 来避免显示连接父项目和它们的子项目的网状线. 但是, 移除这些线也阻止了顶级项目左边加号/减号按钮的显示.

ReadOnly: 指定 -ReadOnly (负 ReadOnly) 来允许编辑每项的文本/名称. 要编辑某项, 选择它接着按下 F2 键. 或者, 你可以对一个项目点击一次来选择它, 至少等待半秒钟, 然后再次点击同一项目进行编辑. 编辑后, 一个项目可以在其同级项目之间按字母顺序重新定位, 请参考下面的例子:

Gui, Add, TreeView, -ReadOnly gMyTree
; ...
MyTree:
if (A_GuiEvent == "e")  ; The user has finished editing an item (use == for case sensitive comparison).
    TV_Modify(TV_GetParent(A_EventInfo), "Sort")  ; This works even if the item has no parent.
return

R: 行高 (创建时).指定字母 R 接着为在控件中留出空间的行数. 例如, R10 将使控件为 10 个项目的高度.

WantF2: 指定 -WantF2 (负 WantF2) 来禁止使用 F2 键击 编辑 当前选择的项目. 仅当 -ReadOnly 也有效时此设置才不会被忽略.不论此设置如何, g-label 仍会接收到 F2 通告.

(未命名的数字样式): 由于上述以外的其他样式很少使用, 它们没有名称.参见 TreeView 样式表 了解这些样式.

TreeViews 中的内置函数

所有的 TreeView 函数操作于当前线程的 默认 GUI 窗口 (这可以通过 Gui, 2:Default 改变). 如果默认窗口不存在或不含有 TreeView 控件, 所有函数返回 0 来表明此问题.

如果窗口含有多个 TreeView 控件, 默认情况下函数操作于最近添加的那个. 要改变这种情况, 请指定 Gui, TreeView, TreeViewName, 此处 TreeViewName 为 TreeView 的 关联变量 的名称或 Window Spy 中显示的其 ClassNN. 一旦改变后, 所有现有和将来的 线程 将使用指定的 TreeView.

添加, 修改, 和删除项目

TV_Add(Name, [ParentItemID, Options]): 添加一个新项到 TreeView 并且返回其唯一的 项目 ID 号 (当失败时返回 0). Name 为被显示的项目文本, 其可以为文本或数字 (包括数值的 表达式 结果). ParentItemID 为新项目的父项的 ID 号 (忽略它或指定 0 来添加项目到顶级). 当添加大量项目时, 在添加项目前使用 GuiControl, -Redraw, MyTreeView 并且在添加项目后使用 GuiControl, +Redraw, MyTreeView 可以提升性能.

TV_Add() 和 TV_Modify() 的选项: 选项 参数是一个包含零个或多个下面列表中单词的字符串 (不区分大小写). 单词间使用空格或制表符分隔.要移除一个选项, 请在选项前加上一个负号.要添加一个选项, 可以在选项前加上一个正号但不是必需的.

Bold: 用粗体显示项目的名称. 要在以后取消项目名称的粗体显示, 请使用 TV_Modify(ItemID, "-Bold").

Check: 在项目的左边显示一个复选标记 (需要 TreeView 含有 复选框). 要在以后取消复选它, 请使用 TV_Modify(ItemID, "-Check"). 在单词 Check 后可选跟着一个 0 或 1 来表示初始状态. 换言之, "Check" 和 "Check" . VarContainingOne 是相同的 (这里中间使用的是 连接运算符).

Expand: 展开此项目来显示其子项目 (如果有的话). 以后要折叠项目, 请使用 TV_Modify(ItemID, "-Expand"). 如果没有子项目, TV_Modify() 返回 0 而不是项目 ID. 相比之下, TV_Add() 标记此项目为展开的以防以后要添加子项目. 与 "Select" (下面的) 不同, 展开一个项目不会自动展开其父项目. 最后, 在单词 Expand 后可选跟着一个 0 或 1 来表示初始状态. 换言之, "Expand" 和 "Expand" . VarContainingOne 是相同的.

First | Sort | N: 这些选项仅适用于 TV_Add(). 它们指定新项目相对于其同级项目的位置 (此处 同级项目 是同一级别的其他任何项目). 如果这些选项都不存在, 新项目被添加到同级项目的最后一个/底部. 否则, 指定 First 添加项目到同级项目的第一个/顶部, 或指定 Sort 按字母顺序插入新项目到同级项目中间. 如果指定一个普通的整数 (N), 则假定为同级项目的 ID 号, 新项目在其后插入 (如果整数 N 是唯一存在的选项, 它不需要包含在引号中).

Icon: 指定单词 Icon 接着此项目图标的编号, 项目图标显示在项目名称的左边. 如果此选项不存在, 则使用 ImageList 中的首个图标.要显示一个空白图标, 指定一个大于 ImageList 中图标编号的数字.如果控件没有 ImageList, 则既不显示图标也不为图标保留空间.

Select: 选择项目. 因为一次只能选择一个项目, 此时任何原来选择的项目会自动取消选择. 此外, 如果有必要此选项会展开其父项目以显示新选择的项目. 要找出当前的选择, 请调用 TV_GetSelection().

Sort: 对于 TV_Modify(), 此选项按字母顺序排列指定项目的子项目. 要排序所有顶级项目, 请使用 TV_Modify(0, "Sort"). 如果不含子项目, 返回 0 而不是所修改的项目 ID.

Vis: 通过滚动 TreeView 和/或展开其父项目 (如果必要) 确保此项完全可见.

VisFirst: 和上面一样, 除了滚动 TreeView 使得此项显示在最上面, 如果可能的话. 此选项与 TV_Modify() 一起使用比与 TV_Add() 通常更有效.

TV_Modify(ItemID [, Options, NewName]): 修改一个项目的属性和/或名称. 成功时它返回项目自己的 ID 而失败 (或部分失败) 时返回 0. 如果仅存在首个参数, 则 选择 指定的项目. 如果省略 NewName, 则当前名称保持不变. 了解 选项, 参见上面的列表.

TV_Delete([ItemID]): 如果省略 ItemID, 则删除 TreeView 中 所有 项目. 否则, 仅删除指定 ItemID 所在的项目. 成功时返回 1 而失败返回 0.

从 TreeView 中获取数据

TV_GetSelection(): 返回选择项目的 ID 号.

TV_GetCount(): 返回控件中项目的总数. 此函数总是即时的因为控件跟踪此计数.

TV_GetParent(ItemID): 返回指定项目的父项目的 ID. 顶级项目没有父项目因此返回 0.

TV_GetChild(ParentItemID): 返回指定项目的第一个/最上面的 子项目的 ID 号 (如果没有则为 0).

TV_GetPrev(ItemID): 返回指定项目上面一个的同级项目的 ID 号 (如果没有则为 0).

TV_GetNext([ItemID, "Checked | Full"]): 此函数含有以下模式:

  1. 省略所有参数时, 它返回 TreeView 中第一个/最上面的项目的 ID 号 (如果没有则为 0).
  2. 如果仅存在首个参数 (ItemID), 它返回指定项目下面一个的同级项目的 ID 号 (如果没有则为 0). 如果首个参数为 0, 它返回 TreeView 中第一个/最上面的项目的 ID 号 (如果没有则为 0).
  3. 当第二个参数为 "Full" 或 "F", 则获取下一个项目, 不论是否是指定项目的同级项目. 这使得脚本可以容易的逐项遍历整个树. 例如:
    ItemID = 0  ; Causes the loop's first iteration to start the search at the top of the tree.
Loop
{
    ItemID := TV_GetNext(ItemID, "Full")  ; Replace "Full" with "Checked" to find all checkmarked items.
    if not ItemID  ; No more items in tree.
break
    TV_GetText(ItemText, ItemID)
    MsgBox The next Item is %ItemID%, whose text is "%ItemText%".
}
  4. 当第二个参数为 "Check", "Checked", 或 "C", 与上面行为相同, 除了跳过任何没有复选标记的项目. 这使得可以逐个获取 TreeView 中所有含有复选标记的项目.

TV_GetText(OutputVar, ItemID): 获取指定 ItemID 的文本/名称并保存到 OutputVar 中. 如果文本长于 8191, 则仅获取开始的 8191 个字符.成功时函数返回项目自己的 ID. 失败时返回 0 (并且 OutputVar 也被置空).

TV_Get(ItemID, "Expand | Check | Bold"): 如果指定的项目含有指定的属性, 则返回其自己的 ItemID. 否则返回 0. 在第二个参数中指定 "E", "Expand", 或 "Expanded" 以判断此项当前是 展开的 (即其子项目是显示的); 指定 "C", "Check", 或 "Checked" 以判断此项含有 复选标记; 或指定 "B" 或 "Bold" 以判断此项当前为 粗体 显示.

提示: 因为在 IF声明 中把任何非零值视为 "真", 下面两行功能相同:

  1. if TV_Get(ItemID, "Checked") = ItemID
  2. if TV_Get(ItemID, "Checked")

G-Label 通告 (主要)

一个 g-label 例如 gMySubroutine 可以使用在此控件选项中. 这使得当用户在控件中执行一个动作时 MySubroutine 标签会自动运行. 此子程序中可参考使用内置变量 A_Gui 和 A_GuiControl 来找出哪个窗口和 TreeView 产生的事件. 更重要的是, 它可以参考 A_GuiEvent, 其包含下列字符串或字母的其中一个 (考虑到和未来版本的兼容性, 一个脚本不应假定这些字符串或字母是唯一可能的值):

DoubleClick: 用户双击了一项. 变量 A_EventInfo 包含目标项目 ID.

D: 用户尝试开始拖动一个项目 (目前还没有内置对拖动项目的支持). 变量 A_EventInfo 包含目标项目 ID.

d (小写的 D): 和上面相同, 除了指右键拖动而不是左键拖动.

e (小写的 E): 用户完成编辑一个项目 (只有当 TreeView 选项中含有 -ReadOnly 时用户才可以编辑项目). 变量 A_EventInfo 包含目标项目 ID.

S: 选择了一个新项目, 由用户或脚本自己选择的. 变量 A_EventInfo 包含新选择项目的 ID.

G-Label 通告 (次要)

如果 TreeView 的 选项 中含有单词 AltSubmit, 其 g-label 会运行的更频繁并且 A_GuiEvent 可能包含下列附加的值:

Normal: 用户左键单击了一个项目.变量 A_EventInfo 包含目标项目 ID.

RightClick: 用户右键单击了一个项目. 变量 A_EventInfo 包含了目标项目 ID. 在大多数情况下, 最好不要显示一个菜单响应此通告. 而是使用 GuiContextMenu 标签 因为它还能识别 Appskey.例如:

GuiContextMenu:  ; Launched in response to a right-click or press of the Apps key.
if A_GuiControl <> MyTreeView  ; This check is optional. It displays the menu only for clicks inside the TreeView.
    return
; Show the menu at the provided coordinates, A_GuiX and A_GuiY.  These should be used
; because they provide correct coordinates even if the user pressed the Apps key:
Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
return

E: 用户开始编辑一个项目 (只有当 TreeView 选项中含有 -ReadOnly 时用户才可以编辑项目). 变量 A_EventInfo 包含目标项目 ID.

F: TreeView 接收到键盘焦点.

f (小写的 F): TreeView 失去了键盘焦点.

K: 当 TreeView 拥有焦点时用户按下了一个键. A_EventInfo 包含此键的虚拟按键代码, 它是介于 1 和 255 之间的一个数字.如果此键是字母键, 在大多数键盘布局中可以通过 Chr(A_EventInfo) 把它转换成相应的字符.不论 WantF2 如何都会接收到 F2 键击. 然而, 不会接收到 Enter 键击; 要接收它, 像 下面 描述的那样使用一个默认按钮.

+ (加号): 展开了一个项目以显示其子项目. 变量 A_EventInfo 包含目标项目 ID.

- (减号): 折叠了一个项目以隐藏其子项目. 变量 A_EventInfo 包含目标项目 ID.

备注

Gui Submit 命令对 TreeView 控件没有效果. 因此, 脚本可以使用 TreeView 的 关联变量 (如果有的话) 来保存其他数据而不用担心它会被覆盖.

当 TreeView 拥有焦点时如果要检测到用户按下的回车键, 请使用一个 默认按钮 (如果需要可以隐藏它). 例如:

Gui, Add, Button, Hidden Default, OK
...
ButtonOK:
GuiControlGet, FocusedControl, FocusV
if FocusedControl <> MyTreeView
    return
MsgBox % "Enter was pressed. The selected item ID is " . TV_GetSelection()
return

为了用键盘在项与项之间导航, 用户还可以通过输入一个项目名称的前几个字符来执行增量搜索. 这使得选择对象跳转到最近匹配的项目.

尽管 TreeView 中的每个项目可以存储任何长度的文本, 但仅显示开始的 260 个字符.

尽管理论上 TreeView 中可以使用最大的项目数为 65536, 接近此数目时添加项的性能将显著降低. 通过使用 TV_Add() 中描述的重绘提示可以稍微减轻这种情况.

与 ListViews 不同, 当 TreeView 销毁时其 ImageList 不会被自动销毁. 因此, 如果 TreeView 中使用的 ImageList 以后不再用于其他地方, 在销毁 TreeView 所在的窗口后脚本应该调用 IL_Destroy(ImageListID) 销毁此 ImageList. 然而, 如果脚本很快将退出这样做是没必要的因为那时所有的 ImageList 会被自动销毁. 相关提示, TreeView 最初的 ImageList 可以被替换为一个新的, 参照此例:

Gui +LastFound
SendMessage, 0x1109, 0, NewImageListID, SysTreeView321  ; 0x1109 is TVM_SETIMAGELIST
if ErrorLevel  ; The TreeView had a previous ImageList.
    IL_Destroy(ErrorLevel)  ; Destroying it is the most typical action.

一个脚本可以在每个窗口中创建多个 TreeView. 要对非默认的 TreeView 进行操作, 请参见 内置函数.

要执行一些操作例如调整大小, 隐藏或改变 TreeView 的字体, 请使用 GuiControl.

Tree View eXtension (TVX) 扩展了 TreeViews 的功能增加支持移动, 插入和删除. 演示的例子参见 www.autohotkey.com/forum/topic19021.html

Windows 95 和 NT4: 如果系统缺少后面这些文件的 4.70 或更高版本: Comctl32.dll, Shell32.dll, and Shlwapi.dll -- 它们随各种更新和应用程序例如 Internet Explorer 3.0 或更高版本一起发布 -- TreeView 的功能受到更多限制并且某些特性可能不会和预期一样.

相关

ListView, 其他控件类型, Gui, GuiContextMenu, GuiControl, GuiControlGet, TreeView 样式表

示例

; The following is a working script that is more elaborate than the one near the top of this page.
; It creates and displays a TreeView containing all folders in the all-users Start Menu.  When the
; user selects a folder, its contents are shown in a ListView to the right (like Windows Explorer).
; In addition, a StatusBar control shows information about the currently selected folder.

; The following folder will be the root folder for the TreeView. Note that loading might take a long
; time if an entire drive such as C:\ is specified:
TreeRoot = %A_StartMenuCommon%
TreeViewWidth := 280
ListViewWidth := A_ScreenWidth - TreeViewWidth - 30

; Allow the user to maximize or drag-resize the window:
Gui +Resize

; Create an ImageList and put some standard system icons into it:
ImageListID := IL_Create(5)
Loop 5  ; Below omits the DLL's path so that it works on Windows 9x too:
    IL_Add(ImageListID, "shell32.dll", A_Index)

; Create a TreeView and a ListView side-by-side to behave like Windows Explorer:
Gui, Add, TreeView, vMyTree r20 w%TreeViewWidth% gMyTree ImageList%ImageListID%
Gui, Add, ListView, vMyList r20 w%ListViewWidth% x+10, Name|Modified

; Set the ListView's column widths (this is optional):
Col2Width = 70  ; Narrow to reveal only the YYYYMMDD part.
LV_ModifyCol(1, ListViewWidth - Col2Width - 30)  ; Allows room for vertical scrollbar.
LV_ModifyCol(2, Col2Width)

; Create a Status Bar to give info about the number of files and their total size:
Gui, Add, StatusBar
SB_SetParts(60, 85)  ; Create three parts in the bar (the third part fills all the remaining width).

; Add folders and their subfolders to the tree. Display the status in case loading takes a long time:
SplashTextOn, 200, 25, TreeView and StatusBar Example, Loading the tree...
AddSubFoldersToTree(TreeRoot)
SplashTextOff

; Display the window and return. The OS will notify the script whenever the user performs an eligible action:
Gui, Show,, %TreeRoot%  ; Display the source directory (TreeRoot) in the title bar.
return

AddSubFoldersToTree(Folder, ParentItemID = 0)
{
    ; This function adds to the TreeView all subfolders in the specified folder.
    ; It also calls itself recursively to gather nested folders to any depth.
    Loop %Folder%\*.*, 2  ; Retrieve all of Folder's sub-folders.
        AddSubFoldersToTree(A_LoopFileFullPath, TV_Add(A_LoopFileName, ParentItemID, "Icon4"))
}

MyTree:  ; This subroutine handles user actions (such as clicking).
if A_GuiEvent <> S  ; i.e. an event other than "select new tree item".
    return  ; Do nothing.
; Otherwise, populate the ListView with the contents of the selected folder.
; First determine the full path of the selected folder:
TV_GetText(SelectedItemText, A_EventInfo)
ParentID := A_EventInfo
Loop  ; Build the full path to the selected folder.
{
    ParentID := TV_GetParent(ParentID)
    if not ParentID  ; No more ancestors.
        return
    TV_GetText(ParentText, ParentID)
    SelectedItemText = %ParentText%\%SelectedItemText%
}
SelectedFullPath = %TreeRoot%\%SelectedItemText%

; Put the files into the ListView:
LV_Delete()  ; Clear all rows.
GuiControl, -Redraw, MyListView  ; Improve performance by disabling redrawing during load.
FileCount = 0  ; Init prior to loop below.
TotalSize = 0
Loop %SelectedFullPath%\*.*  ; For simplicity, this omits folders so that only files are shown in the ListView.
{
    LV_Add("", A_LoopFileName, A_LoopFileTimeModified)
    FileCount += 1
    TotalSize += A_LoopFileSize
}
GuiControl, +Redraw, MyListView

; Update the three parts of the status bar to show info about the currently selected folder:
SB_SetText(FileCount . " files", 1)
SB_SetText(Round(TotalSize / 1024, 1) . " KB", 2)
SB_SetText(SelectedFullPath, 3)
return

GuiSize:  ; Expand/shrink the ListView and TreeView in response to user's resizing of window.
if A_EventInfo = 1  ; The window has been minimized.  No action needed.
    return
; Otherwise, the window has been resized or maximized. Resize the controls to match.
GuiControl, Move, MyTree, % "H" . (A_GuiHeight - 30)  ; -30 for StatusBar and margins.
GuiControl, Move, MyList, % "H" . (A_GuiHeight - 30) . " W" . (A_GuiWidth - TreeViewWidth - 30)
return

GuiClose:  ; Exit the script when the user closes the TreeView's GUI window.
ExitApp


IfMsgBox

检查用户在最近的 MsgBox 命令中点击了哪个按钮.

IfMsgBox, ButtonName

参数

ButtonName

下列字符串之一表示用户在最近的 MsgBox 命令中所点击的按钮:

Yes
No
OK
Cancel
Abort
Ignore
Retry
Continue [v1.0.44.08+]
TryAgain [v1.0.44.08+]
Timeout (即单词 "timeout" 表示 MsgBox 命令 超时)

相关

MsgBox

示例

MsgBox, 4, , Would you like to continue?, 5  ; 5 秒的超时时间.
IfMsgBox, No
    Return  ; 用户点击了 "No" 按钮.
IfMsgBox, Timeout
    Return ; 即在超时时假设点击了 "No".
; 否则, 继续:
...


InputBox

显示一个输入框让用户输入字符串.

InputBox, OutputVar [, Title, Prompt, HIDE, Width, Height, X, Y, Font, Timeout, Default]

参数

OutputVar | 用来保存用户输入文本的变量.
Title | 输入框的标题.如果为空或忽略,默认为脚本的名称.
Prompt | 输入框的文本,通常是用于提示用户期望输入输入的数据类型的信息.如果 提示 较长, 可以使用 continuation section/字串分段 的方法将它分成较短的几行，这样可以增加可读性和可维护性.
HIDE | 如果这个参数是单词 HIDE, 用户的输入将被屏蔽, 对于密码这是有用的.
Width | 如果此参数为空或省略，窗口的初始宽度将是375。该参数可以是一个 表达式.
Height | 如果此参数为空或省略，窗口的初始高度将是189。这个参数可以是一个表达式 。
X-Y | 窗口的 X 和 Y 坐标 (使用 0,0 可以将其移动到桌面的左上角), 可以使用 expressions/表达式. 如果其中一个或两个一起留空或省略, 在那个方向上对话框将居中显示. 其中一个或两个坐标可以为负数,这样可以将窗口部分或完全移出桌面.
Font | 还没有实现 (留空). 将来可能接受像 verdana:8 这样的字串.
Timeout | 以秒为单位的超时时间 (可以包含小数点或者是一个 表达式).? 如果它的值超过 2147483 (24.8 天), 它将会被设置为 2147483. 超过超时时间以后, 输入框窗口将自动关闭同时 ErrorLevel 被设置为 2. OutputVar 仍将保存用户输入的内容.
Default | 对话框首次出现时显示在输入框中的字串. 用户可以使用退格或其他方法修改这个字串.

ErrorLevel

请参阅以下信息。

备注

该对话框允许用户输入文本，然后按 OK/确定 或 CANCEL/取消. 用户可以通过拖动其边界调整对话框的大小.

如果用户按下 CANCEL/取消 按钮: 对于 AutoIt v2 (.aut) 脚本, OutputVar 将被设置为空并且 ErrorLevel 的值不会被改变. 对于所有其他类型的脚本 (例如 .ahk, .ini) ErrorLevel 的值被设置为1 (按 OK/确定 时设置为0) 同时 OutputVar 用来保存用户输入的内容. 这使得 CANCEL/取消 按钮可以用来执行一个其他的功能而不是脚本设计者期望的取消功能.

如果对话超时,对于所有类型的脚本 ERRORLEVEL的 的值将被设置为2, 包括的AutoIt v2的脚本.因此, 在使用这个命令超时之前 AutoIt v2 脚本中应该明确的设置 ErrorLevel 的值为 0 .

通过 Gui +OwnDialogs 的方法, 一个 GUI 窗口可以显示模式输入框.模式输入框可以避免用户在消息框消失之前对原来的 GUI/图形界面 窗口进行操作.

相关

GUI, Input, MsgBox, FileSelectFile, FileSelectFolder, SplashTextOn, ToolTip

示例

InputBox, password, Enter Password, (your input will be hidden), hide
InputBox, UserInput, Phone Number, Please enter a phone number., , 640, 480
if ErrorLevel
    MsgBox, CANCEL was pressed.
else
    MsgBox, You entered "%UserInput%"


MsgBox

在含有一个或多个按钮 (例如 "是" 和 "否") 的小窗口中显示指定的文本 .

MsgBox, Text
MsgBox [, Options, Title, Text, Timeout]

参数

Text | 如果省略所有的参数, MsgBox 将显示 "Press OK to continue." 文本. 否则, 此参数表示显示在消息框中的文本, 用来引导用户如何操作或提示信息. 可以使用 转义序列 来显示特殊字符. 例如, `n 表示换行符, 它结束当前行并开始一个新行. 因此使用 text1`n`ntext2 会在 text1 和 text2 之间添加一个空行. 如果 Text 较长, 可以通过 延续片段 的方法将其分解成较短的几行, 这样可以增加可读性和可维护性.
Options | 表示消息框的类型和合适的按钮组合. 如果为空或省略, 则默认为 0. 请参阅下表来了解允许的值. 如果此参数包含表达式或像 %option% 这样的变量引用, 那么将无法被识别. 而应该使用文字的纯数值.
Title | 消息框窗口的标题. 如果省略或为空, 那么它默认为脚本的名称 (不含路径).
Timeout | (可选的) 以秒为单位表示的超时时间 (可以为小数但不能使用表达式). 如果它的值超过 2147483 (24.8 天), 那么它将被设置为 2147483. 经过了这个超时时间后消息框将自动关闭且 IfMsgBox 命令将看到表示超时状态的值 TIMEOUT. 已知限制: 如果 MsgBox 仅含有一个 "确定" 按钮, 且当 MsgBox 自身的 线程 被其他线程中断时超时了, 那么 IfMsgBox 将认为用户按下了 "确定" 按钮.

Options 可以为一个或多个下列值的组合 (和).

功能 | 十进制值 | 十六进制值
确定 (即仅显示一个 "确定" 按钮) | 0 | 0x0
确定/取消 | 1 | 0x1
终止/重试/忽略 | 2 | 0x2
是/否/取消 | 3 | 0x3
是/否 | 4 | 0x4
重试/取消 | 5 | 0x5
取消/重试/继续 (2000/XP+) | 6 | 0x6
添加一个 "帮助" 按钮 (请参阅后面的备注) | 16384 | 0x4000
错误图标 (停止/错误) | 16 | 0x10
问号图标 | 32 | 0x20
惊叹号图标 | 48 | 0x30
星号图标 (信息) | 64 | 0x40
让第二个按钮成为默认按钮 | 256 | 0x100
让第三个按钮成为默认按钮 | 512 | 0x200
系统模态 (总是在顶部) | 4096 | 0x1000
任务模态 | 8192 | 0x2000
总是在顶部 (WS_EX_TOPMOST 样式) (和系统模态类似, 但省略了标题栏图标) | 262144 | 0x40000
让文本右对齐显示 | 524288 | 0x80000
用于希伯来语/阿拉伯语的从右向左的阅读顺序 | 1048576 | 0x100000

备注

使用上面的表格时, 可以把您期望用于 MsgBox 的选项值加在一起. 例如, 要显示一个默认按钮为 "否" 的 "是"/"否" 消息框, 那么需要把 Options 的值设置为 256+4 (260). 使用十六进制表示为 0x100+0x4 (0x104).

MsgBox 对逗号的处理比较智能, 所以通常不需要对 Text 参数中的逗号进行 转义.

要判断用户在最近的 MsgBox 中按下了哪个按钮, 请使用 IfMsgBox 命令. 例如:

MsgBox, 4,, Would you like to continue? (press Yes or No)
IfMsgBox Yes
    MsgBox You pressed Yes.
else
    MsgBox You pressed No.

参照 这个例子 可以自定义按钮的名称.

提示: 当 MsgBox 窗口活动时按下 Control-C 将复制其中的文本到剪贴板. 这适用于所有的 MsgBox, 而不仅是 AutoHotkey 生成的那些.

在 GUI 窗口中使用 MsgBox: 通过 Gui +OwnDialogs 的方法可以在 GUI 窗口中显示 模态 MsgBox. 模态 MsgBox 在其消失之前会阻止用户与原来的 GUI 窗口进行交互. 此时, 不需要指定上表中的系统模态或任务模态选项.

当 Gui +OwnDialogs 无效 时, 在用户响应 MsgBox 前可以使用任务模态选项 (8192) 来禁用所有的脚本窗口.

"帮助" 按钮: 在 Options 中使用了 "帮助" 按钮选项 (83) 时, 只有符合下面两个条件, 那么按下 "帮助" 按钮才会有效果:

  1. MsgBox 是由 GUI 窗口通过 Gui +OwnDialogs 的方法显示的.
  2. 脚本正在监听 WM_HELP 消息 (0x53). 例如: OnMessage(0x53, "WM_HELP"). 调用 WM_HELP() 函数时, 它可以通过如显示另一个窗口或 MsgBox 的方法引导用户.

"关闭" 按钮 (在 MsgBox 的标题栏): 由于 MsgBox 窗口是操作系统内置的特性, 所以它的 X 按钮仅在某些按钮存在时才会启用. 如果只有一个 "确定" 按钮, 那么点击 X 按钮等同于按下 "确定" 按钮. 其他情况下, 只有含有 "取消" 按钮时才会启用 X 按钮, 此时点击 X 等同于按下 "取消" 按钮.

相关

IfMsgBox, InputBox, FileSelectFile, FileSelectFolder, ToolTip, GUI

示例

MsgBox This is the 1-parameter method. Commas (,) do not need to be escaped.
MsgBox, 4, , This is the 3-parameter method. Commas (,) do not need to be escaped.
MsgBox, 4, , Do you want to continue? (Press YES or NO)
IfMsgBox No
    return
MsgBox, 4, , 4-parameter method: this MsgBox will time out in 5 seconds.  Continue?, 5
IfMsgBox Timeout
    MsgBox You didn't press YES or NO within the 5-second period.
else IfMsgBox No
    return

; 通过在任何参数前加上 "% ", 可以让此参数支持表达式. 在下面的例子中,
; 执行数学运算, 访问数组元素, 并且调用函数.  所有这些项
; 都可以通过 "." 运算符串联组成可以由 MsgBox 显示的单个字符串:
MsgBox % "New width for object #" . A_Index . " is: " . RestrictWidth(ObjectWidth%A_Index% * ScalingFactor)

; 下面的例子提醒用户 MsgBox 即将获取焦点 (此时用户正在输入).
SplashTextOn,,, A MsgBox is about to appear.
Sleep 3000
SplashTextOff
MsgBox The backup process has completed.


Progress / SplashImage

创建或更新含有进度条或图像的窗体.

SplashImage, Off
SplashImage [, ImageFile, Options, SubText, MainText, WinTitle, FontName]

Progress, Off
Progress, ProgressParam1 [, SubText, MainText, WinTitle, FontName]

参数

ImageFile | 如果此参数为单词 OFF, 则销毁窗体. 如果此参数为单词 SHOW, 则显示当前隐藏的窗体. 否则, 此参数为需要显示的 BMP, GIF, 或 JPG 图像的文件名 (如果要显示其他格式的图像例如 PNG, TIF, 和 ICO, 请考虑使用 Gui 命令创建一个包含图片控件的窗体). 如果没有指定绝对路径, 则假定 ImageFile 在 %A_WorkingDir% 中. 如果 ImageFile 和 Options 都为空并且窗体已经存在, 窗体中的图像保持不变,但是其中的文本将更新为由 SubText, MainText, 和 WinTitle 提供的新字符串. 对于新创建的窗体, 如果 ImageFile 为空或装载图片时出现问题, 显示的窗体将不含图片.
ProgressParam1 | 如果进度条窗体已经存在: 如果 Param1 为单词 OFF, 则销毁进度条窗体. 如果 Param1 为单词 SHOW, 则显示当前隐藏的窗体. 否则, 如果 Param1 是一个纯数字, 则改变进度条的位置为它的值. 如果 Param1 为空, 其进度条位置保持不变, 但是其中的文本将更新为由 SubText, MainText, 和 WinTitle 提供的新字符串. 在这两种形式中, 如果进度条窗体已经不存在, 则使用所有选项的默认值创建它. 如果进度条窗体不存在: 创建新的进度条窗体 (替换任何旧的), 此时Param1 是由下面列表中零个或多个选项组成的字符串.
Options | 此参数是由较远的下面列表中零个或多个选项组成的字符串.
SubText | 显示在图像或进度条下面的文本. 尽管会自动换行, 如果要明确的开始一个新行, 请使用换行符 (`n). 要设置一个现有窗体的文本为空, 请在此参数中指定 %A_Space%. 为了自动计算窗体的高度, 可以像下面的 MainText 那样保留空行.
MainText | 显示在图像或进度条上面的文本 (其字体为半粗体). 尽管会自动换行, 如果要明确的开始一个新行, 请使用换行符 (`n). 如果此选项为空或省略, 窗体不会预留空间给 MainText. 要为以后添加内容预留单行空间, 或设置一个现有窗体的文本为空, 请指定 %A_Space%. 要预留多行的空间, 请添加一个或多个换行符 (`n). 当设置好 MainText 的控件区域的高度后, 这个高度只有重新创建窗口才能改变.
WinTitle | 窗口的标题. 如果省略并且正新建窗口, 则使用脚本名称 (不含路径) 作为窗口标题. 如果指定了 B 选项(无边框), 窗口中的标题栏将看不见, 但是像 WinMove 这样的命令中仍可以通过这个标题引用此窗口.
FontName | 用于 MainText 和 SubText 中文本的字体名称. 字体列表 中列出了 Windows 系统各种版本中包含的字体. 如果此参数未指定或目标字体无法找到, 将使用系统默认的 GUI 字体. 关于如何改变字体的大小, 粗细和颜色, 请参看下面的选项段.

Window 的大小, 位置, 和 行为

A: 窗口将 不 总是置顶.

B: 无边框: 窗口将不含有边框和标题栏. 要含有边框而没有标题栏, 请使用 B1 添加薄边框或 B2 来添加对话框样式的边框.

M: 用户可以移动窗口 (除非不含有边框). 另外如果要使窗口大小可以调整 (通过拖动边框的方法), 请指定 M1. 另外如果要在标题栏中包含系统菜单和最小化/最大化/关闭按钮的集合, 请指定 M2.

Pn: 对于进度条窗口, 请指定 n 为进度条的初始位置 (默认值为 0 或者是允许的范围内最接近 0 的数字). 以后要改变进度条的位置时, 请参照此例: Progress, 50

Rx-y: 对于进度条窗口, 请指定 x-y 为进度条的数值范围 (如果 R 不存在, 默认值为 0-100). 例如, R0-1000 将允许介于 0 和 1000 之间的数字; R-50-50 将允许介于 -50 和 50 之间的数字; 而 R-10--5 将允许介于 -10 和 -5 之间的数字. 在 Windows 95 和 NT4 系统中, 只有安装了Internet Explorer 3.0 或更高版本后, 含有负数或超过 65535 数字的区间才能正确的执行.

T: 给窗口增加任务栏按钮并使窗口变成非从属的/独立的. 通常情况下, 从属于脚本主窗体的窗体是没有任务栏按钮的. 此设置也避免了 GUI 窗口使用 Gui +OwnDialogs 的方法获取弹出窗口或进度条窗口的所有权关系.

Hn: 请指定 n 为窗体客户区的高度 (窗体客户区不包含标题栏和边框). 如果未指定, 将根据图像/进度条和文本的高度 自动 计算窗体的高度.

Wn: 请指定 n 为窗体客户区的宽度. 如果未指定, 将根据 SplashImage(如果含有图像的话) 自动 计算窗体的宽度. 否则, 默认宽度为 300.

Xn: 请指定 n 为窗体左上角的 x坐标. 如果未指定, 窗体在屏幕上将水平居中.

Yn: 请指定 n 为窗体左上角的 y坐标. 如果未指定, 窗体在屏幕上将垂直居中.

Hide: 窗体在开始时为隐藏的. 以后要显示时请使用 Progress Show 或 SplashImage Show 命令.

窗体中的组件布局

Cxy: 居中: 如果此选项不存在, SubText 和 MainText 都将居中显示在窗体内. 指定 x 为 0 可以使 SubText 向左对齐. 指定为 1 使其居中显示. 在 y 中指定相同的值效果是一样的, 不过其适用于 MainText (y 可以省略). 例如: c10

ZHn: 组件的高度: 对于进度条窗体, 请指定 n 为进度条的厚度 (默认为 20). 对于 SplashImage 窗口, 请指定 n 为图像的高度. 指定 -1 使得高度自适应于在 ZWn 指定的宽度(即保持宽高比). 如果未指定, 将使用图像的实际高度. 在这两种情况中, 指定 0 可以不显示整个对象, 此时可以让窗口仅显示自定义字体样式, 大小和颜色的文本.

ZWn: 组件的宽度 (仅适用于 SplashImage 窗口): 请指定 n 为图像的宽度. 指定 -1 使得宽度自适应于在 ZHn 中指定的高度(即保持宽高比). 如果未指定, 将使用图像的实际宽度.

ZXn: 请指定 n 为窗口左/右边缘的空白大小总和. 对于不含文本的 SplashImage 窗口默认大小为 0, 其他情况默认大小为 10.

ZYn: 请指定 n 为窗口顶部和底部以及每个控件间在垂直方向上空白空间的大小总和. 对于不含文本的 SplashImage 窗口默认大小为 0, 其他情况默认为 5.

请注意: 要创建一个垂直的进度条或让窗口布局更灵活, 请使用 Gui 命令, 例如:

Gui, Add, Progress, Vertical vMyProgress
Gui, Show
return
; ... later...
GuiControl,, MyProgress, +10  ; Move the bar upward by 10 percent. Omit the + to set an absolute position.

字体的大小和粗细

FMn: 请指定 n 为 MainText 中的字体大小. 默认为 0, 此时在大多数系统中会使用 10 作为字体大小. 此默认值不会影响在 控制面板 > 显示设置 中系统选择的字体大小.

FSn: 请指定 n 为 SubText 中的字体大小. 默认为 0, 此时在大多数系统中会使用 8 作为字体大小.

WMn: 请指定 n 为 MainText 中的字体粗细. 字体粗细应该介于 1 和 1000 之间. 如果未指定, 将使用 600 (半粗体).

WSn: 请指定 n 为 SubText 中的字体粗细. 字体粗细应该介于 1 和 1000 之间 (700 一般被认为是 "粗体"). 如果未指定, 将使用 400 (正常字体).

组件颜色

颜色值可以是下面列表中名称的其中一个 或 一个 6位的十六进制 RGB 值. 例如, 指定 cw1A00FF 将设置窗口背景颜色中红色通道为 1A, 绿色通道为 00, 蓝色通道为 FF.

如果后面还有更多的选项, 请在颜色选项后添加一个空格. 例如: cbRed ct900000 cwBlue

CBn: 进度条的颜色: 请指定 n 为16 种 HTML 基础颜色之一或是 6 位的 RGB 颜色值. 如果未指定, 将使用系统的默认进度条颜色. 指定单词 Default 以返回到系统的默认进度栏颜色.

CTn: 文本颜色: 指定 n 为16 种 HTML 基础颜色之一或是 6 位的 RGB 颜色值. 如果未指定, 将使用系统的默认文本颜色 (通常为黑色). 指定单词 Default 以返回到系统的默认文本颜色.

CWn: 窗体颜色 (背景): 指定 n 为16 种 HTML 基础颜色之一或是 6 位的 RGB 颜色值. 如果未指定, 将使用按钮外观的系统颜色 (以后指定单词 Default 可以返回到此颜色). 在 Windows 2000/XP 或更高版本系统中要使窗口背景透明, 请使用 WinSet TransColor.

颜色名称和相应的RGB值
Black = 000000 | Green = 008000
Silver = C0C0C0 | Lime = 00FF00
Gray = 808080 | Olive = 808000
White = FFFFFF | Yellow = FFFF00
Maroon = 800000 | Navy = 000080
Red = FF0000 | Blue = 0000FF
Purple = 800080 | Teal = 008080
Fuchsia = FF00FF | Aqua = 00FFFF

备注

如果首个参数为单词 OFF, 则销毁窗体.

每个脚本可以显示多达 10 个进度窗口和 10 个 SplashImage 窗口. 创建每个窗口时都会给它分配一个编号. 如果未指定, 此编号为 1(对于首个窗口). 否则, 请在首个参数前加上窗口编号跟一个冒号. 例如, 带有 2:Off 参数的 Progress 命令将关闭编号为 2 的进度条窗口, 2:75 将设置其进度条到 75% 的位置, 2: 将改变其一个或多个文本区域, 而 2:B 将创建一个新的无边界进度条窗体. 同样, 带有 2:Off 参数的 SplashImage 命令将关闭编号为 2 的 SplashImage 窗体, 2: 将改变其一个或多个文本区域, 而 2:C:\My Images\Picture1.jpg 将创建一个新的为 2 的 SplashImage 窗体.

在创建时, 一个大于桌面的窗口会被自动缩小以适应桌面.

指定 SubText 和 MainText 为空并且包含下列选项: b zx0 zy0, 可以显示一个单独的进度条.加上 B 选项后, 用同样的方法可以显示一个单独的图像.

在 Windows XP 或更高版本系统中, 如果当前使用的不是经典主题, 进度条的内部可能显示为一段段而不是一个平滑连续的条. 为了避免这种情况, 请明确指定进度条颜色例如 cbBlue.

除非特别注明, 否则在需要数字的选项字母中使用十进制数 (而不是十六进制数).

像 WinSet and WinMove 这样的命令可以改变一个现有窗口的属性而不必重新创建窗口.

一个 GUI 窗口可以通过 Gui +OwnDialogs 的方法获取进度条窗口或弹出窗口的所有权. 这将使得弹出窗口或进度条窗口总是保持在其父窗口的前面. 此外, 当其从属的 GUI 窗口销毁时, 进度条窗口或弹出窗口自动销毁.

相关

GUI, SplashTextOn, ToolTip

示例

Progress, b w200, My SubText, My MainText, My Title
Progress, 50 ; Set the position of the bar to 50%.
Sleep, 4000
Progress, Off

; Create a window just to display some 18-point Courier text:
Progress, m2 b fs18 zh0, This is the Text.`nThis is a 2nd line., , , Courier New

; Create a simple SplashImage window:
SplashImage, C:\My Pictures\Company Logo.gif

; Create a borderless SplashImage window with some large text beneath the image:
SplashImage, C:\My Pictures\Company Logo.gif, b fs18, This is our company logo.
Sleep, 4000
SplashImage, Off

; Here is a working example that demonstrates how a Progress window can be
; overlayed on a SplashImage to make a professional looking Installer screen:
IfExist, C:\WINDOWS\system32\ntimage.gif, SplashImage, %A_WinDir%\system32\ntimage.gif, A,,, Installation
Loop, %A_WinDir%\system32\*.*
{
    Progress, %a_index%, %a_loopfilename%, Installing..., Draft Installation
    Sleep, 50
    if a_index = 100
        break
}
; There is similar example at the bottom of the GUI page. Its advantage is that it uses only a single
; window and it gives you more control over window layout.


SplashTextOn / SplashTextOff

创建可定制的文本弹出窗口。

SplashTextOff
SplashTextOn [, Width, Height, Title, Text]

参数

Width | 窗口的像素级宽度。默认是 200 。此参数可以是一个 表达式 。
Height | 窗口的像素级高度 (如果脚本的文件扩展名不是 .aut ，那么不包括它的标题栏)。默认是 0 (也就是只显示标题栏)。此参数可以是一个 表达式 。
Title | 窗口的标题。默认是空的 (空白)。
Text | 窗口的文本。默认是空的 (空白)。如果 Text 很长，它能通过一种 continuation section(连续章节) 的方法被分解为多个更短的行，这样可以改善可读性和可维护性。

注意

要进一步控制布局和字体名称/颜色/大小，请用 Progress 命令和 zh0 选项，其省略栏目而只显示文本。例如：Progress, zh0 fs18, 显示一些 18-point(磅) 的文本。

可用 SplashTextOff 命令来消除已存在的弹出窗口。

弹出窗口是”总在最上面“的，意味着它停留在其他所有普通窗口的上面。要改变这种状态，可用 WinSet, AlwaysOnTop, Off, <插入弹出窗口的标题>。WinSet 同样能使弹出窗口变透明。

在此命令显示弹出文本窗口后 WinMove 可被用来将其重新定位以及调整大小。

和 Progress, SplashImage, MsgBox, InputBox, FileSelectFile 以及 FileSelectFolder 不同，每个脚本只能有一个弹出文本窗口。

如果在弹出窗口已经显示时使用 SplashTextOn ，窗口将用新的参数值来重新创建。不过，与其在你想要改变弹出窗口的标题或文本时去重新创建它，倒不如用下面的方法来获得更好的性能，特别是在窗口需要被频繁地改变时：
WinSetTitle, <插入弹出窗口的标题>, , 新标题
ControlSetText, Static1, 新文本, <插入弹出窗口的标题>

相关命令

Progress, SplashImage, ToolTip, MsgBox, InputBox, FileSelectFile, FileSelectFolder, WinMove, WinSet

示例

SplashTextOn, , , 仅显示标题栏。
Sleep, 2000
SplashTextOn, 400, 300, Clipboard, 剪贴板包含：`n%clipboard%
WinMove, Clipboard, , 0, 0  ; 移动弹出窗口到左上角。
Msgbox, 按确定后消除弹出文本
SplashTextOff


ToolTip

创建一个在屏幕任何位置上总在最前端的窗口。

ToolTip [, Text, X, Y, WhichToolTip]

参数

Text | 如果留空或省略，已存在的 tooltip (如果有的话) 将被隐藏。否则，此参数是要显示在 tooltip 中的文本。要创建一个多行 tooltip ，在每行中使用换行符(`n)，例如 行1`n行2 。 如果 Text 很长，通过使用一个 continuation section(连续章节) 能将它分成许多更短的行，这会改善可读性和可维护性。
X, Y | 相对于激活的窗口的 tooltip 的 X 和 Y 坐标位置(使用 "CoordMode, ToolTip" 来改变成屏幕坐标)。如果省略坐标，tooltip 将显示在鼠标指针附近。X 和 Y 坐标可以是 expressions(表达式) 。
WhichToolTip | 如果你不需要同时显示多个 tooltips ，省略此参数。否则，在 1 到 20 之间的一个数字指示哪个 tooltip 窗口运作在上面。如果未指定，这数字是 1 (首个)。此参数可以是一个 expression 。

注意

如果 X 和 Y 坐标会导致 tooltip 脱离屏幕，它会重新定位来使其整个可见。

tooltip 会显示，直到发生了下列情况之一：

  • 脚本终止。
  • ToolTip 命令用一个空的 Text 参数再次执行。
  • 用户在 tooltip 上点击 (此特性会根据操作系统的版本而出现不同)。

一个 GUI(图形用户接口) 窗口可通过 Gui +OwnDialogs 来成为一个 tooltip 的主人。这样的一个 tooltip 会在它的主人毁灭后自动地毁灭。

相关命令

CoordMode, TrayTip, GUI, Progress, SplashTextOn, MsgBox, InputBox, FileSelectFile, FileSelectFolder

示例

ToolTip, 多行`nTooltip, 100, 150

; 要使一个 ToolTip 不使用 Sleep(其停止当前线程) 而在某个时间段后消失：
#Persistent
ToolTip, 定时的 ToolTip`n它将显示 5 秒。
SetTimer, RemoveToolTip, 5000
return

RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return


TrayTip

在托盘图标处创建一个气泡消息窗口。要求 Windows 2000/XP 或以上操作系统。

TrayTip [, Title, Text, Seconds, Options]

参数

Title

如果省略所有参数，当前显示的任何气泡消息窗口将被移除。

否则，此参数是窗体的标题，最长 73 字符（超出此长度将不显示）。

如果 Title 为空，标题行将完全不显示，使窗口垂直距离缩短。
Text

如果省略此参数或留空，当前显示的任何气泡消息窗口将被移除。

否则，指定要显示的信息，会在 Title 下方显示。只显示 Text 的前 265 字符。回车符(`r)或换行符(`n)可以被用来创建多行文本。例如：行1`n行2

如果 Text 较长，可通过 continuation section(连 续章节) 分割成若干较短的行，来提高程序的可读性和可维护性。
Seconds

窗体显示的大概的秒数，之后它将被操作系统自动地移除。指定一个小于 10 或大于 30 的数字，通常会被最小值 (10) 或最大值 (30) 的显示时间代替。如果省略或留空，通常会采用最小时间。此参数可以是 expression(表达 式)。

真实的时间可能不同于指定的时间。Microsoft 解释说，“如果没有显示用户正在使用计算机，系统会不将此段时间计入。”(技术细节请看 这 里。)因此，为了精确控制托盘窗口的显示，可使用 Sleep 命令紧跟不带参数的 TrayTip，或像下方示例中使用 SetTimer 。
Options

指定一下数字中的一个，会在 Title 左侧显示小图标：

1: 消息图标
2: 警告图标
3: 错误图标

如果省略，默认为 0，无图标显示。此参数可以是 expression 。

注意

TrayTip 要求 Windows 2000/XP 或以上的操作系统。在 Windows 9x/NT 上此命令不起作用。

如果脚本没有托盘图标(通过 #NoTrayIcon 或 Menu, tray, NoIcon)，那么 TrayTip 气泡窗体不能被显示。同样地，如果下列的 REG_DWORD 值已存在，并已被设为 0 ，那么 TrayTip 不会起作用：
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced >> EnableBalloonTips

当显示一个气泡窗体时，操作系统通常会播放一个声音。可通过加上 16 到 Options 参 数来关闭此声音(例如 16 是无声音无图标，17 是无声音有信息图标，等等。)

做一个相关提示，每当用户将鼠标悬停在脚本托盘图标上时，会有提示显示。提示内容可以通过：Menu, Tray, Tip, 我的新文本 来改变。

相关命令

ToolTip, SetTimer, Menu, SplashTextOn, MsgBox, InputBox, FileSelectFile, FileSelectFolder

示例

TrayTip, My Title, Multiline`nText, 20, 17

; 为了更精确的控制显示时间
; 而不使用 Sleep (其会停止当前线程):
#Persistent
TrayTip, Timed TrayTip, 此文本将被显示 5 秒。
SetTimer, RemoveTrayTip, 5000
return
RemoveTrayTip:
SetTimer, RemoveTrayTip, Off
TrayTip
return
; 为了让 TrayTip 永久显示, 使用 timer 来周期性地进行刷新：
SetTimer, RefreshTrayTip, 1000
Gosub, RefreshTrayTip ; 调用一次来让它马上开始。
return
RefreshTrayTip:
TrayTip, Refreshed TrayTip, 这是一个更持久的 TrayTip 。, , 16
return


#HotkeyInterval

随同 #MaxHotkeysPerInterval 一起，指定 热键 激活的速率，当超过这一速率时，将会显示一个警告对话框。

#HotkeyInterval Milliseconds

参数

Milliseconds 间隔的长度，以毫秒为单位。

注意

如果在脚本里没有指定该指令，它会像设为 2000 毫秒一样运转。

更多细节和注意事项，请参考：#MaxHotkeysPerInterval 。

相关命令

#MaxHotkeysPerInterval

示例

#HotkeyInterval 2000  ; 这是默认值(毫秒)。
#MaxHotkeysPerInterval 200


#HotkeyModifierTimeout

影响 热键 修饰符的行为: CTRL, ALT, WIN, 和 SHIFT.

#HotkeyModifierTimeout Milliseconds

参数

Milliseconds 以毫秒为单位的时间间隔.值为-1时,从不超时 (在 Send 命令后修饰键总是被推回到按下的状态), 值为0时,总是超时 (修饰键从不被推回到按下的状态).

备注

该指令 不会 影响下面的情况:

  • 热键通过 SendInput 或 SendPlay 模式发送的键击. 这是因为这些模式缓存用户的物理键击直到发送完成才释放。
  • 脚本安装了键盘钩子 (如果你的脚本使用了钩子,你可以通过主窗口 "View->Key history" 菜单项目, 或者使用 KeyHistory 命令查看). 这是由于钩子可以记录用户实际按住的修饰键 (ALT/CTRL/WIN/SHIFT), 所以不需要使用超时.

为了说明这个指令的效果, 请思考这个例子:
^!a::Send, abc

当 Send 命令执行时, 首先它释放 CTRL 和 ALT 按键使得这些字符可以正确地发送. 在发送所有的按键后, 此命令不知道是否应该安全的推回到按住 CTRL 和 ALT 的状态 (以匹配在这过程中用户持续的按住它们). 不过如果过去的时间还没达到指定的毫秒数值, 它将假定用户还没来得及释放这些按键而把他们推回到按下的状态以匹配他们的物理状态. 否则, 修饰键将不会被推回到按下的状态, 用户必须再次按下他们以让他们修饰相同的或另一个热键.

此超时时间应该被设置为小于用户从实际按下修饰键到释放他们的时间. 否则, 修饰键可能被恢复到按下的状态(卡住)即使用户实际上并没有按住他们.

出现下列情况的其中一种时你可以减少或不使用此指令:

  • 在脚本中的任何位置增加一行 #InstallKeybdHook 来安装键盘钩子 (然而, Win9x 系统中不支持键盘钩子).
  • 使用 SendInput 或 SendPlay 模式代替传统的 SendEvent 模式.
  • 当使用传统的 SendEvent 模式时, 减小 SetKeyDelay 的延时到 0 或 -1, 这样有助于更快速的发送键击.

如果脚本中没有指定这个指令, 默认设为 50.

相关

GetKeyState

示例

#HotkeyModifierTimeout 100


#Hotstring

改变 热字符串 的选项或结尾字符。

#Hotstring NoMouse
#Hotstring EndChars NewChars
#Hotstring NewOptions

参数

NoMouse 防止鼠标点击会像 这里 描述的那样重设热字符串识别器。作为副作用，这也阻止了热字符串需要的 鼠标钩子 (然而如果脚本因为其他目的需要它时，它仍会被安装，例如鼠标热键)。#Hotstring NoMouse 出现在脚本的任何位置都将影响所有的热字符串，不仅仅是那些物理上在它下面的热字串。
EndChars NewChars

指定 EndChars 单词，紧跟单独空格然后是新的结尾字符。例如：
#Hotstring EndChars -()[]{}':;"/\,.?!`n `t

由于新的结尾字符对整个脚本是全局生效的 -- 不管 EndChars 指令出现在哪里 -- 故没有必要多次指定 EndChars 。

结尾字符的最大数量是 100 个。超出此长度的字符将被忽略。

要让 tab 成为一个结尾字符，在列表里包括 `t 。要让空格成为一个结尾字符，在列表的其他两个字符中间包含它 (或在列表开头，如果列表仅包含一个其他字符或没有其他字符)。

NewOptions

指定新选项给 热字符串选项 里描述的选项。例如： #Hotstring r s k0 c0

与上面的 EndChars 不同，#Hotstring 指令按这种方法使用时是位置相关的。换句话说，整个热字符串部分可以有不同的默认选项，像在这个例子中一样：

::btw::by the way

#Hotstring r c  ; 下面所有的热字符串将使用 "send raw" 并且默认为区分大小写。
::al::airline
::CEO::Chief Executive Officer

#Hotstring c0  ; 让这下面的所有热字符串不区分大小写。

相关命令

Hotstrings


#If

#If [AHK_L]

创建上下文相关的 热键 和 热字串. 这样的热键根据表达式的结果执行不同的操作 (或什么都不做).

#If [, Expression ]

参数

Expression 任何有效的 表达式.

基本操作

可以使用任何有效的表达式定义激活活动的上下文. 例如:

#If WinActive("ahk_class Notepad") or WinActive(MyWindowTitle)
#Space::MsgBox You pressed Win+Spacebar in Notepad or %MyWindowTitle%.

与 #IfWin 指令一样, #If 是可选的: 它影响脚本中所有实际在它后面的热键和热字串. #If 和 #IfWin 同时也是互斥的; 即只有最近的 #If 或 #IfWin 会起作用.

要关闭上下文相关性, 请指定 #If 或任一 #IfWin 指令但省略所有参数. 例如:

#If

一般说明

当按下了按键组合的其中一种形式的热键, #If 表达式的计算结果决定了是否应该激活热键. 只有在表达式计算完成或 超时 后系统才会响应键盘输入.

由于 AutoHotkey 设计上的怪癖, #If 表达式在某些情况下可能被计算两次. 因此, #If 表达式应该设计为没有副作用.

[AHK_L 53+]: A_ThisHotkey 包含了当前正在求值的 #If 表达式的热键名称

相关

大部分 #IfWin 指令的行为属性也适用于 #If.

可以使用 #IfTimeout 覆盖默认的超时时间值.

示例

; 示例 1: Adjust volume by scrolling the mouse wheel over the taskbar.
#If MouseIsOver("ahk_class Shell_TrayWnd") WheelUp::Send {Volume_Up} WheelDown::Send {Volume_Down} MouseIsOver(WinTitle) { MouseGetPos,,, Win return WinExist(WinTitle . " ahk_id " . Win) }

; 示例 2: Simple word-delete shortcuts for all Edit controls.
#If ActiveControlIsOfClass("Edit") ^BS::Send ^+{Left}{Del} ^Del::Send ^+{Right}{Del} ActiveControlIsOfClass(Class) { ControlGetFocus, FocusedControl, A ControlGet, FocusedControlHwnd, Hwnd,, %FocusedControl%, A WinGetClass, FocusedControlClass, ahk_id %FocusedControlHwnd% return (FocusedControlClass=Class) }

; 示例 3: Context-insensitive hotkey.
#If Esc::ExitApp

; 示例 4: Dynamic hotkeys. Requires Example 1.
NumpadAdd:: Hotkey, If, MouseIsOver("ahk_class Shell_TrayWnd") if (doubleup := !doubleup) Hotkey, WheelUp, DoubleUp else Hotkey, WheelUp, WheelUp return DoubleUp: Send {Volume_Up 2} return


#IfTimeout

#IfTimeout [AHK_L 8+]

设置计算单个 #If 表达式可以使用的最大时间.

#IfTimeout Timeout

参数

Timeout 全局有效的超时时间值, 单位为毫秒.

备注

设置超时时间是为了防止长时间计算表达式而延迟了键盘输入的处理. 如果超过了超时时间, 则继续计算表达式, 但键盘钩子将假定表达式结果为假而继续.

如果脚本中未指定此指令, 则超时时间默认为 1000.

注意系统使用它自己的超时时间. 如果超过了系统的超时时间, 热键和按键原本的功能都可能激活. 系统超时时间值定义为 DWORD 类型值 LowLevelHooksTimeout, 保存在后面的注册表键中:

HKEY_CURRENT_USER\Control Panel\Desktop

相关

#If

示例

#IfTimeout 10 ; Set the timeout to 10 ms.


#IfWinActive / #IfWinExist

创建上下文相关的 热键 和 热字符串 。这样的热键视某类窗口的激活或存在而执行一个不同的动作 (或根本不执行) 。

#IfWinActive [, WinTitle, WinText]
#IfWinExist [, WinTitle, WinText]
#IfWinNotActive [, WinTitle, WinText]
#IfWinNotExist [, WinTitle, WinText]

参数

WinTitle | 目标窗口的标题或部分标题 (匹配模式由设置在 自动执行部分 里的 SetTitleMatchMode 决定)。要使用一个窗口类，指定 ahk_class 确切的ClassName (通过 Window Spy 显示的)。要使用一个 窗口组 ，指定 ahk_group GroupName 。也支持 ahk_pid 和 ahk_id 关键词，但对 #IfWin 来说更常见的是通过 GroupAdd 间接地使用它们(或者，使用 "Hotkey IfWin")。最后，通过指定 多个条件 可以缩小搜索范围。例如：My File.txt ahk_class Notepad
WinText | 如果有的话，此参数必须是目标窗口的单独文本对象中的子字符串 (像内含的 Window Spy 工具显示的那样)。如果 DetectHiddenText 在自动执行部分(脚本的顶部)已被开启，隐藏的文本对象会被探测到。
ExcludeTitle ExcludeText | 虽然这些不被支持，但它们能间接地通过指定 ahk_group MyGroup 给 WinTitle 来使用(在那通过 GroupAdd 创建 MyGroup ，它支持 ExcludeTitle/Text)。

基本的操作

#IfWin 指令能简单地创建上下文相关的 hotkeys 和 hotstrings 。例如：

#IfWinActive ahk_class Notepad
#space::MsgBox 你在记事本中按了 Win+空格 。

#IfWin 指令是位置相关的：它们影响脚本中在它们下面的所有热键和热字符串。它们也是互斥的；也就是说，只有最近的一个才会生效。

要关闭上下文制约，指定任意 #IfWin 指令但省略它所有的参数。例如：

#IfWinActive

当 #IfWin 关闭时 (或没用在脚本中)，所有的 热键 和 热字符串 对所有的窗口都有效 (除了被 Suspend 或 Hotkey 命令 禁用)。

当一个鼠标或键盘热键被 #IfWin 条件限制时，它执行它本来的功能；也就是说，它传递到激活的窗口时就仿佛没有那么一个热键。有两个例外： 1) Windows 95/98/Me: 按一个 IfWin-禁用的 热键没有任何效果 (甚至没有它本来的功能)； 2) 操纵杆热键: 虽然 #IfWin 可用，但它不能阻止其他程序探测按钮的按动。

#IfWin 也能用来改变一个普通的按键像 Enter 或 空格 的表现。这在一个特殊的窗口忽略那个按键或执行一些你发觉不想要的动作时很有用。例如：

#IfWinActive Reminders ahk_class #32770  ; 在 Outlook 里的 "reminders" 。
Enter::Send !o  ; 让 "Enter" 键击打开选择的 reminder 而不是让它睡觉。
#IfWinActive

变体 (重复的) 热键

一个特定的 热键 或 热字符串 能在脚本中定义多次，假如每个定义都有不同的 #IfWin 条件。这些被称作 hotkey variants(热键变体)。例如：

#IfWinActive ahk_class Notepad
^!c::MsgBox 你在记事本中按了 Control+Alt+C 。
#IfWinActive ahk_class WordPadClass
^!c::MsgBox 你在写字板中按了 Control+Alt+C 。
#IfWinActive
^!c::MsgBox 你在不是记事本/写字板的窗口中按了 Control+Alt+C 。

如果有多个(译注：即条件不同但热键相同)变体适合被激发，那么只有最接近脚本顶部的那个会被激发。除此之外是全局的变体 (没有 #IfWin 条件): 它总是最低的优先级；因此，它只在没有其他合适的变体的时侯才会激发 (这个例外不适用于 热字符串)。

在创建重复的热键时，修饰键符号 例如 ^!+# 的顺序没有关系。例如，^!c 和 !^c 是一样的。不过按键必须拼写一致。例如，为了这种目的， Esc 和 Escape 是不一样的(然而大小写没关系)。同样，任何带 通配符前缀 (*) 的热键完全和一个没有通配符的有区别；例如，*F1 和 F1 每个都将会有它们自己的一组变体。

要让同个热键的子程序通过多个变体执行，最简单的方法就是创建一堆相同的热键，每个热键都有不同的 #IfWin 指令在它上面。例如：

#IfWinActive ahk_class Notepad
#z::
#IfWinActive ahk_class WordPadClass
#z::
MsgBox 你在记事本或写字板中按了 Win+Z 。
return

或者，通过 #IfWinActive ahk_group MyGroup 使用一个 窗口组 。

要动态地创建热键变种 (当脚本在运行时)，请看 "Hotkey IfWin" 。

一般说明

#IfWin 也能在前缀按键被占用时还原它们本来的功能 (在一个热键像 "a & b" 中 前缀按键 是 "a" 键)。这用在没有给一个特定的前缀指定可用的热键时。

当 Gosub 或 Goto 被用来跳转到一个热键或热字符串标识时，它跳转到最接近脚本顶部的那个变体。

当一个热键当前被 #IfWin 限制时，它的按键或鼠标按钮会用一个 "#" 符号出现在 KeyHistory 的 "Type" 列里。这能帮助调试一个脚本。

当前不支持例如 %Var% 的变量引用。因此，百分号必须通过 `% 转义 来允许将来支持它们。同样，原义的的逗号必须被转义 (通过 `,) 来允许附加的变量在将来被添加。如果你需要绕弯解决这种限制，使用 GroupAdd 和 ahk_group 。

Hotkey 命令 指定热键的 label 不直接被 #IfWin 影响。取而代之的是，在最接近脚本底部使用的 #IfWin (如果有的话) 将影响所有由 Hotkey 命令创建的热键 (除非使用 "Hotkey IfWin" 来改变)。

Alt-tab 热键 不受 #IfWin 影响: 它们在所有的窗口有效。

最后找到的窗口 可被 #IfWinActive/Exist 设置(但是不被 #IfWinNotActive/NotExist 设置)。例如：

#IfWinExist ahk_class Notepad
#n::WinActivate  ; 激活被 #IfWin 找到的窗口。

如果在 #IfWin 的某个变量里需要开头或结尾空格，转义顺序 `s 和 `t 可以被使用。

由于性能的原因，#IfWin 不会持续监视指定窗口的激活或存在。取而代之的是，它只在你输入一个热键或热字串时才去核查匹配窗口。如果匹配的窗口不存在，你的键击或鼠标点击会被允许传递给没变的激活窗口 (除了在 Windows 95/98/Me 上)。

Windows 95/98/Me: 如果热键的首个变体有一个 $ 前缀，所有的变体将被允许 "发送它们本身" 。这为一个热键去执行它原来的功能提供了一种方法而不是完全什么也不做。例如：

$^a::Send ^a  ; 首个变体必须有一个 $ 前缀来允许它在 Windows 9x 上 "发送自身"。
#IfWinActive ahk_class Notepad
^a::MsgBox 你在记事本激活时按了 Control-A 。

窗口标题和文本是区别大小写的。隐藏的窗口不被探测，除非 DetectHiddenWindows 在自动执行部分 (脚本顶部) 被开启。

相关命令

Hotkey command, Hotkeys, Hotstrings, Suspend, IfWinActive, IfWinExist, SetTitleMatchMode, DetectHiddenWindows

示例

#IfWinActive ahk_class Notepad
^!a::MsgBox 在记事本激活时你按了 Ctrl-Alt-A 。  ; 此热键如果在别的窗口按是无效的 (它将 "pass through"[经过] )。
#c::MsgBox 在记事本激活时你按了 Win-C 。
::btw::此 "btw" 的替换文本将只在记事本里出现。
#IfWinActive
#c::MsgBox 在一个不是记事本的窗口里你按了 Win-C 。


#MaxHotkeysPerInterval

随同 # HotkeyInterval 一起，指定 热键 激活的速率，当超过这一速率时，将会显示一个警告对话框。

#MaxHotkeysPerInterval Value

参数

Value 在 # HotkeyInterval 指定的时间里，不会触发一个警告对话框而能被按下的热键数量的上限。

注意

注意不要将上述数值设定得过于宽松，因为如果你不经意地引入一个键击的无限循环(通过一个 Send 命令意外地触发其它热键)的话，由于快速而泛滥的键盘事件，你的电脑可能会变得反应迟钝。

举一个非常简单的例子，热键 ^c::Send ^c 将导致一个无限键击循环。要避免这种情况，为热键定义添加 $ 前缀 (例如 $^c::)，使得热键不能被 Send 命令触发。

如果没有在脚本中指定该指令，它会像设成 70 一样来运转。

相关命令

#HotkeyInterval

示例

#MaxHotkeysPerInterval 200


#MaxThreads

设置同时启动的线程的最大数量。

#MaxThreads Value

参数

Value 可同时存在的线程的最大总数。指定大于255的数值等同与指定255(在 1.0.48 以前的版本中，这个值的上限是20)。

注意

此设置是全局性的，这就意味着只需要将它指定一次（在脚本任何位置）就能影响整个脚本的表现。

虽然允许但是不推荐将值设为 1，因为这样会在每次脚本显示一个 MsgBox 或者其他对话框时阻止新的热键运行。也会在每次另一个线程休眠或等待时阻止定时器运行。

如果一个线程子程序的首行是 ExitApp, Pause, Edit, Reload, KeyHistory, ListLines, ListVars 或 ListHotkeys，那么至多两种接下来的线程类型即使在 #MaxThread 达到的情况下也可以被创建：hotkey, hotstring, OnClipboardChange, GUI event。还有，不论有多少线程存在，OnExit subroutine(子程序)总是可以启动。

如果此设置低于 #MaxThreadsPerHotkey，那么它将有效地取代那个设置。

如果脚本中没有指定此指令，那么它将表现得好像被设为 10 那样。

相关命令

#MaxThreadsPerHotkey, Threads, #MaxHotkeysPerInterval, #HotkeyInterval, ListHotkeys, #MaxMem

示例

#MaxThreads 2


#MaxThreadsBuffer

使得某些或所有的 热键 缓冲而不是忽略键击, 当达到它们的 #MaxThreadsPerHotkey 限制时.

#MaxThreadsBuffer On|Off

参数

On|Off

On: 从这里到下一个 #MaxThreadsBuffer ON 指令间的所有热键子程序都将缓冲它们热键的键击而不是忽略他们, 每当这些运行的子程序数达到它们的 #MaxThreadsPerHotkey 限制时.

Off: 这是默认的行为. 热键的键击将被忽略, 只要运行的热键已经达到它的最大线程数 (通常为 1, 不过可以通过 #MaxThreadsPerHotkey 来改变).

备注

此指令一般很少使用, 默认是关闭的, 因为这种类型的缓冲, 通常都弊大于利. 例如, 如果你意外的按下一个热键两次, 这个设置为打开的并且如果它的首个 线程 消耗不到 1 秒的时间就结束的话(根据设计, 这种类型的缓冲 1 秒后超时) , 将会导致此热键子程序自动运行两次.请注意 AutoHotkey 也使用多种其他的方法缓冲热键 (例如 "Thread Interrupt" 和 "Critical"). 只是这种特殊的方法可能是有害的, 因此它默认关闭.

此指令的主要用途是要增加键盘的自动重复特征的响应性. 例如, 当你按下一个它的 #MaxThreadsPerHotkey 设置为 1 (默认值) 的热键时, 如果此热键的子程序在运行中, 那么传入的键击将被忽略. 因此, 当子程序结束, 到它等待下一个自动重复的键击进来, 可能需要 50ms 或更多时间, 因为这是自动重复的键击被捕获的周期.为任何被自动重复时需要最好的响应时间的热键启用此指令可以避免 50ms 的延迟.

与所有的 # 指令一样, 此指令不应该像命令一样放在脚本中 (例如把它包含在一个子程序中是没必要的). 相反, 应该把它放在你希望影响的首个热键标签之前.

相关

#MaxThreads, #MaxThreadsPerHotkey , Critical, Thread (command), Threads, Hotkey, #MaxHotkeysPerInterval, #HotkeyInterval, ListHotkeys

示例

#MaxThreadsBuffer on
#x::MsgBox, This hotkey will use this type of buffering.
#y::MsgBox, And this one too.
#MaxThreadsBuffer off
#z::MsgBox, But not this one.


#MaxThreadsPerHotkey

设置每个热键或热字串能同时启动的线程的最大数量。

#MaxThreadsPerHotkey Value

参数

Value 一个给出的热键/热字串子程序能启动的线程的最大数量 (限制 20)。

注意

此设置被用来控制一个给出的热键或热字串子程序允许同时存在多少“实例”。例如，假设一个热键的最大限制是 1，在它的子程序已经运行的情况下，热键被再次按下，那么第二次按键将被忽略。这对防止意外的重复按键很有帮助。不过，如果你希望这些按键被缓冲而不是被忽略，也许是要增加键盘的自动重复特征的响应性，那么可以使用 #MaxThreadsBuffer。

与 #MaxThreads 不同，此设置不是全局性的。将它置于你希望影响的首个热键标签的前面，这样它后面所有的热键都将使用它的值，直到遇上此指令的另一个实例。

任何首行是 ExitApp, Pause, Edit, Reload, KeyHistory, ListLines, ListVars 或 ListHotkeys 的热键子程序将总是忽略此设置而运行。

如果 #MaxThreads 的设置低于此设置，那么会被优先采用。

如果脚本中没有指定此指令，它将表现得好像被设为 1 那样。

相关命令

#MaxThreads, #MaxThreadsBuffer, Critical, Threads, Hotkey, #MaxHotkeysPerInterval, #HotkeyInterval, ListHotkeys

示例

#MaxThreadsPerHotkey 3


#MenuMaskKey

#MenuMaskKey [AHK_L 38+]

改变使用哪个键来屏蔽 Win 或 Alt 按键弹起事件.

#MenuMaskKey KeyName

参数

KeyName 按键名称 或指定了非零的虚拟按键代码的 vkNN 序列. 不使用扫描代码.

备注

此设置是全局的, 这意味着只需要在脚本中指定一次 (在脚本的任何位置) 就可以影响整个脚本的行为.

如果一个热键使用了键盘钩子或鼠标钩子, 最后的键击对于活动窗口或系统可能会不可见. 对于使用 Win 或 Alt 作为修饰键的热键, 在释放修饰键时会激活开始菜单或活动窗口的菜单栏. 为了防止这样的情况发生, AutoHotkey 通过发送一个键击 "屏蔽" 了按键弹起事件. 在修订本 38 之前的版本中, 此键击总是 Ctrl 键击, 已知在某些应用程序中会产生问题.

如果脚本中未指定此指令, 默认设置为 Ctrl.

相关

参见 此贴 了解背景信息.

示例

#MenuMaskKey vk07 ; vk07 is unassigned.
#UseHook #Space:: !Space:: KeyWait LWin KeyWait RWin KeyWait Alt KeyHistory return


#UseHook

强制使用钩子来实现部分或全部键盘热键。

#UseHook [On|Off]

参数

On|Off

#UseHook 后不带下列单词的话就等同于 #UseHook On。

On: 将用键盘钩子来实现此处和下个 #UseHook OFF (如果有的话)之间所有的键盘热键。

Off: 将用默认的方法(如果可用 RegisterHotkey() 的话；否则会用键盘钩子)实现热键。

注意

通常只要可能，都会用 windows API 函数 RegisterHotkey() 来实现键盘热键。不过在某些条件下，如果用键盘钩子来代替的话，热键的响应性可能会更好。

将此指令调为 ON 就相当于在每个受影响热键的定义中使用 $ 前缀。Windows 95/98/Me 例外，它们忽略 #UseHook (虽然 $ 前缀能起有限的作用)。

和所有在脚本启动时仅执行一次的 # 指令一样，#UseHook 在脚本中不应该像命令那样被放置(也就是说，没必要将它包含在子程序中)。而是将它放在你想要影响的首个热键标签前。

使用键盘钩子的热键不能被 Send 命令触发。相似地，鼠标热键也不能被比如 Click 命令触发，因为所有的鼠标热键都使用鼠标钩子。要绕弯解决这种情况，可用 Gosub 直接跳转到热键的子程序。例如：Gosub #LButton

如果脚本中没有出现此指令，那么将表现得像设成了 OFF。

相关命令

#InstallKeybdHook, #InstallMouseHook, ListHotkeys

示例

#UseHook  ;在此点后强制给热键使用钩子。
#x::MsgBox, 此热键将用钩子实现。
#y::MsgBox, 这个也一样。
#UseHook off
#z::MsgBox, 但这个没用。


Hotkey

在脚本运行时创建, 修改, 启用或禁用热键.

Hotkey, KeyName [, Label, Options]
Hotkey, IfWinActive/Exist [, WinTitle, WinText]
Hotkey, If, Expression

参数

KeyName

热键的触发键的名称, 包括任何 修饰符. 例如, 指定 #c 来触发 Win+C 热键.

如果 KeyName 是一个现有的热键, 那么原来的热键将被此命令的其他参数值更新.

KeyName 也可以是现有的热键标签的名称 (即双冒号标签), 这样使得原来的热键被此命令的其他参数值更新.

当指定一个 现有的 热键时, KeyName 是不区分大小写的. 但是, 按键名称必须和现有的热键拼写相同 (即 这种情况下 Esc 与 Escape 是不同的). 并且, 修饰符 的顺序例如 ^!+# 是无关紧要的.

当前的 IfWin 设置 决定了 Hotkey 命令将操作热键的哪个 变体. 如果此变体还不存在, 它将被创建.

当首次创建一个热键时 -- 通过 Hotkey 命令或脚本中的 双冒号标签 -- 其键名以及修饰符的顺序成为此热键的固定名称, 像 A_ThisHotkey 包含的那样. 即使之后 Hotkey 命令使用不同的修饰符顺序操作此热键, 其名称也不会改变.
Label

热键按下时, 将被执行 (作为一个新 线程) 的标签的名称. 可以使用普通标签和 热键/热字串 标签. 不要包含后面的冒号. 如果使用动态的 Label (例如 %VarContainingLabelName%), 请首先调用 IsLabel(VarContainingLabelName) 来检查此标签是否存在.

如果 KeyName 为现有的热键, 此参数可以留空, 此时其标签不会发生变化. 这在仅需要修改热键的 Options 时有用.

如果指定了标签但热键之前已经使用此命令禁用了, 那么热键将保持禁用状态. 要启用它, 在 Options 包含 ON.

此参数还可以是下列特定值的其中一个:

On: 启用热键. 如果热键已经处于启用状态, 则不进行操作.

Off: 禁用热键. 如果热键已经处于禁用状态, 则不进行操作.

Toggle: 设置热键到相反的状态 (启用或禁用).

AltTab (和其他): 这些是在 这里 描述的特殊的 Alt-Tab 热键动作.

注意: 仅当不存在相应的标签时 这些值才有特殊的含义. 例如, 如果标签 On: 存在并且此参数为单词 ON, 它被当成标签名称. 要启用或禁用这样的热键, 使用 Options 参数. Label 可以省略; 例如, Hotkey Esc,, Off.

注意: 当前的 IfWin 设置 决定了 On/Off/Toggle 将操作热键的哪个 变体.
Options

由下列零个或多个字母组成的字符串, 字母间可以用空格分隔. 例如: UseErrorLevel B0

UseErrorLevel: 如果命令遇到问题, 此选项会跳过警告对话框, 设置 ErrorLevel 为 下表 中的一个代码, 然后让 当前线程 继续执行.

On: 如果热键当前是禁用的则启用它.

Off: 如果热键当前是启用的则禁用它. 此选项常用来创建一个初始状态为禁用的热键.

B 或 B0: 指定字母 B 将按照 #MaxThreadsBuffer 描述的方法缓冲热键. 指定 B0 (B 后面跟着数字 0) 来禁用这种类型的缓冲.

Pn: 指定字母 P 后面跟着热键的 线程优先级. 如果创建热键时省略 P 选项, 则优先级被设置为 0.

Tn: 指定字母 T 后面跟着一个表示为此热键允许的线程数, 如同 #MaxThreadsPerHotkey 中描述的那样. 例如: T5

如果 B 和 T 选项中同时省略或省略了其中一个并且热键已经存在, 则这些设置不会改变. 但如果热键还不存在 -- 即使用当前命令创建热键时 -- 它们将使用最近使用的值. 例如, 将使用最靠近脚本结尾的 #MaxThreadsBuffer 实例. 如果没有在脚本中使用 #MaxThreadsBuffer, 则使用其默认设置 (OFF). 对于 #IfWin 也是这样: 除非脚本启动后执行过 "Hotkey IfWin", 否则将对新创建的热键应用最近的实例.

注意: 当前的 IfWin 设置 决定了 Hotkey 命令将操作热键的哪个 变体. 如果此变体还不存在, 它将被创建.
IfWinActive
IfWinExist 		(IfWinNotActive 和 IfWinNotExist 也支持了). 这些子命令使此后创建的所有热键都是上下文相关的. 请参见 下面 了解详情.
WinTitle
WinText

在这两个参数中, 任何变量引用如 %var% 在命令执行结束时被固定下来. 换句话说, 此后对这些变量内容的改变不会影响现有的热键.

和 #IfWinActive/Exist 一样, WinTitle 和 WinText 为 SetTitleMatchMode 和 DetectHiddenWindows 使用在 自动执行段 中的默认设置. 参见 #IfWinActive/Exist 了解详情.

If, Expression [AHK_L 42]: #If Expression 的副本. Expression 必须准确匹配 现有的 #If expression, 不包括 "#If" 或 "#If,". 当用于 Hotkey 命令时, "If" 后面的逗号是必须的. 尽管此命令不能创建新的表达式, 但它可以使用现有的表达式创建新的热键. 参见 #If example 4.

返回值

只有在出现下列情况时 ErrorLevel 才会被改变: 1) 首个参数为 IfWin[Not]Active/Exist, 此时如果遇到问题返回值被设置为 1 否则为 0; 或 2) 在 Options 参数中使用了单词 UseErrorLevel .

错误 | 描述
1 | Label 参数指定了一个不存在的标签名.
2 | KeyName 参数中指定了一个或多个当前键盘布局/语言无法识别或不支持的键.
3 | 不支持的前缀键. 例如, 使用鼠标滚轮作为热键的前缀, 如 WheelDown & Enter 不被支持.
4 | KeyName 参数不适合用于 AltTab 或 ShiftAltTab 功能. 这种情况要求热键为两个键的组合. 例如: RControl & RShift::AltTab
5 | 命令尝试修改一个不存在的热键.
6 | 命令尝试修改一个现有热键的不存在的 变体. 要解决此问题, 使用 "Hotkey IfWin" 设置匹配那些需修改的热键变体的标准.
50 | Windows 95/98/Me: 命令成功执行但操作系统拒绝激活此热键. 这种情况通常由于此热键被其他脚本或应用程序 (或 OS 自身) "在使用中" 所引起的. 这种情况只发生在 Windows 95/98/Me, 因为在其他操作系统中程序将采用 键盘钩子 来 覆盖 这个优先决定权.
51 | Windows 95/98/Me: 命令成功执行但 Windows 95/98/Me 不支持此热键. 例如, 鼠标热键和前缀热键如 "a & b" 不被支持.
98 | 如果创建了此热键将超过每脚本 1000 个热键的限制 (不过, 每个热键的 变体 数目不受限制, 并且对于 热字串 的数目也没有限制).
99 | 内存不足. 这种情况极少, 通常仅在操作系统变得不稳定时才会发生.

提示: 使用 UseErrorLevel 选项可以检查一个热键变体是否存在. 例如:

Hotkey, ^!p,, UseErrorLevel
if ErrorLevel in 5,6
    MsgBox The hotkey does not exist or it has no variant for the current IfWin criteria.

备注

如果是需要根据活动窗口的类型自动禁用选择的热键或热字串, 使用 Hotkey, ^!c, Off 通常不如 #IfWinActive/Exist (或它们的动态副本 "Hotkey IfWinActive/Exist" below) 来的方便.

通过 双冒号 创建热键比使用 Hotkey 命令执行的更好因为在脚本启动时它们会被批量的启用 (而非一个一个地启用). 因此, 最好使用此命令创建那些在脚本开始运行后才知道键名的热键. 一种这样的情况是通过 INI 文件 为热键配置多个不同的动作.

一个给定的标签可以是多个热键的目标. 如果一个热键调用了标签, 您可以通过检查内置变量 A_ThisHotkey 来确定是哪个热键.

如果脚本是 挂起的, 新增加/启用的热键也将是挂起的, 直到挂起状态被关闭 (除非它们像 Suspend 命令中描述的那样被免除了).

由此命令做出的改变使得 键盘 和/或 鼠标 钩子被安装或移除是正常的.

尽管 Hotkey 命令不能直接启用或禁用脚本中不是它创建的热键, 但在大多数情况下它可以通过创建或启用相同的热键来 覆盖 它们. 这样是否有效取决于下列因素: 1) 在其他脚本中需要被覆盖的热键是否为 钩子热键 (非钩子热键总是可以成功覆盖除非在 Win9x 系统中); 2) 最近启动的热键通常优先于其他脚本中的热键 (因此, 因此如果想要覆盖其他脚本的脚本是最近启动的, 覆盖总是会成功); 3) 此热键的启用或创建是否会重新激活 键盘 或 鼠标 钩子 (如果是, 覆盖将总是成功).

每当脚本含有至少一个热键, 它会变成持续运行的, 这意味着需要使用 ExitApp 而不是 Exit 来终止它. 同时热键脚本自动为 #SingleInstance 的单实例属性除非指定了 #SingleInstance Off.

关于 Hotkey, IfWinXX [, WinTitle, WinText] 的备注

"Hotkey IfWin" 命令允许在脚本运行时创建或修改上下文相关的 热键 (与之相比, #IfWinActive/Exist 指令是由位置决定的并且在脚本启动时生效). 例如:

Hotkey, IfWinActive, ahk_class Notepad
Hotkey, ^!e, MyLabel  ; 创建一个仅在记事本中有效的热键.

使用 "Hotkey IfWin" 可以把所有后续创建或修改的 热键 都变成上下文相关的. 此外, 每个 IfWin 子命令是互斥的; 即只有最近的那个会起作用.

要关闭上下文相关性 (即让后续创建的热键对所有的窗口有效), 指定任一省略了 WinTitle/Text 参数的 IfWin 子命令. 例如: Hotkey, IfWinActive

如果脚本中没有使用过 "Hotkey IfWin", 最近使用的 #IfWin (如果有的话) 将作用于 Hotkey 命令.

通过 IfWin 禁用鼠标或键盘热键后, 则热键会执行它原本的功能; 即如同这样的热键不存在那样被传递到活动窗口. 有两种情况例外: 1) Windows 95/98/Me: 按下一个被 IfWin 禁用的热键不会产生效果 (连原本的功能也失效); 和 2) 游戏杆热键: 尽管 IfWin 有效, 但它不会阻止其他程序探测到按钮的按下.

热键变体 (副本)

只要每次定义时含有不同的 IfWin 条件, 一个特定的热键可以被创建多次. 这被称为 热键变体. 例如:

Hotkey, IfWinActive, ahk_class Notepad
Hotkey, ^!c, MyLabelForNotepad
Hotkey, IfWinActive, ahk_class WordPadClass
Hotkey, ^!c, MyLabelForWordPad
Hotkey, IfWinActive
Hotkey, ^!c, MyLabelForAllOtherWindows

如果有多个热键变体符合触发条件, 仅触发最早创建的那个. 这种情况的例外是全局变体 (不带有 IfWin 条件的那个): 它的优先级总是最低, 仅当其他变体都不触发时它才会被触发.

创建副本热键时, 修饰符 例如 ^!+# 的顺序无关紧要. 例如, ^!c 等同于 !^c. 但是, 按键的拼写必须一致. 例如, Esc 与 Escape 在这种情况下是不一样的 (尽管大小写没有关系). 最后, 任何带有 通配符前缀 (*) 的热键和不带通配符的完全不同; 例如, *F1 和 F1 将拥有各自的变体设置.

关于 IfWin 热键的更多信息, 参见 #IfWin 的一般说明.

相关

Hotkey Symbols, #IfWinActive/Exist, #MaxThreadsBuffer, #MaxThreadsPerHotkey, Suspend, IsLabel(), Threads, Thread, Critical, Gosub, Return, Menu, SetTimer

示例

Hotkey, ^!z, MyLabel return MyLabel: MsgBox You pressed %A_ThisHotkey%. return

; Other examples:
Hotkey, RCtrl & RShift, AltTab ; Makes RCtrl & RShift operate like Alt-Tab.
Hotkey, #c, On ; Re-enables the Win-C hotkey.
Hotkey, $+#c, Off ; Disables the Shift-Win-C hotkey.
Hotkey, ^!a, , T5 ; Changes the hotkey to allow 5 threads.

Hotkey, IfWinActive, ahk_class Notepad Hotkey, ^!c, MyLabelForNotepad ; Creates Ctrl-Alt-C as a hotkey that works only in Notepad.


ListHotkeys

显示当前脚本使用的热键，不论它们的子程序当前是否运行，也不论它们是否使用键盘或者鼠标钩子。

ListHotkeys

此命令相当于在主窗口选择 View->Hotkeys 菜单项。

如果一个热键被 Hotkey 命令禁用，它在列表里将显示为 OFF 或者 PART ("PART" 意味着只有一些热键的变体被禁用)。

如果某个热键子程序当前正在运行，那么会显示那个热键的线程总数。

最后，还会显示热键的类型，其为下列之一：

reg: 热键通过操作系统的 RegisterHotkey() 函数来执行。
reg(no): 和上面一样，但是热键不可用(由于不被支持、被禁用或者被挂起)。
k-hook: 热键通过键盘钩子来执行。
m-hook: 热键通过鼠标钩子来执行。
2-hooks: 热键需要上面提到的两种钩子。
joypoll: 热键通过定期地轮询游戏操纵杆来执行。

相关命令

#InstallKeybdHook, #InstallMouseHook, #UseHook, KeyHistory, ListLines, ListVars, #MaxThreadsPerHotkey, #MaxHotkeysPerInterval

示例

ListHotkeys


Reload

用一个新的脚本实例来替换当前运行的实例。

Reload

这个命令对于频繁改变的脚本很有用。给这个命令指定热键，你可以在编辑器保存改动后轻松地重启脚本。

任何传递给原始脚本的 command-line parameters(命令行参数)不会被传递给新的实例。不要使用 Reload 来传递这样的参数。相应地，使用 Run 命令配合 A_AhkPath 和 A_ScriptFullPath 变量(以及 A_IsCompiled 变量，如果脚本总是用在被编译过的形式)。同样，包含字串 /restart 作为第一个参数(也就是说，在可执行程序名字的后面)，这告诉程序执行和 Reload 相同的动作。也可参见：command line switches and syntax(命令行开关和语法)。

当脚本重启时，它在它的原来的工作目录(实际上是当它被首次载入时的那个目录)载入。也就是说，SetWorkingDir 将不会改变被新的实例使用的工作目录。

如果脚本不能被重载 -- 也许是因为它有一个语法错误 -- 原来的脚本实例会继续运行。因此，Reload 命令后面应该跟着一旦有失败时你想要采取的任何措施(例如一个 return 来退出当前子程序)。要想使原来的实例检测到失败，仿照此例：

Reload
Sleep 1000 ; 如果成功，reload 将会在 Sleep 期间关闭这个实例，因此下一行命令将从不执行。
MsgBox, 4,, 脚本不能被重载。你想打开它来编辑吗？
IfMsgBox, Yes, Edit
return

相关命令

Edit

示例

^!r::Reload  ;指定 Ctrl-Alt-R 作为重启脚本的热键。


#InstallKeybdHook

强制无条件地安装键盘钩子。

#InstallKeybdHook

注意

键盘钩子是为了激活不被 RegisterHotkey(操作系统内置的功能) 支持的 热字串 以及任何键盘 热键 这样的目的而监视键击的。它也支持一些其他特性例如 Input 命令。

在 Windows 95/98/Me 下键盘热键不被支持，因为这些操作系统需要一个必须存在于 DLL 文件内的不同类型的钩子。

AutoHotkey 不会无条件地安装键盘和鼠标钩子因为它们总共消耗至少 500 KB 的内存。因此，键盘钩子通常仅在脚本包含下列条件之一时才会安装： 1) 热字串; 2) 一个或多个需要键盘钩子的 热键 (大多数不需要); 3) SetCaps/Scroll/Numlock AlwaysOn/AlwaysOff; 4) Input 命令，钩子在首次实际使用时安装。

相比之下，#InstallKeybdHook 指令将无条件地安装键盘钩子，它在允许 KeyHistory 显示最近 20 次键击 (为了调试脚本目的) 或者避免需要使用 #HotkeyModifierTimeout 时也许会很有用。

你能通过 KeyHistory 命令或菜单项确定一个脚本是否在使用钩子。你能通过 ListHotkeys 命令或菜单项确定哪个热键正在使用钩子。

这个指令也会使一个脚本 persistent(持久运行)，意味着应该使用 ExitApp 命令来终止脚本。

相关命令

#InstallMouseHook, #UseHook, Hotkey, Input, #Persistent, KeyHistory, Hotstrings, GetKeyState, KeyWait

示例

#InstallKeybdHook


#InstallMouseHook

强制无条件地安装鼠标钩子。

#InstallMouseHook

注意

鼠标钩子是为了激活鼠标 热键 和 帮助热字串 为目的而监视鼠标点击的。在 Windows 95/98/Me 下它不被支持，因为这些操作系统需要一个必须存在于 DLL 文件内的不同类型的钩子。

AutoHotkey 不会无条件地安装键盘和鼠标钩子因为它们总共消耗至少 500 KB 的内存 (但如果键盘钩子已安装，那么安装鼠标钩子仅需要大约 50 KB 额外的内存；反之亦然)。因此，键盘钩子通常仅在脚本包含一个或多个鼠标 热键 时才会安装。它也会为了 热字串 而安装，但可以通过 #Hotstring NoMouse 来禁用。

相比之下，#InstallMouseHook 指令会无条件地安装鼠标钩子，它在允许 KeyHistory 来监视鼠标点击时可能会很有用。

你能通过 KeyHistory 命令或菜单项确定一个脚本是否在使用钩子。你能通过 ListHotkeys 命令或菜单项确定哪个热键正在使用钩子。

这个指令也会使一个脚本 persistent(持久运行)，意味着应该使用 ExitApp 命令来终止脚本。

相关命令

#InstallKeybdHook, #UseHook, Hotkey, #Persistent, KeyHistory, GetKeyState, KeyWait

示例

#InstallMouseHook


#KeyHistory

设置在 KeyHistory 窗口中显示的键盘和鼠标事件的最大数目. 您可以将其设置为 0 来禁用按键历史.

#KeyHistory MaxEvents

参数

MaxEvents 在 KeyHistory 窗口中显示的键盘和鼠标事件的最大数目. (默认为 40, 限制在 500 以内). 指定 0 可以完全禁用按键历史.

备注

因为此设置在脚本开始运行前已经生效了, 所以只需要指定一次 (在脚本的任何位置).

因为每次键击或鼠标点击都是由按下事件和弹起事件组成, 所以 KeyHistory 只显示在这里指定的数目一半的 "完整事件". 例如, 如果脚本含有 "#KeyHistory 50", 那么最多显示 25 次的键击和鼠标点击.

相关

KeyHistory, #NoTrayIcon

示例

#KeyHistory 0      ; 禁用按键历史.
#KeyHistory 100  ; 最多保存 100 事件.


BlockInput

禁用或启用用户通过键盘和鼠标与计算机交互的能力.

BlockInput, Mode

参数

Mode

模式 1: 下列单词之一:

On: 阻止用户与计算机交互 (鼠标和键盘输入都无效).

Off: 重新启用输入.

模式 2 (在 Windows 9x 上无效): 此模式的操作独立于其他两种. 例如, BlockInput On 会继续阻塞输入直到使用了 BlockInput Off, 即使在下面某个单词仍然有效的情况下.

Send: 正在执行 Send 或 SendRaw 命令 (仅对于传统的 SendEvent 模式) 时, 用户的键盘和鼠标输入被忽略. 这样避免了用户的键击扰乱模拟键击流. 当 Send 结束时, 会重新启用输入 (如果之前没有使用 BlockInput On 阻塞的情况下).

Mouse: 正在执行 Click, MouseMove, MouseClick 或 MouseClickDrag 命令 (仅对于传统的 SendEvent 模式) 时, 用户的键盘和鼠标输入被忽略. 这样避免了用户的鼠标移动和点击扰乱模拟鼠标事件. 当鼠标命令结束时, 会重新启用输入 (如果之前没有使用 BlockInput On 阻塞的情况下).

SendAndMouse: 上面两种模式的组合.

Default: 同时关闭 Send 和 Mouse 模式, 但不改变输入阻塞的当前状态. 例如, 如果 BlockInput On 当前有效, 那么使用 BlockInput Default 不会关闭它.

模式 3 (在 Windows 9x 上无效; 需要 v1.0.43.11+): 此模式的操作独立于其他两种. 例如, 如果 BlockInput On 和 BlockInput MouseMove 都有效时, 鼠标移动会被阻塞直到这两者被同时关闭.

MouseMove: 鼠标光标不会随用户对鼠标的物理移动而移动 (DirectInput 应用程序可能是个例外). 脚本中首次使用此命令时, 会安装 鼠标钩子 (在还没有安装时). 同时, 脚本变得 持续运行的, 意味着应该使用 ExitApp 结束脚本. 鼠标钩子会一直保持加载状态, 直到下一次使用 Suspend 或 Hotkey 命令, 此时如果没有任何热键或热字串需要那么它会被移除 (请参见 #Hotstring NoMouse).

MouseMoveOff: 允许用户移动鼠标光标.

备注

比起 BlockInput, 优先考虑使用 SendMode Input 或 SendMode Play 通常会更好, 这样键击和鼠标点击会变得不可中断. 这是因为与 BlockInput 不同, 这些模式不会丢弃发送期间用户输入的内容; 作为替代, 这些键击被缓冲起来在之后发送. 不使用 BlockInput 也避免了下一段落所描述的需要解决的粘滞按键问题.

如果在用户按住按键时启用 BlockInput, 可能会导致这些键 "卡住". 通过等待这些按键释放后才启用 BlockInput 可以避免此问题, 与本例一样:

^!p::
KeyWait Control  ; 等待按键释放.  为每个热键修饰符使用一次 KeyWait 命令.
KeyWait Alt
BlockInput On
; ... 发送键击和鼠标点击 ...
BlockInput Off
return

每当发送 ALT 事件时, 输入阻塞会自动和临时禁用 (之后重新启用).

下表显示了 BlockInput 在不同 Windows 版本上表现的多样性; 然而由于 Windows API 的特性, 在任何平台中按下 Ctrl+Alt+Del 都将重新启用输入.

操作系统 | "BlockInput" 效果
Windows 95 | 无效.
Windows 98/Me | 阻塞用户输入且 AutoHotkey 不能 模拟输入.
Windows NT 4 (不含 ServicePack 6) | 无效.
Windows NT 4 (含 ServicePack 6) | 阻塞用户输入, 不过 AutoHotkey 可以模拟键击和鼠标点击.
Windows 2000/XP | 阻塞用户输入, 不过 AutoHotkey 可以模拟键击和鼠标点击.

Windows 98/Me: 尽管在这些操作系统上执行 BlockInput 期间脚本不能发送键击和鼠标点击, 不过类似 WinMove 这样的命令仍然有效. ControlSend 可能也会起作用.

钩子热键 的某些类型在 BlockInput 启用时仍然可以被触发. 例子包括 "MButton" (鼠标钩子) 和 "LWin & Space" (含有除修饰符 "$#" 外的明确前缀的键盘钩子).

当脚本关闭时会自动重新启用输入.

相关

SendMode, Send, Click, MouseMove, MouseClick, MouseClickDrag

示例

if A_OSType <> WIN32_WINDOWS ; 即不是 Windows 9x.
    BlockInput, on
Run, notepad
WinWaitActive, Untitled - Notepad
Send, {F5} ; 粘贴时间和日期
BlockInput, off


ControlSend / ControlSendRaw

向一个窗口或控件发送模拟键击。

ControlSend [, Control, Keys, WinTitle, WinText, ExcludeTitle, ExcludeText]
ControlSendRaw: 参数同上。

Parameters

Control

可以是控件的名称/文本或 ClassNN (控件的 classname(类名)和序号)，它们都可以通过 Window Spy 来确定。当使用名称/文本时，matching behavior(匹配模式)通过 SetTitleMatchMode 决定。如果此参数为空或省略，目标窗口的顶端控件将被使用。如果这个参数为 ahk_parent，键击将会被直接发送到控件的父窗口 (见实例 Automating Winamp)。

要对一个控件的 HWND (窗口句柄)进行操作，将 Control 参数留空并为 WinTitle 参数指定 ahk_id %ControlHwnd% (这样即使当 DetectHiddenWindows 是 Off 状态，它也能对隐藏的控件起作用)。一个控件的 HWND 往往由 ControlGet Hwnd 、MouseGetPos 或 DllCall 取得。
Keys

一连串要发送的按键(详细请见 Send 命令)。如要发送一个原义的逗号，请进行 escape(转义) (例：`, )。键击被发送的速率由 SetKeyDelay 来决定。

与 Send 命令不同的是，鼠标点击不能通过 ControlSend 来发送，请用 ControlClick 。
WinTitle | 目标窗口的标题或副标题(匹配模式由 SetTitleMatchMode 决定)。如果此参数和后面的3个参数被省略，Last Found Window(最近找到的窗口) 将被使用。如果此参数是字母 A 并且后面的三个参数被省略，激活的窗口将被使用。要使用一个窗口类，指定 ahk_class 确切的类名(通过 Window Spy 显示)。要使用一个 process identifier (PID)(进程标识符)，指定 ahk_pid %包含PID的变量% 。要使用一个 window group(窗口组)，指定 ahk_group GroupName 。要使用一个窗口的 unique ID number(唯一标识符编号)，指定 ahk_id %包含ID的变量% 。通过指定 multiple criteria(多个条件) 缩小搜索范围。 例如：My File.txt ahk_class Notepad
WinText | 如果用到，此参数必须是目标窗口的一个单独 text element(文本对象)的 substring(子字串) (像内置的 Window Spy 工具显示的一样)。如果 DetectHiddenText 是 ON 的状态，隐藏的文本对象将被探测。
ExcludeTitle | 标题含有此参数值的窗口将不被考虑。
ExcludeText | 文本含有此参数值的窗口将不被考虑。

ErrorLevel

如果遇到一个问题 ErrorLevel 设为 1 ，否则是 0 。

Remarks

ControlSendRaw 命令准确地按照键击本身在Keys 参数中显示的那样发送，而不是将 {Enter} 转换成一个 ENTER 键击，^c 转换成 Control-C 键击等等。

如果 Control 参数被省略，或目标窗口自身没有控件时，该命令将尝试通过发送到它的顶端控件(通常是正确的那一个)来直接发送到目标窗口。当一个窗口自身根本不带有控件或无所谓发送到哪个控件时，这么做是非常有用的。

默认情况下，修饰键(Control，Alt，Shift，和 Win 键) 将通常那样的通过 Send 命令被发送。这样可以让命令提示符和其他控制台窗口正确地检测到大写字母，键控字符等等。同时这样也提高了在其他方面上的可靠性。

然而，在某些情况下这些修饰键事件可能会干扰当前激活的窗口，尤其当一个 ControlSend 命令正在执行或 Alt 键正被发送(因为 Alt 键激活了当前激活窗口的菜单栏)，而用户也正在活跃地打字的时候。通过明确地发送修饰键的按下和弹起事件可以避免这种情况的发生，如这个例子：
ControlSend, Edit1, {Alt down}f{Alt up}, 无标题 - 记事本

以上这种方式同时使得修饰键(Control/Alt/Shift/Win)的发送在工作站被锁定时(被登录提示框保护时)也生效。

当正在对一个控制台窗口如命令提示符使用 ControlSend 命令时，应避免使用 BlockInput 命令。这是因为，这么做会阻碍大小写按钮和修饰键(比如 Control 键)的正常工作。

SetKeyDelay 命令设置的数值决定按键被发送的速度。如果目标窗口无法正确可靠地接受键击，请尝试通过增加 SetKeyDelay 命令的第二个参数来增加按键时长，如这些例子：
SetKeyDelay, 10, 10
SetKeyDelay, 0, 10
SetKeyDelay, -1, 0

如果目标控件是一个 Edit(输入框) 控件(或某些类似的)，以下命令以下的代码通常会比 ControlSend 更可靠并且更快：
Control, EditPaste, 这些文本将会被插入到光标处。, ControlName, WinTitle
ControlSetText, ControlName, 这些文本将会完全替换掉已存在的文本。, WinTitle

ControlSend 命令通常并不能很好地操控窗口的菜单栏。要解决这个问题，使用 WinMenuSelectItem 命令。如果由于菜单栏的类型导致这么做并不可行，您可以尝试通过学习 SendMessage Tutorial(发送消息指南) 来了解消息以操控需要的菜单项。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

Related

SetKeyDelay, Escape sequences (e.g. `%) , Control, ControlGet, ControlGetText, ControlMove, ControlGetPos, ControlClick, ControlSetText, ControlFocus, Send, Automating Winamp

Examples

ControlSend, Edit1, 这是一行在记事本窗口中的文本。,  无标题
SetTitleMatchMode, 2
ControlSend, , abc, cmd.exe  ; 直接发送到命令提示符窗口。


GetKeyState

检查键盘按键或鼠标/游戏杆按钮是否按下或放开. 也可以获取游戏杆的状态.

GetKeyState, OutputVar, KeyName [, Mode]
KeyIsDown := GetKeyState("KeyName" [, "Mode"])

参数

OutputVar

用于保存获取的按键状态的变量名称, 它的值当按下时是D, 弹起时是U (不过 GetKeyState() 函数当按下时返回 true (1), 弹起时返回 false (0)). 如果按键的状态无法识别, 此变量将为空.

关于游戏杆的下面几点说明:

1) 对于像 JoyX 这样的游戏杆轴, OutputVar 将设置为介于 0 和 100 之间的浮点数, 作为该轴活动范围的百分率, 表明游戏杆的位置. 可以通过 SetFormat 改变数字的格式. 此 测试脚本 可以用来分析游戏杆.

2) 当 KeyName 为 JoyPOV 时, 获取的值将介于 0 和 35900 之间. 许多游戏杆使用下列近似的 POV 值:
-1: 不报告
0: 向前 POV
9000 (例如 90 度): 向右 POV
27000 (例如 270 度): 向左 POV
18000 (例如 180 度): 向后 POV
KeyName

此参数可以是键盘中任何的单个字符或来自 按键列表 中键名的其中一个, 例如鼠标/游戏杆 (尽管在 Windows 95/98/Me 系统中通常无法检测到鼠标按钮的状态). 示例: B, 5, LWin, RControl, Alt, Enter, Escape, LButton, MButton, Joy1.

或者, 可以指定一个显式的虚拟按键代码例如 vkFF. 只有在一个按键没有指定名称这样少见的情况下, 这种方法才有用.它的虚拟按键代码可以通过 按键列表页面 底部的步骤来确定.
Mode

当获取游戏杆状态时, 此参数被忽略.

如果省略, 默认的模式是获取按键的逻辑状态. 这是操作系统和活动窗口所认为的按键处于的状态, 但不一定和它的物理状态一样.

或者, 可以指定这些字母的其中一个:

P: 获取物理状态 (例如用户是否实际按住了按键). 在 Windows Me/98/95 系统下, 一个按键的物理状态 (Mode = P) 总是和它的逻辑状态一致. 在 Windows NT/2000/XP 或更高版本的系统中, 如果没有安装键盘和/或鼠标钩子的话, 按键或鼠标按钮的物理状态通常和逻辑状态一致(有时逻辑状态可能比物理状态滞后). 在安装了钩子的情况下, 它将准确反映出用户是否按下了按键或鼠标按钮(只要在脚本正在执行时它被按下).您可以通过 KeyHistory 命令或菜单项确定您脚本中是否使用了钩子. 通过添加 #InstallKeybdHook 和/或 #InstallMouseHook 指令到脚本中您可以强制安装钩子.

T: 获取切换状态 (仅对于可以切换的按键才有效例如 Capslock, Numlock, Scrolllock, 和 Insert). 获取的值为 D 表明按键是打开的, 而 U 表明它是关闭的 (不过 GetKeyState() 函数当打开时返回 true (1), 关闭时返回 false (0)).

获取 Insert 按键的切换状态可能只工作在 Windows 2000/XP 或更高版本的系统中.

在 Windows 9x 系统中, 获取切换状态可能不太可靠. 例如, 按下按键后, 可能需要等到显示了一个和脚本关联的窗口例如 MsgBox 后, 才能正确获取它的新状态.

备注

为了等待按键或鼠标/游戏杆按钮进入一种新的状态, 通常用 KeyWait 来代替 GetKeyState 的循环.

带有不常见键盘驱动的系统更新按键的状态可能比较慢, 尤其是像 Capslock 这样的按键的开关状态. 在按键状态改变后立即对其状态进行检查的脚本可以提前使用 Sleep 命令, 以使系统有时间更新按键的状态.

关于使用 GetKeyState 并与游戏杆有关的例子, 请参看 游戏杆重映射页面 和 游戏杆到鼠标的映射脚本.

相关

GetKeyState(), KeyWait, Key List, Joystick remapping, KeyHistory, #InstallKeybdHook, #InstallMouseHook

示例

; Basic examples:
GetKeyState, state, RButton  ; Right mouse button.
GetKeyState, state, Joy2  ; The second button of the first joystick.

GetKeyState, state, Shift
if state = D
    MsgBox At least one Shift key is down.
else
    MsgBox Neither Shift key is down.

GetKeyState, state, CapsLock, T ;  D if CapsLock is ON or U otherwise.
state := GetKeyState("Capslock", "T")  ; True if CapsLock is ON, false otherwise.

; Remapping example (this is only for illustration because it would be easier to use
; the built-in remapping feature):
; In the following hotkey, the mouse button is kept held down while NumpadAdd is
; down, which effectively transforms NumpadAdd into a mouse button. This method
; can also be used to repeat an action while the user is holding down a key or button:
*NumpadAdd::
MouseClick, left,,, 1, 0, D  ; Hold down the left mouse button.
Loop
{
    Sleep, 10
    GetKeyState, state, NumpadAdd, P
    if state = U  ; The key has been released, so break out of the loop.
        break
    ; ... insert here any other actions you want repeated.
}
MouseClick, left,,, 1, 0, U  ; Release the mouse button.
return

; Example: Make joystick button behavior depend on joystick axis position.
joy2::
GetKeyState, joyx, JoyX
if joyx > 75
    MsgBox Action #1 (button pressed while joystick was pushed to the right).
else if joyx < 25
    MsgBox Action #2 (button pressed while joystick was pushed to the left).
else
    MsgBox Action #3 (button pressed while joystick was centered horizontally).
return

; See the joystick remapping page and the Joystick-To-Mouse script for other examples.


KeyHistory

显示脚本信息和最近键击和鼠标点击的历史.

KeyHistory

备注

使用此命令等同于在主窗口中选择 "View->Key history" 菜单项.

要禁用按键历史, 请在脚本的任何位置指定下面这行:
#KeyHistory 0

还可以使用 #KeyHistory 来改变显示的事件的最大数目.

此特性旨在帮助 调试脚本和热键. 通过使用 按键列表 页面底部描述的步骤, 它还可以用来检测非标准键盘按键的扫描码 (知道按键的扫描码就可以把这个按键用在热键中).

滚轮事件 (WheelDown, WheelUp, WheelLeft 和 WheelRight) 的虚拟键 (VK) 是一些在 AutoHotkey 外没有任何意义的占位符值. 此外, 滚轮事件的扫描码实际上是滚轮转动的格数 (通常为 1).

如果脚本没有安装 键盘钩子, 那么 KeyHistory 窗口将只显示由脚本自己 (即不包含用户的) 生成的按键事件. 如果脚本没有安装 鼠标钩子, 那么将不显示鼠标按钮事件. 如果您的脚本使用了其中的一种钩子, 那么可以通过脚本主窗口 (可通过托盘图标的 "Open" 菜单打开) 的菜单项 "View->Key History" 找到它. 通过添加下面两行语句中的任何一行或同时添加两行到脚本中, 您可以强制安装钩子:
#InstallKeybdHook
#InstallMouseHook

相关

#KeyHistory, #InstallKeybdHook, #InstallMouseHook, ListHotkeys, ListLines, ListVars, GetKeyState, KeyWait

示例

KeyHistory ; 在窗口中显示历史信息.


KeyWait

等待一个按键或鼠标/操纵杆按钮被松开或者按下。

KeyWait, KeyName [, Options]

参数

KeyName

这个名称可以是键盘上的几乎任意单独字符或者是 按键列表 里的某个按键名称，例如一个鼠标/操纵杆按钮。不支持除了操纵杆的按钮外的操纵杆属性。

也可以指定一个显式的虚拟按键代码例如 vkFF 。当一个按键没有名称并且在按下时生成不可见的字符这种罕见的情况时，这会很有用。它的虚拟按键代码可以通过参照 按键列表页面 底部的步骤来确定。

Options

如果此参数为空，命令将无限期地等待用户自己松开指定的按键或鼠标/操纵杆按钮。不过，如果没有安装 键盘钩子 并且 KeyName 是通过例如 Send 命令人为地松开的一个键盘按键，按键将被视为物理地松开了。当没有安装 鼠标钩子 时，对鼠标按键来说也是一样的。

Options: 一个下列单个或多个字母组成的字符串(可任意顺序，在中间的空格是可选的):

D: 等待按键被按下。

L: 检测按键的逻辑状态，这是操作系统和激活的窗口相信按键会一直处于的状态(不一定和物理的状态一样)。译注：按键被检测时所处的状态会成为它永远的状态而不管之后是否物理地改变。此选项忽略操纵杆按钮。

T: 超时(例如，T3)。在判定超时并设置 ErrorLevel 为 1 之前要等待的秒数。如果按键或按钮达到了指定的状态，命令不会等到超时期满。反而，它将马上设置 ErrorLevel 为 0 并且脚本将继续执行。

超时的参数值可以是一个浮点数例如 2.5 ，但不能是一个十六进制的数值例如 0x03 。

ErrorLevel

如果命令超时 ErrorLevel 将设为 1 ，反之为 0 。

注意

在 Windows Me/98/95 下，一个按键或鼠标按键的物理状态将一直和它的逻辑状态一致。

在 Windows NT/2k/XP 以及之后版本，一个按键或鼠标按键的物理状态通常将和逻辑状态一致，除非安装了键盘和/或鼠标钩子，这种情况下它会精确地反映逻辑状态而无论用户是否物理地按住了按键。通过 KeyHistory 的命令或菜单项你能确定你的脚本是否在使用钩子。你能通过给脚本添加 #InstallKeybdHook 和 #InstallMouseHook 指令来强制安装任何一个或两个钩子。

当命令处于一个等待状态时，新的 threads(线程) 能通过 hotkey, 自定义菜单项 或 timer 来启动。

要等待两个或多个按键被松开，请连续地使用 KeyWait 。例如：

KeyWait Control  ; 等待 Control 和 Alt 两个都被松开。
KeyWait Alt

要等待一系列按键中的某个按键被按下，请看 Input 命令的示例部分。

相关命令

GetKeyState, Key List, Input, KeyHistory, #InstallKeybdHook, #InstallMouseHook, ClipWait, WinWait

示例

; 例子 #1: 基本用法：
KeyWait, a  ; 等待按键 A 被松开。
KeyWait, LButton, D  ; 等待鼠标左键被按下。
KeyWait, Joy1, D T3  ; 等待首个操纵杆按钮在 3 秒内按下。
KeyWait, LAlt, L  ; 等待左边的 Alt 键被逻辑地松开。

; 例子 #2: 一个简单的热键：
~Capslock::
KeyWait, Capslock  ; 等待用户物理地松开它。
MsgBox 你按了并且松开了 Capslock 键。
return

; 例子 #3: 重映射一个按键或鼠标按钮 (这仅是为了阐述，因为使用 内置重映射特性 会更加简单):
; 当 NumpadAdd 按下时鼠标左键是按住的，这实际上把 NumpadAdd 变成了鼠标左键。

*NumpadAdd::
MouseClick, left,,, 1, 0, D  ; 按住鼠标左键。
KeyWait, NumpadAdd  ; 等待按键被松开。
MouseClick, left,,, 1, 0, U  ; 松开鼠标按键。
return

; 例子 #4: 检测何时一个按键被两次按下 (近似于双击)。
; 当你按住 RControl 键要修饰另一个按键时，KeyWait 被用来阻止键盘的自动重复特性创造出一个不需要的两次按键。
; 它通过依赖于 #MaxThreadsPerHotkey 处于它的默认设置 1 来保持住热键的线程运行从而阻止自动重复。
; 注意：在 SetTimer 页面的底部有一个更复杂的脚本来辨别单次、两次和三次按键之间的区别。
~RControl::
if (A_PriorHotkey <> "~RControl" or A_TimeSincePriorHotkey > 400)
{
    ; 在按键之间间隔太久，所以这不是一个两次按键。
    KeyWait, RControl
    return
}
MsgBox 你两次按击了右边的 control 键。
return


Input

等待用户输入一个字符串 (不支持Windows 9x，在Windows 9x下它什么都不处理).

Input [, OutputVar, Options, EndKeys, MatchList]

参数

OutputVar

用来保存用户输入文本的变量 (默认情况下，手工的输入也被保存下来)。

如果这个参数和其他参数被省略，那么任何在其他 thread (线程)中执行的 Input 将被终止，终止后那个 Input 的 ErrorLevel 会被赋值为 NewInput。 而当前命令的 ErrorLevel 会被设置为 0 (如果它终止了一个先前的输入) 或 1 (如果它在先前没有终止输入)。

OutputVar 本身并不记录击键，而是记录由活动窗口的 键盘布局/键盘语言 击键产生的字符。 所以，不产生字符的击键 (比如 PageUp 和 Escape) 并没有被记录下来。(尽管它们可以被下面的 EndKeys 参数识别出来)。

空白字符会被逐个记录下来，比如 TAB (`t) 。 回车(ENTER)被记录为换行 (`n).
Options

由下列字母组成的字符串(零个，一个或者多个，可任意顺序，在中间的空格是可选的):

B: 忽略退格键。一般而言，按下退格键会删除最后一个输入的字符。 注意：如果输入的文本是可见的(比如在一个编辑器中)，用户在其中使用方向键或其他方式操纵了提示输入字符串的光标后，退格键依然会删除最后一个字符而不是光标前面的字符。

C: 区分大小写。一般而言，MatchList 并不区分大小写(在 1.0.43.03 版本之前, 只有字母 A-Z 被认为是有大小写的，而诸如 ü/Ü 的字母被认为没有).

I: 忽略所有由 AutoHotkey 脚本产生的字符，比如 SendEvent 命令。然而，不论此选项是否开启，由 SendInput 和 SendPlay 方法产生的输入总是被忽略。

L: 限制文本长度(比如 L5)。设置输入文本所允许的最大长度。如果文本到达了这个长度，输入会被终止， ErrorLevel 会被赋值为 Max 。但是如果文本和 MatchList 中某个词组符合的话， ErrorLevel 会被赋值为 Match。如果这个选项没有开启，那么文本默认的长度是16383，这也是文本的绝对最大长度。

M: 如果修改过的从 Control-A 到 Control-Z 的击键对应于某个ASCII码的话，那么它就可以被识别并被转录。试试下面这个识别 Control-C 的例子：

Transform, CtrlC, Chr, 3 ; Store the character for Ctrl-C in the CtrlC var.
Input, OutputVar, L1 M
if OutputVar = %CtrlC%
    MsgBox, You pressed Control-C.
ExitApp

注意：从 Ctrl-A 到 Ctrl-Z 的字符对应于 Chr(1) 到 Chr(26)。此 M 选项可能会导致一些快捷键在输入的过程中产生意料之外的效果(比如 Ctrl-LeftArrow )

T: 设置超时 (比如 T3)。 设置等待输入文本的秒数，到时后终止 Input 并将 ErrorLevel 赋值为 Timeout。如果 Input 超时， OutputVar 会被赋值为用户在超时以前输入的文本。这个参数可以被设为浮点数，比如 2.5。

V: 可见性。一般而言，用户的输入是阻塞的(隐藏在操作系统之后)。使用这个选项来发送用户的击键至活动窗口。

*: 通配符(寻找所有地方)。一般而言，用户输入的文本必须完全匹配 MatchList 中的一个词组来产生一个匹配。使用这个选项来通过搜索完整长度的字符串来找到一个匹配。
EndKeys

按键的列表(零个，一个或者多个)，其中任何一个按下都会终止 Input 的输入。(EndKey 本身不会被写入 OutputVar)。但一个 Input 通过这种方式被终止后， ErrorLevel 会被赋值为 EndKey 接一个 冒号 再接 EndKey 的值。例如：
EndKey:.
EndKey:Escape

这个 EndKey 列表使用一种和 Send 命令相仿的格式。比如，这个列表被设置为 {Enter}.{Esc} 后，按下 ENTER, 句号 (.), 或者 ESCAPE 之后都会终止输入。要使用大括号来终止输入，则需要将它们指定为 {{} 和/或 {}} 。

如果想要使用 Control, Alt, 或者 Shift 来作为输入的终止键，则必须指出它是左边或者是右边的键，比如设置为 {LControl}{RControl} 而不是 {Control}。

尽管譬如 Control-C (^c) 之类用做修改的键不被支持，一些需要 shift 键被按下的字符 -- 比如这些标点符号 ?!:@&{} -- 已经在 1.0.14+ 的版本中被支持了。

明确的虚拟键也可以被指定为输入的终止键，比如 {vkFF} 。这在一些罕见的情况下会很有用，比如一个键没有名字而且在按下的时候不产生可见的字符。这些虚拟键的键码可以通过 key list page 页面下方的步骤来确定。
MatchList

一个由逗号分隔的关键词组的列表，其中的任何一个都可以终止一个输入 (在这种情况下 ErrorLevel 被赋值为 Match)。为了产生一个匹配，用户输入的文本必须完全匹配该列表中的某个词组 (除非 * 选项 被选择)。另外， 任何在分隔逗号旁边的空格或者跳格(tabs)都非常重要，这意味着它们也是匹配字符串中的一部分。例如，如果 MatchList 是 "ABC , XYZ "，那么用户在输入 ABC 后输入空格，或者在空格后输入 XYZ 都会产生一个匹配。

两个连续的逗号在匹配词组中产生一个字面上的逗号。比如，下面的列表中，在第一个字符串的末尾会加上一个字面上的逗号： "string1,,,string2"。同样的，下面的列表中只包含一个内部有一个逗号的词组： "single,,item"。

因为 MatchList 中的每一项并不是独立的参数，所以这个列表可以被全部包含在一个变量里。实际上，如果这个列表的长度超过了16383，那么它的部分或者全部就必须存储在一个变量里，因为16383是任何一个脚本一行中所能存储的最大长度。例如， MatchList 可以由 %List1%,%List2%,%List3% 组成 -- 而其中每一个变量中保存了用来匹配字符串的词组的一个大的子列表。

ErrorLevel

1 or 0 | 如果这个命令没有使用任何参数，那么 ErrorLevel 会被赋值为 0 (如果它成功终止了一个先前的输入) 或 1 (如果没有输入需要处理)。
NewInput | 这个命令被另外一个使用 Input 命令的 thread (线程)所中断。
Max | 输入达到了所允许的最大的字符串长度并且这个输入没有匹配到 MatchList 中的任何一项。
Timeout | 输入超时。
Match | 输入和 MatchList 中的某一项匹配。
EndKey:name | 任意一个用来终止 Input 的 EndKeys 被按下。在这种情况下， ErrorLevel 会被设置为 EndKey 接一个 冒号 再接 EndKey 的值(不带大括号)，比如： EndKey:Enter, EndKey:Escape, 等等。

注意

如果在使用这个命令的时候，另外一个 thread (线程)中已经有一个 Input 在执行，那么那个线程中的 Input 会被终止且 ErrorLevel 会被赋值为 NewInput。在这之后(如果这个命令给出了参数)，新的 Input 命令才开始执行。

在一个 Input 执行的过程中，诸如 custom menu items 和 timed subroutines 之类的新的 threads (线程)依旧可以被创建。类似的，如果 Input 是 visible (可见的)，键盘的 hotkeys 也依然有效。如果 Input 不可见，那就只有 hook hotkeys 可以被触发。

在一个脚本第一次使用这个命令时，keyboard hook (键盘钩子)会被加载(如果它还没有加载)。另外，这个脚本会变成 persistent (持久的)，这意味着需要使用 ExitApp 来停止这个脚本。键盘钩子会保持加载状态直到下一次 Suspend 或 Hotkey 命令的使用，到那时它就会被移除，除非其它的热键或热字符串仍然需要使用它。

如果您在使用多种语言或着多种键盘布局，那么 Input 会使用当前活动窗口的键盘布局而不是脚本所使用的(无论 Input 是否 visible (可见))。但是，在 1.0.44.03 之前的版本中使用的是脚本所使用的布局。

一般情况下， hotstrings 比 Input 命令更容易使用，虽然它不是很灵活。

Input 在 Windows 9x 下什么都不做。(连 ErrorLevel 和 OutputVar 也不改变)。如果要在 Windows 9x 下检测输入，请使用 A_OSType 。

相关命令

KeyWait, Hotstrings, InputBox, #InstallKeybdHook, Threads, if var in/contains MatchList

示例

; Wait for the user to press any key.  Keys that produce no visible character -- such as
; the modifier keys, function keys, and arrow keys -- are listed as end keys so that they
; will be detected too.
Input, SingleKey, L1, {LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause}

; This is a working hotkey example.  Since the hotkey has the tilde (~)
; prefix, its own keystroke will pass through to the active window
; (except on Win9x).  Thus, if you type [btw (or one of the other match
; phrases) in any editor, the script will automatically perform an
; action of your choice (such as replacing the typed text):

~[::
Input, UserInput, V T5 L4 C, {enter}.{esc}{tab}, btw,otoh,fl,ahk,ca
if ErrorLevel = Max
{
    MsgBox, You entered "%UserInput%", which is the maximum length of text.
    return
}
if ErrorLevel = Timeout
{
    MsgBox, You entered "%UserInput%" at which time the input timed out.
    return
}
if ErrorLevel = NewInput
    return
IfInString, ErrorLevel, EndKey:
{
    MsgBox, You entered "%UserInput%" and terminated the input with %ErrorLevel%.
    return
}
; Otherwise, a match was found.
SetKeyDelay, -1  ; Most editors can handle the fastest speed.
if UserInput = btw
    Send, {backspace 4}by the way
else if UserInput = otoh
    Send, {backspace 5}on the other hand
else if UserInput = fl
    Send, {backspace 3}Florida
else if UserInput = ca
    Send, {backspace 3}California
else if UserInput = ahk
    Run, www.autohotkey.com
return


Send/SendRaw/SendInput/SendPlay/SendEvent: Send keys & clicks

Send / SendRaw / SendInput / SendPlay / SendEvent: 发送按键和点击

发送模拟键击和鼠标点击到 活动 窗口.

Send Keys
SendRaw Keys
SendInput Keys
SendPlay Keys
SendEvent Keys

参数

Keys 要发送的按键序列. 和其他命令一样, 在首个参数前的逗号可以省略.

原始模式: SendRaw 命令会准确按照键击显示的那样发送, 而不把 {Enter} 转换成 ENTER 键击, 把 ^c 转换成 Control-C 等. 要在 SendInput, SendPlay 和 SendEvent 中使用原始模式, 把 {Raw} 写在需发送的按键序列前面; 例如: SendInput {Raw}abc

正常模式: 不处于原始模式时, 下列字符被看成是修饰键 (这些修饰键仅影响紧跟着的下一个键):

!: 发送一个 ALT 键击. 例如, Send This is text!a 将发送按键序列 "This is text" 并接着按下 ALT+a. 注意: 在某些程序中 !A 和 !a 会产生不同的效果. 这是由于 !A 按了 ALT+SHIFT+A 而 !a 按了 ALT+a. 如果不确定, 则使用小写.

+: 发送一个 SHIFT 键击. 例如, Send +abC 会发送文本 "AbC", 而 Send !+a 会按下 ALT+SHIFT+a.

^: 发送一个 CONTROL 键击. 例如, Send ^!a 会按下 CTRL+ALT+a, 而 Send ^{Home} 则发送 CONTROL+HOME. 注意: 在某些程序中 ^A 和 ^a 会产生不同的效果. 这是由于 ^A 按了 CONTROL+SHIFT+A 而 ^a 按了 CONTROL+a. 如果不确定, 则使用小写.

#: 发送一个 WIN 键击, 因此 Send #e 会按住 Windows 接着按下字母 "e".

SendInput 和 SendPlay [v1.0.43+]: SendInput 和 SendPlay 与 Send 使用相同的语法但通常更快更可靠. 此外, 它们缓存了发送期间任何物理的键盘或鼠标活动, 这样避免了在发送时夹杂用户的键击. 可以使用 SendMode 让 Send 和 SendInput 或 SendPlay 具有相同的功能. 关于每种模式的更多细节, 参见下面的 SendInput 和 SendPlay.

SendEvent [v1.0.43+]: SendEvent 和 1.0.43 之前版本的 Send 命令使用相同的方法发送键击. 键击发送的频率由 SetKeyDelay 决定. 默认情况下, Send 和 SendEvent 是含义一样的; 但通过 SendMode 可以让它变成和 SendInput 或 SendPlay 一样.

按键名称: 下面的表格列出了可以发送的特殊按键 (每个按键名称必须用大括号包围):

按键名称 | 生成的键击
{F1} - {F24} | 功能键. 例如: {F12} 表示 F12 键.
{!} !
{#} #
{+} +
{^} ^
{{} {
{}} }
{Enter} | 主键盘上的 ENTER 键
{Escape} 或 {Esc} | ESCAPE
{Space} | SPACE (仅对于需发送的按键序列开始或末尾的空格才需要这样表示 -- 序列中间的空格是原义的)
{Tab} | TAB
{Backspace} 或 {BS} | Backspace
{Delete} 或 {Del} | Delete
{Insert} 或 {Ins} | Insert
{Up} | 主键盘上的向上方向键
{Down} | 主键盘上的向下方向键
{Left} | 主键盘上的向左方向键
{Right} | 主键盘上的向右方向键
{Home} | 主键盘上的 Home 键
{End} | 主键盘上的 End 键
{PgUp} | 主键盘上的 Page-up 键
{PgDn} | 主键盘上的 Page-down 键
{CapsLock} | CapsLock (在 NT/2k/XP 系统上使用 SetCapsLockState 更可靠). 发送 {CapsLock} 前可能要求 SetStoreCapslockMode Off.
{ScrollLock} | ScrollLock (也请参见: SetScrollLockState)
{NumLock} | NumLock (也请参见: SetNumLockState)
{Control} or {Ctrl} | CONTROL (技术信息: 发送中性的虚拟按键和左边的扫描代码, 即在 vkXXscYYY 中, XX 为中性的而 YYY 为左边的扫描代码)
{LControl} or {LCtrl} | 左 CONTROL 键 (技术信息: 在 Win9x 中等同于 CONTROL, 但在 NT/2k/XP 系统中它发送左边的虚拟按键而不是中性的)
{RControl} or {RCtrl} | 右 CONTROL 键
{Control Down} 或 {Ctrl Down} | 按住 CONTROL 键直到发送 {Ctrl Up}. XP/2000/NT: 要按住左边或右边的键, 请使用 {RCtrl Down} 和 {RCtrl Up}.
{Alt} | ALT (技术信息: 发送中性的虚拟按键和左边的扫描代码)
{LAlt} | 左 ALT 键 (技术信息: 在 Win9x 中等同于 ALT, 但在 NT/2k/XP 系统中它发送左边的虚拟按键而不是中性的)
{RAlt} | 右 ALT 键 (或 AltGr, 取决于键盘布局)
{Alt Down} | 按住 ALT 键直到发送 {Alt Up}. XP/2000/NT: 要按住左边或右边的键, 请使用 {RAlt Down} 和 {RAlt Up}.
{Shift} | SHIFT (技术信息: 发送中性的虚拟按键和左边的扫描代码)
{LShift} | 左 SHIFT 键 (技术信息: 在 Win9x 中等同于 SHIFT, 但在 NT/2k/XP 系统中它发送左边的虚拟按键而不是中性的)
{RShift} | 右 SHIFT 键
{Shift Down} | 按住 SHIFT 键直到发送 {Shift Up}. XP/2000/NT: 要按住左边或右边的键, 请使用 {RShift Down} 和 {RShift Up}.
{LWin} | 左 Windows 键
{RWin} | 右 Windows 键
{LWin Down} | 按住左 Windows 键直到发送 {LWin Up}
{RWin Down} | 按住右 Windows 键直到发送 {RWin Up}
{AppsKey} | Windows App 键 (调用右键点击或上下文菜单)
{Sleep} | 电脑 SLEEP 键.
{ASC nnnnn}

发送 ALT+nnnnn 小键盘上的按键组合, 可以用来生成键盘上不存在的特殊字符. 要生成 ASCII 字符, 指定一个介于 1 和 255 之间的数字. 要生成 ANSI 字符 (在多数语言中的标准), 指定一个介于 128 和 255 之间的数字, 但需要在数字前加上一个前导零, 例如 {Asc 0133}.

要生成 Unicode 字符, 指定一个介于 256 和 65535 之间的数字 (不带前导零). 但是, 有些应用程序不支持这种情况. 因此, 为了更可靠和更简便的发送长的 Unicode 字符串, 使用 "Transform Unicode".
{U+nnnn}

[AHK_L 24+]: 发送一个 Unicode 字符, 其中 nnnn 为不包括 0x 前缀的字符的十六进制值. 请注意 AutoHotkey_L 的 Unicode 版本中, 如果脚本文件保存为 UTF-8 或 UTF-16 时文本中可以直接包含 Unicode 字符.

如果这个字符没有映射为一个虚拟按键代码, 则使用 SendInput() 或 WM_CHAR 发送这个字符而当前的发送模式无效.

{vkXX}
{scYYY}
{vkXXscYYY}

发送一个虚拟按键为 XX 且扫描码为 YYY 的键击. 例如: Send {vkFFsc159}. 如果省略了 sc 或 vk 部分, 则会发送最适当的值.

XX 和 YYY 是十六进制的值, 通常可以在主窗口中打开 View->Key history 菜单项查看. 也请参见: 特殊按键
{Numpad0} - {Numpad9} | 小键盘上的数字键 (与 Numlock 打开时输入的一样). 例如: {Numpad5} 为数字 5.
{NumpadDot} | 小键盘上的点 (与 Numlock 打开时输入的一样).
{NumpadEnter} | 小键盘上的 Enter 键
{NumpadMult} | 小键盘上的乘
{NumpadDiv} | 小键盘上的除
{NumpadAdd} | 小键盘上的加
{NumpadSub} | 小键盘上的除
{NumpadDel} | 小键盘上的 Delete 键 (此键和后面的小键盘按键是当 Numlock 关闭时输入的)
{NumpadIns} | 小键盘上的 Insert 键
{NumpadClear} | 小键盘上的 Clear 键 (通常为 '5' 键在 Numlock 关闭时输入的).
{NumpadUp} | 小键盘上的向上方向键
{NumpadDown} | 小键盘上的向下方向键
{NumpadLeft} | 小键盘上的向左方向键
{NumpadRight} | 小键盘上的向右方向键
{NumpadHome} | 小键盘上的 Home 键
{NumpadEnd} | 小键盘上的 End 键
{NumpadPgUp} | 小键盘上的 Page-up 键
{NumpadPgDn} | 小键盘上的 Page-down 键
{Browser_Back} | 2000/XP/Vista+: 按下浏览器的 "后退" 按钮
{Browser_Forward} | 2000/XP/Vista+: 按下浏览器的 "前进" 按钮
{Browser_Refresh} | 2000/XP/Vista+: 按下浏览器的 "刷新" 按钮
{Browser_Stop} | 2000/XP/Vista+: 按下浏览器的 "停止" 按钮
{Browser_Search} | 2000/XP/Vista+: 按下浏览器的 "搜索" 按钮
{Browser_Favorites} | 2000/XP/Vista+: 按下浏览器的 "收藏" 按钮
{Browser_Home} | 2000/XP/Vista+: 运行浏览器并打开主页
{Volume_Mute} | 2000/XP/Vista+: 主音量静音/取消静音. 通常相当于 SoundSet, +1, , mute
{Volume_Down} | 2000/XP/Vista+: 减小主音量. 通常相当于 SoundSet -5
{Volume_Up} | 2000/XP/Vista+: 增加主音量. 通常相当于 SoundSet +5
{Media_Next} | 2000/XP/Vista+: 在媒体播放器中播放下一曲目
{Media_Prev} | 2000/XP/Vista+: 在媒体播放器中播放前一曲目
{Media_Stop} | 2000/XP/Vista+: 停止媒体播放器
{Media_Play_Pause} | 2000/XP/Vista+: 播放/暂停媒体播放器
{Launch_Mail} | 2000/XP/Vista+: 启动电子邮件程序
{Launch_Media} | 2000/XP/Vista+: 启动媒体播放器
{Launch_App1} | 2000/XP/Vista+: 启动用户程序1
{Launch_App2} | 2000/XP/Vista+: 启动用户程序2
{PrintScreen} | Print Screen
{CtrlBreak} | Ctrl+break
{Pause} | Pause
{Click [Options]}
[v1.0.43+] 		使用与 Click 命令 中相同的可用选项发送鼠标点击. 例如, {Click} 会在鼠标指针当前位置点击鼠标左键一次, 而 {Click 100, 200} 则在坐标 100, 200 处点击 (这里的坐标模式取决于 CoordMode). 要移动鼠标而不点击, 在坐标后指定 0; 例如: {Click 100, 200, 0}. 在鼠标点击之间的延迟由 SetMouseDelay 决定 (而不是 SetKeyDelay).
{WheelDown}, {WheelUp}, {WheelLeft}, {WheelRight}, {LButton}, {RButton}, {MButton}, {XButton1}, {XButton2} | 向指针当前位置发送鼠标按钮事件 (要指定位置和其他选项, 请使用上面的 {Click}). 在鼠标点击之间的延迟由 SetMouseDelay 决定. WheelLeft/Right 需要 1.0.48+ 版本支持, 并且在 Windows Vista 之前的操作系统中无效.
{Blind}

当按键序列中首个项目为 {Blind} 时, 如果 Alt/Control/Shift/Win 在发送开始时为按下的状态则不松开. 例如, 热键 +s::Send {Blind}abc 将发送 ABC 而不是 abc 因为用户按住了 Shift 键.

{Blind} 同时也会忽略 SetStoreCapslockMode; 即不会改变 Capslock 的状态. 最后, {Blind} 会忽略发送的键击中的额外控制功能; 这样的键击中可以避免后面的情况: 1) 发送 LWin/RWin 键击时出现开始菜单; 2) 发送 Alt 键击时激活菜单栏.

在 按键的重映射 内部使用 Blind 模式. 例如, 重映射 a::b 会发生这样的情况: 1) 输入 "a" 时会映射为 "b"; 2) 输入大写字母 A 时映射为大写字母 B; 并且 3) 按下 Control-A 时映射为按了 Control-B.

SendRaw 和 ControlSendRaw 不支持 {Blind}. 此外, SendPlay 也不完全支持这种模式, 尤其在处理修饰键 (Control, Alt, Shift 和 Win) 时.
{Raw}
[v1.0.43+] 		准确按照键击显示的那样发送, 而不把 {Enter} 转换成 ENTER 键击, 把 ^c 转换成 Control-C 等. {Raw} 可以不放在按键序列的开始, 在按键序列中出现后, 它会影响它后面的剩余部分.

重复或按住按键

重复键击: 把需要重复的按键名称和重复次数写入到大括号中. 例如:

Send {DEL 4}  ; 按 4 次 Delete 键.
Send {S 30}   ; 发送 30 次大写字母 S.
Send +{TAB 4}  ; 按 4 次 Shift-Tab.

按住或松开按键: 把按键名称和单词 Down 或 Up写入到大括号中. 例如:

Send {b down}{b up}
Send {TAB down}{TAB up}
Send {Up down}  ; 按下向上方向键.
Sleep 1000  ; 按住 1 秒.
Send {Up up}  ; 松开向上方向键.

使用上面的方法按住一个按键后, 这个期间它不会像您实际按住这个按键一样自动重复 (这是因为自动重复是一种驱动/硬件的特性). 不过, 可以使用 Loop 来模拟自动重复. 下面的例子中发送了 20 次 tab 键击:

循环 20
{
    Send {Tab down}  ; 自动重复是由连续的按下事件组成 (没有弹起事件).
    Sleep 30  ; 在两次键击之间的毫秒数 (或使用 SetKeyDelay 设置).
}
Send {Tab up}  ; 松开按键.

还可以使用单词 DownTemp. 除了修饰键 (Control/Shift/Alt/Win) 外它的效果与 Down 相同. 在那些情况下, DownTemp 告知后续的 send 命令这个键不是永久按下, 并可能在需要时随时松开. 例如, Send {Control DownTemp} 之后接着 Send a 会产生一个普通的 "a" 键击, 而不是 control-A 键击.

一般说明

除了字母 A 到 Z 外, 还支持下列的字母和符号 (但是, 如果您系统上的代码页不是 1252 [US & Western Europe], 这个列表可能会不一样):
€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ

BlockInput 与 SendInput/SendPlay 的比较: 尽管可以使用 BlockInput 命令防止用户输入的任何键击扰乱模拟键击流, 但使用 SendInput 或 SendPlay 通常更好, 这样键击和鼠标点击会保持连续. 这是由于与 BlockInput 不同, SendInput/Play 不会丢弃发送期间用户输入的内容; 作为替代, 这样的键击被缓冲起来在之后发送.

发送大量键击时, 使用 字串分段 可以提高可读性和可维护性.

由于操作系统不允许程序模拟 CTRL-ALT-DELETE 组合键, 执行像 Send ^!{Delete} 的命令不会产生效果.

SendInput [v1.0.43+]

由于 SendInput 突出的速度和可靠性, 通常作为发送键击和鼠标点击的首选方法. 在大多数情况下, SendInput 近乎瞬时发送的, 即使在发送长字符串时. 由于 SendInput 如此快速, 所以也更可靠, 因为这样其他一些窗口更没有机会出乎意料地弹出并打断正发送的键击. 可靠性进一步提升是通过把用户在 SendInput 发送期间输入的内容推迟的情况而言.

与其他发送模式不同, 操作系统限制 SendInput 每次只能发送大约 5000 个字符 (此限制可能因操作系统版本和性能设置而有所不同). 超过此限制的字符和事件不会被发送.

注意: SendInput 会忽略 SetKeyDelay 设置, 因为在这种发送模式中操作系统不支持延迟. 但是, 在后面描述的情况中当 SendInput 恢复到 SendEvent 时, 它会使用 SetKeyDelay -1, 0 (但如果 SendEvent 的按键延迟为 "-1,-1" 时, 则使用 "-1,-1"). 当 SendInput 恢复为 SendPlay 时, 它使用 SendPlay 的按键延迟.

如果执行 SendInput 脚本外的 其他 脚本安装了 低级键盘钩子, SendInput 会自动恢复为 SendEvent (或 SendPlay, 当 SendMode InputThenPlay 有效的时候). 这是由于外部钩子的存在让 SendInput 失去了所有的优势, 使它不如 SendPlay 和 SendEvent 两者. 然而, 在 AutoHotkey 1.0.43 之前的版本中 SendInput 无法检测到底层键盘钩子, 在这些情况下将不会自动恢复使得比 SendPlay/Event 更不可靠.

当 SendInput 使用像 {Click} 这样的方法发送鼠标点击, 并且 CoordMode Mouse, Relative 有效时(默认), 每次点击都会相对于发送开始时的那个活动窗口. 因此, 如果 SendInput 有意地激活另一个窗口 (通过像 alt-tab 这样的方法), 这个命令中后续点击的坐标将变成错误的, 因为它们仍然相对于原来的活动窗口而不是新的活动窗口.

Windows 95 (和 NT4 SP3 之前的系统): 不支持 SendInput 并自动恢复为 SendEvent (或 SendPlay, 如果 SendMode InputThenPlay 有效的话).

SendPlay [v1.0.43+]

比起其他模式 SendPlay 最大的优势是具有在相当多种游戏中 "play back" 键击和鼠标点击能力. 例如, 某种特殊的游戏可能仅接受 SendPlay 选项 的 热字串.

在三种发送模式中, SendPlay 是最不常用的, 因为它本身并不模拟键击和鼠标点击. 作为替代, 它制造一系列事件 (消息) 直接流向活动窗口 (类似于 ControlSend, 但在更低的层面).

和 SendInput 一样, SendPlay 的键击不会夹杂用户输入的内容. 因此, 如果用户碰巧在 SendPlay 发送期间输入了一些内容, 它们会被延迟到发送完后.

尽管 SendPlay 明显比 SendInput 慢, 但它通常比传统的 SendEvent 模式更快 (即使在 按键延迟 为 -1 时).

SendPlay 无法触发其中调用了 Windows 键 (LWin 和 RWin) 的系统热键. 例如, 它不能显示开始菜单或使用 Win-R 来显示运行对话框.

如果安装了 键盘钩子 则在 SendPlay 发送期间会自动屏蔽 Windows 键 (LWin 和 RWin). 这样可以避免在发送期间当用户无意按了 Windows 键时显示开始菜单. 与之相比, LWin 和 RWin 之外的其他按键不需要屏蔽, 因为操作系统会自动把它们延迟到 SendPlay 执行完后 (通过缓冲).

SendPlay 不使用 SetKeyDelay 和 SetMouseDelay 的标准设置. 作为替代, 默认时它没有延迟, 这可以改变, 例如:

SetKeyDelay, 0, 10, Play  ; 请注意 0 和 -1 在 SendPlay 模式中是一样的.
SetMouseDelay, 10, Play

SendPlay 无法切换 Capslock, Numlock 或 Scroll-lock 按键的状态. 同样地, 如果键击发送到脚本自身的窗口时, 则它才能改变由 GetKeyState 获取的按键状态. 即使在这时, 对左/右修饰键的任何改变 (例如 RControl) 只能通过它们的中性副本检测到 (例如 Control). 并且, SendPlay 还有在 SendMode 页面 描述的其他限制.

与 SendInput 和 SendEvent 不同, 用户可以通过按下 Control-Alt-Del 或 Control-Escape 打断 SendPlay 的发送. 这种情况发生时, 剩余的键击不会被发送, 但脚本会像 SendPlay 正常结束一样继续执行.

尽管 SendPlay 能发送 LWin 和 RWin 事件, 但它们被直接发送到活动窗口而不执行它们原本的操作系统功能. 要变通解决此问题, 使用 SendEvent. 例如, SendEvent #r 会显示开始菜单的运行对话框.

与 SendInput 不同, 即使在 Windows 95 和 NT4 SP3 之前的系统中 SendPlay 也能使用.

相关

SendMode, SetKeyDelay, SetStoreCapslockMode, 转义序列 (e.g. `%) , ControlSend, BlockInput, Hotstrings, WinActivate

示例

Send Sincerely,{enter}John Smith ; 输入两行的签名.
Send !fs ; 选择 File->Save 菜单 (Alt+F 后面跟着 S).
Send {End}+{Left 4} ; 跳到文本的末尾然后发送四次 shift 和左方向键组合的键击.
SendInput {Raw}使用最快的方法发送一长系列的原始字符 (SendInput).


SendMode

SendMode [v1.0.43+]

让 Send 命令和 SendInput 或 SendPlay 具有同样的功能而不是其默认的 (SendEvent) 。也让 Click 和 MouseMove/Click/Drag 使用了指定的方法。

SendMode Input|Play|Event|InputThenPlay

第一个参数是下面的某个单词：

Event: 这是所有脚本开始时默认使用的。它让 Send, SendRaw, Click 和 MouseMove/Click/Drag 使用 SendEvent 方法。

Input: 让 Send, SendRaw, Click 和 MouseMove/Click/Drag 切换到 SendInput 方法。已知限制：

  • Windows 资源管理器忽略 SendInput 某些导航的热键例如 Alt+左箭头。 要绕弯解决这问题，使用 SendEvent !{Left} 或 SendInput {Backspace} 。

InputThenPlay [v1.0.43.02+]: 和上面的一样，除了当 SendInput 不可用 时恢复为 Play 模式 (下面的) 而不是退回到 Event 模式。这也会促使 SendInput 命令 它自身在 SendInput 不可用时恢复到 Play 模式。

Play: 让 Send, SendRaw, Click 和 MouseMove/Click/Drag 切换到 SendPlay 方法。
已知限制：

  • 不存在当前键盘布局上的字符 (例如英语里的 Ô ) 不能被发送。要绕弯解决这问题，使用 SendEvent 。
  • 例如在那些写字板和 Metapad 的 RichEdit(富文本编辑框) 控件 (也可能其他控件) 里模拟鼠标拖选可能无效。要为一个特别的拖选使用一个替换的模式，参照这个例子： SendEvent {Click 6, 52, down}{Click 45, 52, up}
  • 模拟鼠标滚轮的旋转仅产生在一个方向的移动 (通常是向下的，但在某些应用程序里是向上的)。而且在例如微软 Word 和记事本应用程序中滚轮旋转可能无效。要为一个特别的旋转使用一个替换的模式，参照这个例子：SendEvent {WheelDown 5}
  • 当在自动执行部分 (脚本顶部) 使用 SendMode Play ，将影响所有重映射的按键并可能失去它们的某些功能。详见 SendPlay 重映射限制 。

注意

由于 SendMode 也改变了 Click 和 MouseMove/Click/Drag 的模式，当你想要为一个特别的鼠标事件使用一个不同的模式时可能很多次了。最简单的方式就是通过 {Click} 来实施。例如：

SendEvent {Click 100, 200}  ; SendEvent 使用更旧更传统的方法点击。

如果 SendMode 用在了自动执行部分 (脚本顶部)，它也会影响 键盘和鼠标重映射 。尤其是如果你在重映射时使用了 SendMode Play，请看 SendPlay 重映射限制 。

每个再次启动的 thread (例如一个 hotkey, 自定义菜单项 或 定时的 子程序) 都以此命令的默认设置重新开始。在自动执行部分 (脚本顶部) 使用此命令可以改变那个默认设置。

相关命令

Send, SetKeyDelay, SetMouseDelay, Click, MouseClick, MouseClickDrag, MouseMove

示例

SendMode Input
SendMode InputThenPlay


SetKeyDelay

设置 Send 和 ControlSend 命令发送的两次按键事件间的延时。

SetKeyDelay [, Delay, PressDuration, Play]

参数

Delay | 延时时间，单位毫秒。可以是一个 expression/表达式 。使用 -1 表示无延时，使用 0 表示最小延时（但是，如果使用了 Play 参数的话，0 和 -1 都表示无延时）。留空则保持当前的 延时 不变。
PressDuration | 按键时长。有些游戏或者特殊的应用程序要求每次按键有一定的按下时间。也就是说，按下一个按键，停顿一段时间，再松开。 使用 -1 表示无停顿，使用 0 表示最小停顿（但是，如果使用了 Play 参数的话，0 和 -1 都表示无停顿）。留空则保持当前的 按键时长 不变 注意：PressDuration 参数同样会在功能键（CTRL，ALT，SHIFT，以及 WIN）状态改变的时候产生一个停顿。 这个参数可以是一个 expression/表达式 。
Play [v1.0.43+] | 这个参数使用单词 Play 的话，表示这是为 SendPlay 模式 设置的延时，而不是一般的 SendEvent 模式。如果脚本中从未使用过这个参数，则 SendPlay 模式的延时永远是 -1/-1 。

注意

注意：SetKeyDelay 的设置对 SendInput 是无效的，在那个模式中永远是无延时。同样，对启用了 SendMode Input 设置的 Send 命令也是无效的。

脚本在执行了每个 Send 或 ControlSend 命令发送的按键事件之后，会有一个自动的延时（休眠）。这样做的目的是提高脚本的可靠性，因为一个窗口一般无法响应太过频繁的按键事件。

根据系统的时间精度，设置的延时可能会被四舍五入为最近的整十数字。例如在 XP 中，1 到 10 之间的延时（包括 10 ）都等效于 10 （NT 和 2000 中也是这样）。

在 Send/SendEvent 模式中，设置延时为 0 的话相当于执行了命令 Sleep(0) ，它会将当前脚本的剩余时间片分配给有需要的进程。如果没有进程需要，延时 0 就相当于完全没有延时。相反的，设置延时为 －1 表示永远没有延时。为了提高脚本的可靠性，一般推荐使用 0 而不是 －1 。

当延时设置为 －1 的时候，在 SendEvent 模式 中，脚本发送按键事件的速度取决于脚本进程的优先级。提升一个脚本的优先级，使用 Process, Priority,, High 。虽然这样一般会使按键的发送速度超过 当前窗口 的处理速度，不过系统会自动将按键存入缓存中。在 Send 命令完成之后，缓存中的按键会继续发送到目标窗口（即使这个窗口不再处于激活状态）。这种情况一般是不要紧的，因为任何并发的对同一个窗口发送的按键事件会自动排列在缓存中的按键事件之后。

如果未进行设置，在 SendEvent 模式中默认的 Delay 是 10（在 .aut 脚本中是 20）。在 SendPlay 模式 中默认的 Delay 是 -1 。两个模式中默认的 PressDuration 都是 －1 。

内置变量 A_KeyDelay 保存了当前 Send/SendEvent 模式中 Delay 参数的设置。没有内置变量保存 SendPlay 模式 中Delay 参数的设置，也没有内置变量保存 PressDuration 参数的设置。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将该命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

Send, ControlSend, SendMode, SetMouseDelay, SetControlDelay, SetWinDelay, SetBatchLines, Click

示例

SetKeyDelay, 0


SetCapsLockState/SetNumLockState/SetScrollLockState

设置 Capslock/NumLock/ScrollLock 的状态。也可以让这些键保持开启或关闭的状态。

SetCapsLockState [, State]
SetNumLockState [, State]
SetScrollLockState [, State]

参数

State

如果省略这个参数，将会清除按键的“AlwaysOn/Off”状态（如果设置了的话）。否则，这个参数可以是下面几个词：

On：开启按键，同时清除按键的“AlwaysOn/Off”状态（如果设置了的话）。

Off：关闭按键，同时清除按键的“AlwaysOn/Off”状态（如果设置了的话）。

AlwaysOn：让按键保持一直启用状态（在 Windows95 中无效）。

AlwaysOff: 让按键保持一直关闭状态（在 Windows95 中无效）

注意

由于系统本身的限制，这些命令在 Windows Me/98/95 中不一定有用。在 Win9x 中，想切换这些按键到相反的状态，可以使用 Send 命令，例如：Send {Capslock}

要保持一个键的 AlwaysOn 或者 AlwaysOff 状态，脚本会自动使用 键盘勾子 。

相关命令

SetStoreCapslockMode, GetKeyState

示例

SetNumlockState, on
SetScrollLockState, AlwaysOff


SetStoreCapslockMode

设置在一个 Send 命令之后是否恢复 CapsLock 的状态。

SetStoreCapslockMode, On|Off

参数

On|Off

On：这个是脚本的默认值：如果一个 Send 命令暂时改变了 CapsLock 的状态，那么命令结束之后，它会自动恢复原来的状态。

Off：CapsLock 的状态完全不会被改变。所以，如果 CapsLock 处于开启状态的话，Send 命令输出的字母都是大小写颠倒的。

注意

由于系统的限制，这个命令在 Windows Me/98/95 中可能不会有效。也就是说在 Send 和 ControlSend 命令中 CapsLock 不能总是保持关闭的状态。即使它被关闭了，在命令完成之后它也不会自动恢复原来的状态。

这个命令其实不怎么常用，因为默认设置在大多数情况下都非常好使。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

SetCaps/Num/ScrollLockState, Send, ControlSend

示例

SetStoreCapslockMode, off


EnvAdd

把变量设置为它自身加上给定的值的总和 (也能从一个日期-时间的值里加上或减去时间)。同义于: var += value

EnvAdd, Var, Value [, TimeUnits]
Var += Value [, TimeUnits]
Var++

参数

Var | 要操作的变量名称。
Value | 任何整数、浮点数或表达式。
TimeUnits | 如果提供，此参数指示命令添加 Value 给 Var，将 Var 作为一个 YYYYMMDDHH24MISS 格式的日期-时间标记并且把 Value 作为整数或浮点数单位来添加 (要做减法，指定一个负值)。TimeUnits 可以是 Seconds, Minutes, Hours 或 Days (或者仅用它们的第一个字母)。 如果 Var 是一个空变量，将用当前的时间来代替它。如果 Var 包含一个无效的时间标记或一个早于 1601 的年份，又或者如果 Value 是非数值，Var 将被设为空来表明有问题。 内置变量 A_Now 包含 YYYYMMDDHH24MISS 格式的当前本地时间。 要计算两个时间标记之间的时间量，请用 EnvSub。

注意

此命令等于这种速记形式：Var += Value

变量通过使用 Var++, Var--, ++Var 或 --Var 能被加上或减去 1 。

如果 Var 或 Value 为空或者不以数字开头，为了计算的目的它将被视为 0 (除了在一个表达式内部使用时，除了使用 TimeUnits 参数时)。

如果 Var 或者 Value 包含小数点，最后的结果将是一个由 SetFormat 设置格式的浮点数。

相关命令

EnvSub, EnvMult, EnvDiv, SetFormat, Expressions, If var is [not] type, SetEnv, FileGetTime

示例

EnvAdd, MyCount, 2
MyCount += 2  ;等同于上面的命令

var1 =  ;使它为空，以便在下面使用当前的时间代替它。
var1 += 31, days
MsgBox, %var1%  ;答案将是当前 31 天后的日期。


EnvDiv

将变量设置为它自身除以给定的值。同义于: var /= value

EnvDiv, Var, Value

参数

Var | 要操作的变量名称。
Value | 任何整数、浮点数或者表达式。

注意

此命令等同于这种速记形式: Var /= Value

除以零会导致脚本载入时弹出错误信息窗口(如果可能的话)；要不就使变量为空。

如果 Var 或 Value 为空或者不以数字开头，那么出于计算的目的它将被视为 0 (除了在一个表达式内部使用时，例如 Var := X /= Y)。

如果 Var 或 Value 包含小数点，那么最后的结果将是一个浮点数，其格式可由 SetFormat 命令设置。否则，结果将被截断 (例如 19 除以 10 将得出 1)。

相关命令

EnvAdd, EnvSub, EnvMult, SetFormat, Expressions, If var is [not] type, SetEnv, bitwise operations (Transform)

示例

EnvDiv, MyCount, 2
MyCount /= 2 ;等同于上面的命令


EnvMult

将变量设置为它自身乘以给定的值。同义于: var *= value

EnvMult, Var, Value

参数

Var | 要操作的变量名称。
Value | 任何整数、浮点数或者表达式。

注意

此命令等同于这种速记形式: Var *= Value

如果 Var 或 Value 为空或者不以数字开头，那么出于计算的目的它将被视为 0 (除了在一个表达式内部使用时，例如 Var := X *= Y)。

如果 Var 或 Value 包含小数点，那么最后的结果将是一个浮点数，其格式可由 SetFormat 命令设置。

相关命令

EnvAdd, EnvSub, EnvDiv, SetFormat, Expressions, If var is [not] type, SetEnv, bitwise operations (Transform)

示例

EnvMult, MyCount, 2
MyCount *= 2  ;等同于上面的命令


EnvSub

把变量设置为它自身减去给定的值 (也能比较日期-时间的值)。同义于：var -= value

EnvSub, Var, Value [, TimeUnits]
Var -= Value [, TimeUnits]
Var--

参数

Var | 要操作的变量名称。
Value | 任何整数、浮点数或表达式。(当提供了 TimeUnits 时将不支持表达式)。
TimeUnits

如果提供，此参数指示命令从 Var 减去 Value 就像它们都是 YYYYMMDDHH24MISS 格式的日期-时间标记。TimeUnits 可以是 Seconds, Minutes, Hours 或 Days (或者仅用它们的第一个字母)。如果 Value 为空，将用当前的时间来代替它。同样，如果 Var 是一个空变量，将用当前的时间来代替它。

结果总会向下调整成整数。例如，如果两个时间标记之间实际的差是 1.999 天，它将报称 1 天。如果需要更高的精度，可指定 TimeUnits 为 Seconds 并把结果除以 60.0, 3600.0 或 86400.0 。

如果 Var 或 Value 是一个无效的时间标记或者包含一个早于 1601 的年份，Var 将被设为空来表明有问题。

内置变量 A_Now 包含 YYYYMMDDHH24MISS 格式的当前本地时间。

要精确地测定在两个事件之间消逝的时间，可用 A_TickCount 方法，因为它提供了毫秒级的精度。

要从一个时间标记加上或者减去某个 seconds, minutes, hours 或 days 的数值，也可用 EnvAdd (减法是通过添加一个负数来获得的)。

注意

此命令等于这种速记形式：Var -= Value

变量通过使用 Var++, Var--, ++Var 或 --Var 能被加上或减去 1 。

如果 Var 或 Value 为空或者不以数字开头，为了计算的目的它将被视为 0 (除了在一个表达式内部使用时，除了使用 TimeUnits 参数时)。

如果 Var 或者 Value 包含小数点，最后的结果将是一个由 SetFormat 设置格式的浮点数。

相关命令

EnvAdd, EnvMult, EnvDiv, SetFormat, Expressions, If var is [not] type, SetEnv, FileGetTime

示例

EnvSub, MyCount, 2
MyCount -= 2 ;等同于上面的命令

var1 = 20050126
var2 = 20040126
EnvSub, var1, %var2%, days
MsgBox, %var1% ;答案会是 366 天，因为 2004 是个闰年。


If var [not] between LowerBound and UpperBound

根据数值或字母顺序检查 变量的 内容是否在两个值之间 (包含边界).

if Var between LowerBound and UpperBound
if Var not between LowerBound and UpperBound

参数

Var | 需要被检查的 变量 名称.
LowerBound | 指定范围的下限, Var 必须大于或等于此字符串, 数字或变量引用.
UpperBound | 指定范围的上限, Var 必须小于或等于此字符串, 数字或变量引用.

备注

如果这三个参数都为纯数值, 那么它们将被作为数字而不是字符串进行比较. 其他情况下, 它们将被作为字符串按字母顺序进行比较 (即字母次序将决定 Var 是否在指定范围内). 此时, 可以使用 " StringCaseSense On" 来设置在比较时区分大小写.

运算符 "between", "is", "in" 和 "contains" 不支持用于 表达式 中.

相关

IfEqual/Greater/Less, if var in/contains MatchList, if var is type, IfInString, StringCaseSense, EnvAdd , 区块, Else

示例

if var between 1 and 5
    MsgBox, %var% is in the range 1 to 5, inclusive.

if var not between 0.0 and 1.0
    MsgBox %var% is not in the range 0.0 to 1.0, inclusive.

if var between %VarLow% and %VarHigh%
    MsgBox %var% is between %VarLow% and %VarHigh%.

if var between blue and red
    MsgBox %var% is alphabetically between the words blue and red.

LowerLimit = 1
UpperLimit = 10
InputBox, UserInput, Enter a number between %LowerLimit% and %UpperLimit%
if UserInput not between %LowerLimit% and %UpperLimit%
    MsgBox Your input is not within the valid range.


If var is [not] type

检查 变量的 内容是否为数值, 大写字母或其他.

if var is type
if var is not type

参数

var | 变量 名.
type | 请参阅下面的备注.

备注

受支持的 Type:

integer | 当 var 非空且包含不带小数点的纯数值字符串 (十进制或十六进制) 时为 true. 允许含有前导和尾随空格和 tab. 字符串可以以加号或减号开始.
float | 当 var 非空且包含浮点数; 即含有小数点的纯数值字符串时为 true. 允许含有前导和尾随空格和 tab. 字符串可以以加号, 减号或小数点开始.
number | 当 var 包含整数或浮点数 (上文描述的每种数字) 时为 true.
digit | 当 var 为空或仅包含由 0 到 9 字符组成的数字时为 true. 不允许出现其他字符, 例如后面这些: 空格, tab, 加号, 减号, 小数点, 十六进制数以及 0x 前缀.
xdigit | 十六进制数: 除了还允许 A 到 F (大写和小写形式) 字符外, 其他与 digit 相同. 在 v1.0.44.09+, 允许使用 0x 前缀.
alpha | 当 var 为空或仅包含字母时为 true. 如果字符串中含有任何数字, 空格, tab, 标点或其他非字母的字符时则为 false. 例如, 如果 var 包含一个空格后跟一个字母, 那么它 不会 被看成是 alpha.
upper | 当 var 为空或仅包含大写字母时为 true. 如果字符串中含有任何数字, 空格, tab, 标点或其他非大写字母的字符时则为 false.
lower | 当 var 为空或仅包含小写字母时为 true. 如果字符串中含有任何数字, 空格, tab, 标点或其他非小写字母的字符时则为 false.
alnum | 除了还允许 0 到 9 的数字外, 其他与 alpha 相同.
space | 当 var 为空或仅包含空白字符时为 true, 其中空白字符包括后面这些字符: 空格 (%A_Space%), tab (%A_Tab% or `t), 换行符 (`n), 回车符 (`r), 垂直 tab (`v) 和进纸符 (`f).
time | 当 var 包含有效的日期时间戳时为 true, 其中日期时间戳可以是 YYYYMMDDHH24MISS 格式的全部或开始部分. 例如, 类似 2004 这样的 4 位字符串被视为有效的. 使用 StringLen 可以判断是否存在额外的时间部分. 小于 1601 的年份会被视为无效的, 因为操作系统通常不支持它们. 被视为有效的最大年份为 9999. 可以使用单词 DATE 代替 TIME, 效果相同.

注意: 运算符 "between", "is", "in" 和 "contains" 不支持 用于 表达式 中.

[AHK_L 42+]: 如果没有使用 StringCaseSense Locale, 那么会忽略系统区域设置.

相关

%A_YYYY%, SetFormat, FileGetTime, IfEqual, if var in/contains MatchList, if var between, StringLen, IfInString, StringUpper, EnvAdd , 区块, Else

示例

if var is float
    MsgBox, %var% is a floating point number.
else if var is integer
    MsgBox, %var% is an integer.
if var is time
    MsgBox, %var% is also a valid date-time.


Random

产生一个伪随机数。

Random, OutputVar [, Min, Max]
Random, , NewSeed

参数

OutputVar | 存储结果的变量名。被存储的浮点数的格式由 SetFormat 决定。
Min | 可以产生的最小的数。可以是负数，浮点数，或者一个 expression (表达式)。缺省情况下，产生的最小的数是 0 。 允许的最小整数是 -2147483648，浮点数没有限制。
Max | 可以产生的最大的数。可以是负数，浮点数，或者一个 expression (表达式)。如果省略，缺省情况下，产生的最大的数是 2147483647 (这也是允许的最大整数 -- 但是浮点数没有限制)。
NewSeed

此模式通过 NewSeed (可以是一个 expression (表达式)) 对随机数产生器重新定义种子。这对随后产生的随机数都有影响。NewSeed 应当是介于 0 和 4294967295 (0xFFFFFFFF)之间的整数。重新定义种子能够提高所产生随机数的质量和安全性，尤其当 NewSeed 是一个真正的随机数而不是像伪随机数一样质量欠佳时更是这样。通常，种子只需要重新定义一次即可。

如果脚本中从来没有重定义过种子，种子使用一个 64 位值的低 32 位作为开始。这个 64 位的值是从1601年1月1日开始100纳秒的数目。这个低 32 位值从 0 变化至 4294967295，其中100毫秒累计 ~7.2 分钟。

注意

此命令产生一个伪随机数，即一个模拟真正随机数的数字，但是它实际上是一个基于复杂方程式的使得决定或者猜测下一个数字极为困难的数字。

如果 Min 或者 Max 其中之一被设置为十进制浮点数，最后的结果将是由 SetFormat 决定格式的浮点数。否则，结果将是一个整数。

结果是浮点数的局限：1) 只有其中 32位用于产生变量；2) 它偶尔也会比指定的 Max 略微大一点点(这是由浮点数内在的不精确性导致的)。

相关命令

SetFormat

示例

Random, rand, 1, 10
Random, rand, 0.0, 1.0

关于原始资料的注释

此函数使用了 Mersenne Twister 随机数产生器，MT19937, 原作者：Takuji Nishimura , Matsumoto, Shawn Cokus, Matthe Bellew, Isaku Wada.

Mersenne Twister 是一个用于产生随意数的算法。它在考虑其他随机数产生器的基础上被设计出来。它的循环周期，219937-1，和它的等分布顺序，623 dimensions(维度)，都非常之大。与此同时，这个产生器非常快，它避免了乘法和除法，并且从缓存和管道中得益。想了解更多，请访问原作者的网站 www.math.keio.ac.jp/~matumoto/emt.html

(译者注：以下是关于算法的法律声明与使用限制，一般不允许翻译，但是这个没说，以下就不翻译了，不影响大家对此命令的使用^_^)

Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Do NOT use for CRYPTOGRAPHY without securely hashing several returned values together, otherwise the generator state can be learned after reading 624 consecutive values.

When you use this, send an email to: matumoto@math.keio.ac.jp with an appropriate reference to your work. It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu when you write.

This above has been already been done for AutoHotkey, but if you use the Random command in a publicly distributed application, consider sending an e-mail to the above people to thank them.


SetFormat

设置数学运算得到的整数和浮点数的格式.

SetFormat, NumberType, Format

参数

NumberType

必须为 IntegerFast, FloatFast, Integer 或 Float (含 fast 的两种模式需要 1.0.48+ 版本支持; 参见 备注).
Format

当 NumberType 为 Integer 或 IntegerFast 时, 需要十六进制时在此参数中指定 H 或 HEX, 而十进制时指定 D. 十六进制数必须以前缀 0x 开头 (例如 0xFF). [AHK_L 42+]: 十六进制整数被格式化为含有小写的 A-F 数字当此参数为 h 而大写当此参数为 H.

当 NumberType 为 Float 或 FloatFast 时, 在此参数中指定 总宽度.小数位数 (例如 0.6). 在 1.0.46.11+ 版本中, 可以在后面添加字母 "e" 来得到科学计数法表示的结果; 例如 0.6e 或 0.6E (使用大写字母 E 则在每个结果的数字中使用大写 E). 注意: 在 AutoHotkey 1.x 中, 使用科学计数法表示结果时此参数必须包含小数点; 例如 1.0e1 是正确的而 1e1 则错误.

总宽度 通常为 0 表示结果不需要使用空格或零填充. 如果总宽度大于实际宽度, 结果中将使用空格或零填充 (参见 备注) 至指定宽度. 注: 总宽度包含小数点的宽度, 同时当总宽度小于实际宽度时, 则使用实际宽度.

小数位数 为要显示的小数部分的位数 (超出部分将进行四舍五入). 注: 如果指定的小数位数大于实际的位数, 则总是使用零填充. 如果为空或零, 则结果中不会显示小数点和小数部分, 即浮点运算的结果会显示为整数而不是浮点数. 默认的小数位数为 6. 注: 如果没有指定小数位数, 则小数位数为 0, 即 1 和 1.0 是一样的.

填充: 如果 总宽度 大于实际宽度, 结果中将在左边填充空格; 即每个数字将是右对齐的. 要让数字左对齐, 在 总宽度 加上一个负号. 要使用零而不是空格填充, 在 总宽度 前加上一个零 (例如 06.2).

Fast 与 Slow 模式的比较

在 1.0.48+ 版本中, 可以使用 IntegerFast 代替 Integer, 而使用 FloatFast 代替 Float.
  • 优点: 快速模式能维持变量缓存整数和浮点数的能力, 这样可以极大地加快数值密集的运算. (相反地, 慢速模式强制将所有的数值结果立即转换并保存为字符串.)
  • 缺点: 保存数字到变量时, 快速模式延迟 SetFormat 的效果到脚本实际需要此变量的文本/字符串版本时 (例如要在 MsgBox 显示变量的内容). 由于不同的 SetFormat 可能同时生效 (例如更多或更少的小数位), 这可能可能导致不可预期的结果. 要让当前的快速模式立即生效, 执行一个像 HexValue .= "" 这样的操作, 这个操作中把一个空字符串附加到当前保存在 HexValue 的数字上.

如果在脚本的任意位置使用了慢速模式 "Integer" 或 "Float", 即使 SetFormat 命令所在的这行从未执行, 在脚本开始运行时都会禁用整数或浮点数的缓冲.

浮点格式

在 v1.0.48+, 浮点变量的内部精确度大约为 15 位, 除非在脚本的某处使用了 SetFormat Float (例如慢速模式). 此时, 浮点数保存的精度由 小数位数 决定 (就像 1.0.48 之前的版本那样). 换句话说, 一旦浮点运算的结果保存到变量中, 多余的精度会丢失并且无法通过再进行像 SetFormat, Float, 0.15 这样的计算进行还原. 为了防止精度的丢失, 请避免在脚本中使用 SetFormat Float 或者使用 SetFormat FloatFast 代替.

不论当前有效的是快速模式还是慢速模式, 浮点结果和变量都四舍五入到 小数位数, 每当它们被显示或转换到字符串文本时 (例如 MsgBox 或 FileAppend). 要查看完整的精度, 使用类似 SetFormat, FloatFast, 0.15 这样的命令.

要把浮点数转换成整数, 使用 Var:=Round(Var), Var:=Floor(Var) 或 Var:=Ceil(Var). 要把整数转换成浮点数, 给它加上 0.0 (例如 Var+=0.0) 或使用 MyFloat:=Round(MyInteger, 1) 这样的命令.

内置变量 A_FormatFloat 包含了当前的浮点格式 (例如 0.6).

整数格式

整数运算结果一般显示为十进制, 不是十六进制. 要切换为十六进制, 使用 SetFormat, IntegerFast, Hex. 这种方法还可以用来把整数从十进制转换为十六进制 (反之亦然), 如同此页面底部示例演示的那样.

在脚本中指定原义的整数可以写为十六进制或十进制. 十六进制整数都以前缀 0x 开始 (例如 0xA9). 它们可以用于任何需要数字的地方. 例如, Sleep 0xFF 相当于 Sleep 255, 不管当前 SetFormat 中整数格式的设置如何.

AutoHotkey 支持 64 位有符号整数, 其范围从 -9223372036854775808 (-0x8000000000000000) 到 9223372036854775807 (0x7FFFFFFFFFFFFFFF).

内置变量 A_FormatInteger 包含了当前的整数格式 (H 或 D).

一般说明

如果脚本中没有使用 SetFormat, 整数默认为十进制格式, 而浮点数默认为 总宽度.小数位数 = 0.6. 每个新运行的 线程 (例如 热键, 自定义菜单项 或 计时器 的子程序) 都会以这些设置的默认值开始; 但可以在自动执行段 (脚本的顶部) 使用 SetFormat 改变这些默认值.

旧式的赋值风格如 x=%y% 会忽略任何首尾的空格 (例如填充的). 要避免这种情况, 使用 AutoTrim 或 冒号-等号运算符 (例如 x:=y).

使用 if var is number/integer/float 可以判断一个变量的内容是否为数值.

要对一个整数填充零或空格可以不必对其进行浮点运算, 参照此例:

Var := "          " . Var     ; 引号内包含 10 个空格.  要用零填充, 把其中的空格替换为零.
StringRight, Var, Var, 10  ; 这里用足够的空格填充 Var 中的数字使其总宽度为 10 个字符.
Var := SubStr("          " . Var, -9)  ; 这里单行实现上面两行的操作.

相关

表达式赋值 (:=), EnvAdd, EnvSub, EnvMult, EnvDiv, AutoTrim, if var is type

示例

Var = 11.333333 SetFormat, float, 6.2 Var -= 1 ; Sets Var to be 10.33 with one leading space because the total width is 6.
SetFormat, float, 0.2 Var += 1 ; Sets Var to be 11.33 with no leading spaces.
SetFormat, float, 06.0 Var += 0 ; Sets Var to be 000011

; Convert a decimal integer to hexadecimal:
SetFormat, IntegerFast, hex Var += 0 ; Sets Var (which previously contained 11) to be 0xb. Var .= "" ; Necessary due to the "fast" mode.
SetFormat, IntegerFast, d


Transform

执行各种数学功能, 按位运算, 和类似 ASCII/Unicode 转换的任务.

Transform, OutputVar, Cmd, Value1 [, Value2]

参数

OutputVar | 用于保存 Cmd 结果的变量名称. SetFormat 决定了整数结果是保存为十六进制还是十进制.
Cmd, Value1/2 | 见下表.

Cmd, Value1, Value2

Cmd, Value1 和 Value2 参数相互依赖, 它们的用法描述如下.

Unicode [, String]: 从剪贴板中获取 Unicode 文本或保存 Unicode 文本到剪贴板上. 注意: 使用 ClipboardAll 的方法可以保存和恢复整个剪贴板的内容, 这种方法使得 "Transform Unicode" 操作时不会丢失剪贴板的原始内容.

此子命令的两种操作模式举例如下:

Transform, OutputVar, Unicode  ; Retrieves the clipboard's Unicode text as a UTF-8 string.
Transform, Clipboard, Unicode, %MyUTF_String%  ; Places Unicode text onto the clipboard.

在上面的第二个例子中, %MyUTF_String% 可以使用原义的 UTF-8 字符串代替.

使用热键得到一个给定的 Unicode 字符串相应的 UTF-8 字符串, 例如:

^!u::  ; Control+Alt+U hotkey.
MsgBox Copy some Unicode text onto the clipboard, then return to this window and press OK to continue.
Transform, ClipUTF, Unicode
Clipboard = Transform, Clipboard, Unicode, %ClipUTF%`r`n
MsgBox The clipboard now contains the following line that you can paste into your script. When executed, this line will cause the original Unicode string you copied to be placed onto the clipboard:`n`n%Clipboard%
return

请注意: 1) Windows 95 系统需要 Microsoft 的 Unicode 支持层 才能支持此子命令 (Windows 98/Me/NT4 或更高版本系统中已经内置这个支持); 2) "Send {ASC nnnnn}" 命令是生成 Unicode 字符的一种可选方法, 但其并不是在所有的应用程序中都有效.

Asc, String: 获取 String 中首个字符的 ASCII 码 (一个介于 1 和 255 之间的数字). 如果 String 为空, OutputVar 也将被置空. 例如: Transform, OutputVar, Asc, %VarContainingString%. 对应函数: Asc(String).

Chr, Value1: 获取 ASCII 码为 Value1 的单个字符. 如果 Value1 不是 1 和 255 及其之间的数字, OutputVar 将被置空来表明此问题. 例如: Transform, OutputVar, Chr, 130. 对应函数: Chr(Number).

Deref, String: 展开变量引用和包含在其他变量中的 转义序列. 任何糟糕格式的变量引用在展开时将被忽略. 把 OutputVar 展开为其内容也是如此; 换句话说, 在 String 的变量中任何对 OutputVar 引用在展开时将被忽略 (但请注意 String 自身可以 是 %OutputVar%). 在下面的例子中, 如果 var1 包含字符串 "test" 而 var2 包含 原义的 字符串 "%var1%", 此时 OutputVar 将被赋值为字符串 "test": Transform, OutputVar, deref, %var2%. 在 函数 内, String 中的每个变量总是解析为局部变量, 只有在局部变量不存在时才解析为全局变量 (如果没有则为空).

HTML, String [, Flags]:

在 AutoHotkey 和 AutoHotkey_L ANSI 版本中: Flags 参数可以省略. 通过把 ASCII 值大于 127 的字符译成它们的 HTML 名称来把 String 转换为其 HTML 对应字符串 (例如 £ 译成 &pound;). 此外, 这四个字符 "&<> 依次被译成 &quot;&amp;&lt;&gt;. 最后, 每个换行符 (`n) 被译成 <br>`n (即 <br> 后面跟着一个换行符).

在 AutoHotkey_L Unicode 版本中: 除了上述的功能外, Flags 可以为零或下列值的组合 (和). 如果省略, 默认为 1.

  • 1: 把某些字符转换成命名表示法, 例如 € 被转换成 &euro;
  • 2: 把某些字符转换成编号表示法, 例如 € 被转换成 &#8364;

仅影响非 ASCII 字符. 如果 Flags = 3, 仅在命名表示法不可用的情况下才使用编号表示法. 后面的这些字符总是需要转换: <>"& 和 `n (换行符).

FromCodePage / ToCodePage: 不赞成使用. 使用 StrPut() / StrGet() 代替.

Mod, Dividend, Divisor: 获取被除数 Dividend 除以除数 Divisor 后得到的余数. 如果 Divisor 为零, OutputVar 将被置空. Dividend 和 Divisor 都可以为小数. 如果 Divisor 为负数, 在计算中将被视为正数处理. 下面这个例子结果为 2: Transform, OutputVar, mod, 5, 3. 对应函数: Mod(Dividend, Divisor).

Pow, Base, Exponent: 获取底数 Base 的指数 Exponent 次幂. Base 和 Exponent 都可以为小数. 如果 Exponent 为负数, 即使 Base 和 Exponent 都为整数, OutputVar 也将被格式化为浮点数. 不支持 Base 为负数且 Exponent 为分数例如 1.5 的情况; 这将使得 OutputVar 被置空. 也请参见: ** operator.

Exp, N: 获取 e (其近似值为 2.71828182845905) 的 N 次幂. N 可以为负数也可以为小数. 对应函数: Exp(N).

Sqrt, Value1: 获取 Value1 的平方根. 如果 Value1 为负数, OutputVar 将被置空. 对应函数: Sqrt(Number).

Log, Value1: 获取 Value1 的对数 (底数为 10). 如果 Value1 为负数, OutputVar 将被置空. 对应函数: Log(Number).

Ln, Value1: 获取 Value1 的自然对数 (底数为 e). 如果 Value1 为负数, OutputVar 将被置空. 对应函数: Ln(Number).

Round, Value1 [, N]: 如果 N 省略, OutputVar 将被设置为 Value1 四舍五入后的整数. 如果 N 为正数, 则将 Value1 取整到 N 个小数位. 如果 N 为负数, 则将 Value1 取整到小数点左边 N 位. 例如, -1 取整到个位, -2 取整到十位, 而 -3 取整到百位. 注意: 取整小数位时不会移除末尾的零. 例如, 把 12.333 取整到十分位后将变成 12.300000. 在操作前使用像 SetFormat, float, 0.1 的命令可以改变此行为 (事实上, 第一步使用 SetFormat 后可能不需要再使用 Round 了). 对应函数: Round(Number [, N]).

Ceil, Value1: 获取 Value1 向上取的最近的整数. 对应函数: Ceil(Number).

Floor, Value1: 获取 Value1 向下取的最近的整数. 对应函数: Floor(Number).

Abs, Value1: 获取 Value1 的绝对值, 这是通过移除 Value1 前面的负号(破折号) (如果有的话) 来计算的. 对应函数: Abs(Number).

Sin, Value1: 获取 Value1 的正弦三角函数值. Value1 必须用弧度表示. 对应函数: Sin(Number).

Cos, Value1: 获取 Value1 的余弦三角函数值. Value1 必须用弧度表示. 对应函数: Cos(Number).

Tan, Value1: 获取 Value1 的正切三角函数值. Value1 必须用弧度表示. 对应函数: Tan(Number).

ASin, Value1: 获取弧度表示的反正弦值 (此数字的正弦值为 Value1). 如果 Value1 小于 -1 或大于 1, OutputVar 将被置空. 对应函数: ASin(Number).

ACos, Value1: 返回弧度表示的反余弦值 (此数字的余弦值为 Value1). 如果 Value1 小于 -1 或大于 1, OutputVar 将被置空. 对应函数: ACos(Number).

ATan, Value1: 返回弧度表示的反正切值 (此数字的正切值为 Value1). 对应函数: ATan(Number).

注意: 下面的每个按位操作都有一个用于表达式中的更简洁的 按位运算符.

BitNot, Value1: 把 Value1 按位取反后保存到 OutputVar (如果 Value1 是浮点数, 在计算前把它截取成整数). 如果 Value1 介于 0 和 4294967295 (0xffffffff) 之间, 它将被视为 无符号的 32 位值. 否则, 它被视为 有符号的 64 位值. 后面的例子结果为 0xfffff0f0 (4294963440): Transform, OutputVar, BitNot, 0xf0f

BitAnd, Value1, Value2: 获取 Value1 和 Value2 按位与运算的结果 (在计算前首先把浮点数截取成整数). 后面的例子结果为 0xff00 (65280): Transform, OutputVar, BitAnd, 0xff0f, 0xfff0

BitOr, Value1, Value2: 获取 Value1 和 Value2 按位或运算的结果 (在计算前首先把浮点数截取成整数). 后面的例子结果为 0xf0f0 (61680): Transform, OutputVar, BitOr, 0xf000, 0x00f0

BitXOr, Value1, Value2: 获取 Value1 和 Value2 按位异或运算的结果 (在计算前首先把浮点数截取成整数). 后面的例子结果为 0xff00 (65280): Transform, OutputVar, BitXOr, 0xf00f, 0x0f0f

BitShiftLeft, Value1, Value2: 获取 Value1 往左移动 Value2 个位的结果, 这相当于 Value1 乘以 "2 的 Value2 次幂" (在计算前首先把浮点数截取成整数). 下面这个例子结果为 8: Transform, OutputVar, BitShiftLeft, 1, 3

BitShiftRight, Value1, Value2: 获取 Value1 往右移动 Value2 个位的结果, 这相当于 Value1 除以 "2 的 Value2 次幂", 舍去余数 (在计算前首先把浮点数截取成整数). 下面这个例子结果为 2: Transform, OutputVar, BitShiftRight, 17, 3

备注

接受数值参数的子命令在它们的这些参数中也可以使用 表达式.

如果 Value1 或 Value2 是一个浮点数, 后面的 Cmd 获取的结果将为浮点数而不是整数: Mod, Pow, Round, 和 Abs. 获取结果的小数位数由 SetFormat 决定.

要将弧度转换成角度, 将其乘以 180/pi (约为 57.29578). 要将角度转换成弧度, 将其乘以 pi/180 (约为 0.01745329252).

pi 的值 (约为 3.141592653589793) 为 1 的反正切值乘以 4.

相关

SetFormat, 表达式, EnvMult, EnvDiv, StringLower, if var is type

示例

Transform, OutputVar, Asc, A ; Get the ASCII code of the letter A.


Var := expression

执行一个表达式并且将结果存储在一个 变量 中。

Var := expression

参数

Var | 变量 的名称，存储 表达式 的结果。
Expression | 查看 表达式 以及下面的例子获取更多信息。

注意

>“:=”运算符是优化过了的，在一些简单的脚本中，它的执行速度和“＝”是一样快的。例如：

x := y  ; 效率同：x = %y%
x := 5  ; 效率同：x = 5.
x := "literal string"  ; 效率同：x = literal string.

单词“true”和“false”是内置常量，代表 1 和 0 。它们可以增加代码的可读性，例如：

CaseSensitive := false
ContinueSearch := true

这个命令，以及所有接收 OutputVar 参数的命令都可以创建一个 数组 ，只要让 OuputVar 包含一个对其它变量的引用就行了。例如 Array%i% := Var/100 + 5 。查看 数组 获取更多信息。

相关命令

Expressions, IF (expression), Functions, SetEnv, EnvSet, EnvAdd, EnvSub, EnvMult, EnvDiv, If, Arrays

示例

Var := 3
Var := "literal string"
Var := Price * (1 - Discount/100)

Finished := not Done or A_Index > 100
if not Finished
{
    FileAppend, %NewText%`n, %TargetFile%
    return
}
else
    ExitApp


#NoTrayIcon

不显示一个托盘图标。

#NoTrayIcon

在一个脚本的任何位置指定它，当脚本被运行时将防止那个脚本托盘图标的显示（即使脚本被编译进一个EXE）。

如果你在一个有热键的脚本使用它，你也许应该捆绑一个热键到 ExitApp 命令。否则，将没有简单的方法退出程序（除了重启计算机或者终止进程）。例如：#x::ExitApp

托盘图标能在脚本运行的任何时候通过使用命令 menu, tray, Icon 或者 menu, tray, NoIcon 来使其消失或再现。在脚本的最顶端使用 menu , tray, NoIcon 的唯一缺点是托盘图标可能在脚本一开始运行时短暂地可见。要避免这种情况，用 #NoTrayIcon 代替。

如果托盘图标当前被隐藏，内置变量 A_IconHidden 为1，或者反之为0。

相关命令

Menu, ExitApp

范例

#NoTrayIcon


#SingleInstance

在一个脚本已经运行时决定是否允许它再次运行。

#SingleInstance [force|ignore|off]

参数

force|ignore|off

这个参数决定了脚本的上个实例正在运行时，启动该脚本将会发生的动作：

单词 FORCE 将跳过对话框，并自动地替换旧的实例，其实际上同 Reload 命令相似。

单词 IGNORE 将跳过对话框，并让旧的实例运行。也就是说，试图启动一个已运行的脚本将被忽略。

单词 OFF 允许多个脚本实例同时运行。

如果这个参数被省略，将显示一个对话框，询问是保持旧的实例还是使用新的实例来替换它。

注意

一个包含 hotkeys 、hotstrings 、#Persistent 、OnMessage() 或者 Gui 命令的脚本，默认是单实例的。使用上述方法能取消或修改这一特性。

相关命令

Reload, #Persistent

示例

#SingleInstance force
#SingleInstance ignore
#SingleInstance off


AutoTrim

设置在 "Var1 = %Var2%" 这样的语句中进行赋值时是否忽略 Var2 的前导和尾随空格和 tab.

AutoTrim, On|Off

参数

On|Off

On: 在类似 Var1 = %Var2% 这样的语句中, 赋值给 Var1 时忽略 Var2 中的前导和尾随 tab 和空格. 这是默认设置.

Off: 不忽略这样的 tab 和空格. 然而, 不论这个设置如何, 都会忽略任何字面上的 tab 和空格 (包括 `t). 例如, Var1 = `t%Var2% 语句总是忽略 `t 字符. 为了避免此问题, 请使用如下方式之一:

Var1 = %A_Tab%%Var2%%A_Space%  ; AutoTrim 必须为 OFF 时此语句才有效.
Var1 := "`t" . Var2 . " "  ; AutoTrim 的设置对此语句没有影响, 因为它是 表达式.

备注

如果没有在脚本中使用此命令, 那么此默认设置为 ON.

内置变量 A_AutoTrim 包含了此命令当前的设置 (On 或 Off).

内置变量 A_Space 和 A_Tab 分别包含单个空格和单个 tab 字符.

AutoTrim 对诸如 Var := " string " 这样的 表达式赋值 没有影响. 换句话说, 在这种情况下总是会保留前导和尾随空格和 tab.

每个新运行的 线程 (例如 热键, 自定义菜单项 或 定时 子程序) 都会以此命令的默认设置开始. 通过在脚本的自动执行段 (脚本的顶部) 使用此命令可以改变这个默认设置.

相关

SetEnv

示例

AutoTrim, off
NewVar1 = %OldVar%  ; 如果 OldVar 包含前导和尾随空格, 那么 NewVar 也会包含它们.
NewVar2 = %A_Space%  ; 使用 AutoTrim off 的设置时, 可以用这种方式赋值单个空格.

Var1 := "`t" . Var2 . " "  ; AutoTrim 的设置对此语句没有影响, 因为它是 表达式.


CoordMode

为一些命令设置相对于激活窗口或屏幕的坐标模式。

CoordMode, ToolTip|Pixel|Mouse|Caret|Menu [, Screen|Relative]

参数

Param1 | ToolTip: 影响 ToolTip 。 Pixel: 影响 PixelGetColor 、PixelSearch 和 ImageSearch 。 Mouse: 影响 MouseGetPos 、Click 和 MouseMove/Click/Drag 。 Caret: 影响内置变量 A_CaretX 和 A_CaretY 。 Menu: 当为 "Menu Show" 命令指定坐标时影响它。
Param2 | 如果省略 Param2 ，默认对屏幕。 Screen: 坐标相对于桌面(整个屏幕)。 Relative: 坐标相对于激活的窗口。

注意

如果此命令没有使用，除了那些文档上有说明的命令外，所有的命令(例如 WinMove 和 InputBox) 都使用相对于激活窗口的坐标。

对于此命令来说，每个最近启动的 thread (例如一个 hotkey 、custom menu item 或 timed 子程序) 以新的默认设置开始。这个默认设置可以通过在自动执行部分(脚本的顶部)使用此命令来改变。

相关命令

Click, MouseMove, MouseClick, MouseClickDrag, MouseGetPos, PixelGetColor, PixelSearch, ToolTip, Menu

示例

CoordMode, ToolTip, Screen  ; 将 ToolTips 放置在相对于屏幕坐标的地方:
CoordMode, ToolTip  ; 和上面是一样的效果，因为 "screen" 是默认的。


Critical

Critical （关键线程）

防止 current thread （当前线程）被其他线程中断。

Critical [, Off]
Critical 50 ; 请看底部的注释 bottom of remarks.

如果第一个参数被省略（或者是 On），则 current thread （当前的线程）被设置为 Critical （关键线程）这就意味着他不会被其他的线程所中断。如果第一个参数是Off(或者0，在 1.0.48+ 版本中)，则当前的线程忽略 "Thread Interrupt" 的设置，立即被设置为可以中断的状态。

不同于 high-priority （高优先级线程），如果在Critical 状态的线程运行中产生了另一个事件，则该事件不会被忽略。例如，当用户按下一个热键 hotkey， 但该热键的线程正以 Critical 状态运行，这时用户按下的热键会被缓冲，直到当前的线程结束或者被设置为可以中断的非关键状 态，这时用户按下的热键才会被一个新的线程所执行。

一个处于 Critical 状态的线程也会被紧急事件所中断。紧急事件包括：1） OnExit 子 程序；2）任意一个监听的消息值小于0x312的 OnMessage() 函数（或是被这些消息所触发的 callback 函数）；3）任意一个被当前线程自己所间接触发的 （通过 SendMessage 或 DllCall 等函数所触发） 为了避免被这些函数的中断，可以临时的关闭这些函数。

当缓冲事件等待被线程执行时，使用"Critical Off"不能够立即中断当前的线程。相反，执行中断平均需要花费5毫秒。这样在中断前，至少在"Critical Off"下面的一行代码 99.999%可能会被执行。你可以通过利用 Sleep -1 或用 WinWait 等待一个不存在的窗口等方法，进行强制中断。

当一个 MsgBox 或者其他对话框显示时，会中断一个Critical状态的线程，而不同于 "Thread Interrupt"，线程会在对话框关闭时恢复Critical 状态。

关于如何保存和还原当前 Critical 的设置，请参考 A_IsCritical 。因为 Critical 状态是一个特殊设置的线程，当线程结束，接下来运行的线程或者重新运行的线程（如果有的话）不会再以Critical 状态运行。所以不需要在结束一个线程后再声明"Critical Off"。

如果在自动运行片段（也就是脚本的最上面的一段代码）没有声明 Critical ，所有的线程不会以 Critical 状态运行（尽管可以设置 "Thread Interrupt" 来实现）。相反，如果在自动运行片段声明了Critical 且不曾关闭Critical状态，则每个新运行的线程（如 hotkey，custom menu item （自定义菜单项）和 timed 子程序）都会以 Critical 状态运行。

"Thread NoTimers" 命令和 Critical 相似，除了他可以防止被 timers 所中断。

在v1.0.47 及其以后的版本中，设置 Critical 状态同时会对 current thread （当前线程 ）产生 SetBatchLines -1 效果。

在v1.0.47及其以后的版本中，第一参数 指定为一个正数（例如Critical 30 ），表示该线程为关键线程，但是也改变了检查 内部消息队列的间隔时间。如果第一个参数为On，会以默认16毫秒间隔检查，当参数为Off则以5毫秒间隔检查。增加推迟消息/事件的延时间隔，可 以给 current thread （当前线程 ）更多的时间来结束。这样可以减少因为“线程正在运行”而导致消息 OnMessage() 和 界面事件 GUI events 丢失的可能性。然而，例如 Sleep 和 WinWait 命令会默认检查消息而忽略这个设置（一个解决方案是 DllCall("Sleep", Uint, 500)）。注意：检 查消息的时间间隔增加的太多有可能减少各种事件的响应，如 GUI 窗口的重绘。

相关命令

Thread (command), Threads , #MaxThreadsPerHotkey, #MaxThreadsBuffer, OnMessage(), RegisterCallback(), Hotkey, Menu, SetTimer

示例

#space:: ; Win+Space hotkey.
Critical
ToolTip 在这个提示消失之前不会再有新的线程运行
Sleep 3000
ToolTip ; 关闭提示
return ; 热键子程序结束，以下的线程不会再以关键状态运行。


Edit

在关联编辑器中打开当前脚本进行编辑.

Edit

Edit 命令使用注册表中与 "edit" 操作关联的编辑器 (如果没有则为记事本) 打开当前脚本进行编辑. 然而, 如果已经有一个编辑器窗口中打开了这个脚本 (根据窗口标题判断), 那么会激活这个窗口而不打开编辑器的新实例.

在已编译脚本中执行此命令将没有效果.

相关提示, 可以在多种编辑器中启用 AutoHotkey 语法高亮 - 参见下面. 此外, 通过 这个例子 可以在任何编辑器中激活 AutoHotkey 命令的上下文相关帮助. 最后, 通过使用像 ISense 这样几乎可以在任何编辑器上工作的自动完成工具可以提升您的效率. 它监视您的输入并显示菜单和参数列表, 为您输入某些内容以及提醒您参数的顺序.

相关

Reload

示例

Edit ; 打开当前脚本进行编辑.
; 如果您编辑器的命令行用法像下面这样,
; 那么可以使用此脚本把它设置为 ahk 文件的默认编辑器:
;
;   Editor.exe "Full path of script.ahk"
;
; 当您运行这个脚本时, 它会提示您
; 选择您编辑器的可执行文件.
;
FileSelectFile Editor, 2,, Select your editor, Programs (*.exe)
if ErrorLevel
    ExitApp
RegWrite REG_SZ, HKCR, AutoHotkeyScript\Shell\Edit\Command,, "%Editor%" "`%1"

带有 AutoHotkey 支持的编辑器

SciTE4AutoHotkey 被称为 SciTE 文本编辑请的自定义版本, 为 AutoHotkey 脚本量身订制的. 其特性包括:

  • 语法高亮
  • 智能自动缩进
  • 自动完成
  • 调用提示 (也称为智能感应)
  • 代码折叠
  • 支持 交互式调试
  • 辅助编写 AutoHotkey 脚本的其他工具

可以从此处找到 SciTE4AutoHotkey: http://www.autohotkey.com/forum/topic58820.html

支持 AutoHotkey 语法高亮的 其他编辑器:

  • AkelPad - http://www.autohotkey.com/forum/topic23586.html
  • Crimson Editor - http://www.autohotkey.com/forum/topic5506.html
  • Eclipse, FAR manager 和任何使用 Colorer take5 的编辑器 - http://www.autohotkey.com/forum/topic10378.html
  • Emacs - http://www.autohotkey.com/wiki/index.php?title=Emacs
  • Notepad++ - http://www.autohotkey.com/forum/topic58792.html
  • Notepad2 - http://www.autohotkey.com/forum/viewtopic.php?t=37652
  • PSPad - http://www.autohotkey.com/forum/topic9294.html
  • SciTE 或其他基于 Scintilla 的编辑器 - http://www.autohotkey.com/forum/topic9656.html
  • Sublime Text Editor - http://www.autohotkey.com/forum/viewtopic.php?p=368326#368326
  • Total Commander 的 Synplus 插件 - http://www.autohotkey.com/forum/topic7278.html

此外, AutoHotkey Basic (http://www.autohotkey.com/download/) 的 zip 下载包中含有在下列编辑器中激活语法高亮的文件. 然而, 其中一些文件严重过时, 所以可能有效也可能无效:

  • ConTEXT
  • EditPlus
  • EmEditor
  • jEdit
  • MED
  • TextPad
  • UltraEdit
  • Vim

如果您最喜爱的编辑器没有在这里列出来, 那么搜索 论坛 试试您的运气.

要添加一个编辑器到此页面, 请通过论坛 联系 Lexikos.


ImageSearch

在屏幕某一区域中搜索图像。

ImageSearch, OutputVarX, OutputVarY, X1, Y1, X2, Y2, ImageFile

参数

OutputVarX/Y

变量名称，其可储存屏幕上所发现图像之左上像素之X坐标及Y坐标。(若未能搜索到图像，则变量为空)。坐标为相对于活动窗口的坐标，除非用 CoordMode 进行更改。

两参数之一或两者皆可留空，其中可用事件 ErrorLevel (参见下文)来确定是否搜索到匹配图像。
X1,Y1 | 欲搜索矩形范围之左上角的X坐标及Y坐标，其可为表达式。坐标是相对于活动窗口的坐标，除非用 CoordMode 进行更改。
X2,Y2 | 欲搜索矩形范围之右下角的X坐标及Y坐标，其可为表达式。坐标是相对于活动窗口的坐标，除非用 CoordMode 进行更改。
ImageFile

图像的文件名，若未指定绝对路径，则假定位于 %A_WorkingDir% 中。所有操作系统均支持 GIF、JPG、BMP、ICO、CUR、及ANI 图像 (BMP 图像必须为 16-bit 或更高)。其他图标资源包括以下类型的文件：EXE、DLL、CPL、SCR、及包含图标资源的其他类型。在 Windows XP 或更高版本中，可支持诸如 PNG、TIF、Exif、WMF、及 EMF 等其他图像格式。低于 XP 版本的操作系统亦可通过以下方法支持这些图像格式：即，将微软公司的免费 GDI+ DLL 拷贝至 AutoHotkey.exe 文件夹中(但当为编译的脚本 (compiled script)时，要将 DLL 拷贝至脚本文件夹中)。如欲下载 DLL，请在www.microsoft.com中搜索以下词语： gdi redistributable

Options: 亦可将零或更多个以下字符串直接置于文件名之前。每个选项用单个空格或制表符与下一选项分隔开。例如： *2 *w100 *h-1 C:\Main Logo.bmp

*IconN: 为使用不是在文件中排第一组的图标组，在 *Icon 后紧接指定的图标组编号。举例而言，*Icon2 将会加载第二图标组的默认图标。

*n (变化(variation)): 为 n 指定一个在 0 到 255 之间(包含255)的数字来表示在组成每个像素颜色的红、绿和蓝的饱和度的每个方向上允许变化的 shades(色调) 的数值。举例而言，*2 将容许 2 色调变化。当该图像之颜色发生轻微变化时，或当 ImageFile 使用一种诸如 GIF 或 JPG 等不能在屏幕上精确呈现图像之格式时，此参数有用。若指定 255 色调变化，则所有颜色皆将匹配。默认值为 0 色调。

*TransN: 此选项通过在图像中指定一种可与屏幕上任一颜色相匹配的颜色而促使更易于发现匹配图像。其通常用于寻找具有一些透明区域的 PNG、GIF、及 TIF 文件（然而，图标不需要此选项，此乃因对其透明性是自动支持的）。对于 GIF 文件，*TransWhite 很可会起作用。对于 PNG 及 TIF 文件，*TransBlack 可能最好。除此以外，可为 N 指定一些其他颜色名或 RGB 值(请参见 颜色表(color chart) 中的说明，或以 RGB 模式使用 PixelGetColor。) 实例：*TransBlack, *TransFFFFAA, *Trans0xFFFFAA

*wn 及 *hn: 缩放该图像的宽度及高度(此宽度及高度亦可决定自多图标 .ICO 文件中加载哪个图标)。若这两个选项均省略，则自 ICO、DLL、或 EXE 文件加载的图标会被缩放至系统默认的小图标大小，其通常为16 X 16(你可通过指定 *w0 *h0来强制使用实际/固有(actual/internal)大小)。非图标图像以其实际大小加载。为在保持图像纵横比的前提下缩小或放大图像，可将高宽两个尺度之一指定为 -1 ，而将另一尺度指定为正值。举例而言，指定 *w200 *h-1 将使图像的宽度为 200 像素，并对其高度进行自动设定。

ErrorLevel

若在指定区域发现了该图像，则将 ErrorLevel 设定为 0 ，若未发现，则设为 1 ，若存在阻止命令执行搜索的问题(例如未能打开该图像文件或格式设置出错的选项)，则设为 2 。

注意

ImageSearch 可用于在屏幕上查找缺少文本或其文本不易被检索到的图形目标。例如，其可用于查找图形按钮、图标、网页链接、或游戏目标的位置。一旦定位，则可通过Click对这些目标进行点击。

某些时候可采用如下策略：搜索图像的一小块图像剪辑而不搜索整个图像。此方法可在图像发生整体性变化而其内部某些部分保持不变的情况下提高可靠性。一种提取图像剪辑的方法是：

  1. 当在活动的窗口中可以看到图像时按 Alt+PrintScreen。此操作可将屏幕截图置于剪贴板中。
  2. 打开诸如画图板等图像处理程序。
  3. 粘贴剪贴板中的内容(即屏幕截图)。
  4. 选择对该图像而言唯一且不变的区域。
  5. 拷贝并粘贴该区域至新图像文件。
  6. 将其保存为随 ImageSearch 使用的小文件。

为实现匹配，屏幕上的图像必须与经由 ImageFile 参数及其选项所加载的图像具有相同大小。

待搜索区域必须可见；换言之，不可能搜索隐藏在另一窗口后面之窗口的区域。通过比较，通常能够探查到部分位于鼠标光标下面的的图像。例外情况是游戏光标，其在大多数情况下会遮住位于其下面的任何图像。

由于搜索自该区域的顶行开始向下移动，若存在一个以上的匹配图像，则将发现最接近顶部者。

包含透明色的图标会自动容许其颜色匹配屏幕上的任何颜色。因此，位于该图标后面之部分的颜色并不重要。

ImageSearch 可支持 8-bit 颜色的屏幕(256 色)或更高。

搜索行为可随显示适配卡的颜色深度(尤其对于 GIF 及 JPG 文件而言)发生变化。因此，若脚本将在多种颜色深度下运行，则最好在每种色深设置下皆进行测试。您可以使用变化色调选项(shades-of-variation option (*n) )来协助搜索行为在多种颜色深度下保持连续性。

若屏幕上的图像是半透明的，则 ImageSearch 可能会无法找到它。在此情况下，可尝试使用变化色调选项 (*n) 或通过 WinSet, Transparent, Off 使窗口临时不透明。

相关命令

PixelSearch, PixelGetColor, CoordMode, MouseGetPos

示例

ImageSearch, FoundX, FoundY, 40,40, 300, 300, C:\My Images\test.bmp CoordMode Pixel ; 将下面坐标表示为相对于屏幕而不是相对于所激活窗口的坐标。
ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenHeight, *Icon3 %A_ProgramFiles%\SomeApp\SomeApp.exe if ErrorLevel = 2 MsgBox 不能实施搜索。else if ErrorLevel = 1 MsgBox 未在屏幕上寻得图标。else MsgBox 在 %FoundX%x%FoundY% 处寻得图标。


ListLines

显示最近已运行过的各脚本行。

ListLines

注意

该命令与主窗口中"View->Lines most recently executed"菜单项的功能一致。该命令可帮助您 调试脚本。

做一个相关的提示，内置变量 A_LineNumber 和 A_LineFile 分别包含当前运行的行号和其所在的文件名称。

相关命令

KeyHistory, ListHotkeys, ListVars

示例

ListLines


ListVars

列出脚本中的变量：它们的名称和当前的内容。

ListVars

注意

此命令等同于选择了主窗口中的 "View->Variables" 菜单项。它可以帮你调试脚本。

列表的每一行由以下部分组成:
1) 变量名。
2) 变量内容的长度和变量的大小。例如: [50 of 63]
3) 变量内容的前 60 个字符。

如果该命令在一个函数中使用，这个函数的局部变量将首先列出(先于脚本的全局变量)。

已知的限制：如果一个函数(或者全局变量的列表本身)包含 10,000 个变量以上，此命令可能不会以准确的字母排列顺序来显示它们；也就是说，有些可能会在列表中丢失。

相关命令

KeyHistory, ListHotkeys, ListLines

示例

ListVars


Menu

创建, 删除, 修改和显示菜单和菜单项. 改变托盘图标和它的提示. 控制是否可以打开 已编译脚本 的主窗口.

Menu, MenuName, Cmd [, P3, P4, P5]

参数

MenuName | 它可以为 TRAY 或任何自定义菜单的名称. 首次和 Add 一起使用自定义菜单的名称时会自动创建此菜单. 例如: Menu, MyMenu, Add, Item1 创建后, 可以用 Show 命令显示自定义菜单. 通过 Add 命令, 它还可以作为一个子菜单附加到一个或更多的其他菜单上.
Cmd, P3, P4, P5 | 这 4 个参数彼此依赖. 参见下面的列表了解允许的组合.

添加或改变菜单项

Add [, MenuItemName, Label-or-Submenu, Pn]: 此命令有多种用途, 包括添加菜单项, 使用新的子菜单或标签更新菜单项或把普通菜单项转换成子菜单项 (或相反). 如果 MenuItemName 还不存在, 它将被添加到菜单. 否则, 将使用指定的 Label-or-Submenu 更新 MenuItemName.

要添加一个菜单分隔线, 忽略所有三个参数.

当用户选择菜单项时标签子程序作为一个新 线程 运行 (类似于 Gosub 和 热键子程序). 如果省略 Label-or-Submenu, 那么将使用 MenuItemName 同时作为标签和菜单项名称.

要让 MenuItemName 变成子菜单 -- 在选择时打开一个新菜单的菜单项 -- 在 Label-or-Submenu 中指定一个冒号后面跟着一个现有自定义菜单的 MenuName. 例如:

Menu, MySubmenu, add, Item1
Menu, tray, add, This Menu Item Is A Submenu, :MySubmenu

最后一个参数可以包含字母 P 后面跟着菜单的 线程优先级, 例如 P1. 如果添加菜单项时省略此参数, 优先级将为 0, 这是标准的默认值. 如果在更新菜单项时省略, 菜单项的优先级将不会被改变. 要改变一个现有菜单项的优先级, 省略 Label-or-Submenu 参数. 使用一个十进制 (不是十六进制) 数表示优先级.

Delete [, MenuItemName]: 从菜单中删除 MenuItemName. 标准菜单项例如 Exit (参见下面) 不能被单独删除. 如果删除了 default 菜单项, 效果类似于使用了 NoDefault 选项. 如果省略了 MenuItemName, 整个 MenuName 菜单将被删除, 同时删除在其他菜单中名称为 MenuName 的任何子菜单项.

DeleteAll: 从菜单中删除所有自定义菜单项, 如果没有包含 标准 菜单项 (参见下面) 时则使菜单留空. 与使用 Delete 命令 (参见上面) 完全删除菜单不同, 一个空菜单仍然存在, 因此其他任何包含此菜单项作为子菜单的菜单仍保留这些子菜单.

Rename, MenuItemName [, NewName]: 改变 MenuItemName 为 NewName (如果 NewName 为空, MenuItemName 将转变成一条分隔线). NewName 不能和任何现有的自定义菜单项名称相同. 菜单项的当前目标标签或子菜单不会改变.

Check, MenuItemName: 在 MenuItemName 前添加一个可见的复选标记 (如果还没有的话).

Uncheck, MenuItemName: 从 MenuItemName 中移除复选标记 (如果有的话).

ToggleCheck, MenuItemName: 如果没有则添加一个复选标记; 否则, 移除它.

Enable, MenuItemName: 如果之前禁用了 (变灰) MenuItemName, 允许用户再次选择它.

Disable, MenuItemName: 使 MenuItemName 变成灰色以表示用户无法选择它.

ToggleEnable, MenuItemName: 如果之前启用了 MenuItemName 则禁用它; 否则启用它.

Default [, MenuItemName]: 改变菜单的默认项为 MenuItemName 并加粗其字体 (当前在 TRAY 以外的菜单中设置默认项只是改变外观而已). 当用户双击托盘图标时, 会运行其默认菜单项. 如果没有默认项, 则双击没有效果. 如果省略了 MenuItemName, 效果等同于使用了下面的 NoDefault.

NoDefault: 对于托盘菜单: 让菜单恢复其默认菜单项, 对于未编译脚本为 OPEN 而 已编译脚本 则没有 (除非 MainWindow 选项有效). 如果因为之前使用了下面的 NoStandard 命令使得 OPEN 菜单项不存在, 那么将没有默认项, 因此双击托盘图标没有效果. 对于 TRAY 以外的其他菜单: 任何现有的默认项恢复为非加粗字体.

Standard: 在菜单底部插入标准菜单项 (如果还不存在的话). 此命令可用于托盘菜单或任何其他菜单.

NoStandard: 从托盘菜单移除所有标准 (非自定义) 的菜单项 (如果存在的话).

设置或移除一个菜单项的图标 [AHK_L 17+]

Icon, MenuItemName, FileName [, IconNumber, IconWidth]: 设置 MenuItemName 的图标. FileName 可以为一个图标文件或 AutoHotkey 支持的格式的任何图像. 要使用文件中首个外的其他图标组, 在 IconNumber 中指定其编号 (如果省略, 默认值为 1). 此外, 可以使用负数作为 资源标识符. 在 IconWidth 中指定期望的图标宽度. 如果 IconNumber 表示的图标组包含多种大小的图标, 则使用最接近的匹配并将图标调整到特定的大小. 参见示例段中的用法示例.

目前在 Windows Vista 和更高版本系统中如果需要设置的图标保留透明度则必须指定 "真实的大小". 例如:

Menu, MenuName, Icon, MenuItemName, Filename.png,, 0

NoIcon, MenuItemName: 移除 MenuItemName 的图标, 如果有的话.

改变托盘的图标或提示 (MenuName 必须为 TRAY)

Icon [, FileName, IconNumber, 1]: 将脚本的图标改变为 FileName 中图标的某个. 支持下列的文件类型: ICO, CUR, ANI, EXE, DLL, CPL, SCR 以及其他包含图标资源的类型. 要使用文件中首个外的其他图标组, 在 IconNumber 中指定其编号 (如果省略, 默认值为 1). 例如, 2 将加载第二个图标组中的默认图标. 此外, 在 AutoHotkey_L 中, 可以使用负数作为资源标识符. 在 FileName 中指定星号 (*) 来恢复脚本到其默认图标.

最后一个参数: 在最后一个参数中指定 1 来冻结图标, 而 0 则解冻它 (或留空来保持冻结/解冻状态不变). 当图标已经冻结时, Pause 和 Suspend 命令不会改变它. 注意: 要冻结 当前的 图标, 请使用 1, 例如: Menu, Tray, Icon,,, 1

改变托盘图标同时也改变由 InputBox, Progress 和后续创建的 GUI 窗体显示的图标. 已编译脚本 即使在编译时指定一个自定义图标也会受到影响. 注意: 如果之前使用如 #NoTrayIcon 隐藏了托盘图标, 改变图标将不会让它显示; 要让它显示, 使用 Menu, Tray, Icon (不带参数).

从 .ICO 外的其他类型文件中加载托盘图标时可能产生轻微的变形. 尤其是 16x16 的图标. 要避免这种情况, 把想要的托盘图标保存到 .ICO 文件中.

操作系统的 DLL 和 CPL 文件包含的一些图标可能会有用. 例如: Menu, Tray, Icon, Shell32.dll, 174 ; 省略 DLL 文件的路径以便它也适用于 Windows 9x.

内置变量 A_IconNumber 和 A_IconFile 包含了当前图标的编号和名称 (带有完整路径) (如果为默认图标则两者都为空).

Icon (不带参数): 如果还没有托盘图标则创建它. 如果在脚本中使用了 #NoTrayIcon, 则此命令将覆盖它.

NoIcon: 如果存在托盘图标则移除它. 如果在脚本的最顶部使用此命令, 当脚本运行时托盘图标可能出现短暂的时间. 要避免这种情况, 使用 #NoTrayIcon 代替. 如果托盘图标当前是隐藏的那么内置变量 A_IconHidden 值为 1 否则为 0.

Tip [, Text]: 改变托盘图标的提示 -- 这是在鼠标悬停在托盘图标上时显示的. 要创建多行提示, 在每行之间使用换行符 (`n), 例如 Line1`nLine2. 仅显示 Text 中的前 127 个字符. 如果省略了 Text, 则提示恢复为其默认文本. 内置变量 A_IconTip 包含了当前提示的文本 (如果文本是默认的则为空).

杂项命令

Show [, X, Y]: 显示 MenuName, 允许用户使用方向键, 菜单快捷键 (下划线字母) 或鼠标选择菜单项. 可以显示包括托盘菜单在内的任何菜单, 但 GUI 菜单栏例外. 如果 X 和 Y 都省略, 则菜单显示在鼠标指针当前位置. 如果仅其中一个省略, 则用鼠标指针的位置代替省略的这个. X 和 Y 都相对于活动窗口. 预先指定 "CoordMode, Menu" 可以让它们相对于整个屏幕.

Color, ColorValue [, Single]: 改变菜单的背景颜色为 ColorValue, 它是 16 种 HTML 基础颜色之一或是 6 位的 RGB 颜色值 (参见 颜色图表). 将 ColorValue 留空 (或指定单词 Default) 来恢复菜单的默认颜色. 如果后一个参数不是单词 Single, 则任何附加到此菜单的子菜单都将改变颜色. 此命令在 Windows 95/NT 上无效.

Click, ClickCount: 在 ClickCount 中指定 1 来允许单击激活托盘菜单的默认菜单项. 在 ClickCount 中指定 2 来恢复到默认行为 (双击). 例如: Menu, Tray, Click, 1

MainWindow: 此命令仅影响 已编译脚本. 它允许通过托盘图标打开脚本主窗口, 否则这是不行的. 它同时也启用了主窗口的 View 菜单项例如 "Lines most recently executed", 这样就允许查看脚本的源代码和其他信息. MenuName 必须为 TRAY.

NoMainWindow (默认): 此命令仅影响 已编译脚本. 它恢复脚本的默认行为, 即阻止打开主窗口. 即使此选项有效, 脚本运行中遇到下列命令时仍然会显示主窗口: ListLines, ListVars, ListHotkeys 和 KeyHistory. MenuName 必须为 TRAY.

UseErrorLevel [, off]: 如果脚本中从未使用过此选项, 其默认为 OFF. 每当 Menu 命令遇到错误时, OFF 设置会显示一个对话框并终止 当前线程. 指定 Menu, Tray, UseErrorLevel 以阻止对话框的显示和线程的终止; 作为替代, 如果出现错误 ErrorLevel 被设置为 1 否则为 0. 要让此选项转回 off, 在后一个参数中指定 OFF. 此设置是全局的, 这意味着它影响所有菜单, 而不仅 MenuName.

备注

要给 一个 菜单项名称中的某个字母加下划线, 那么在这个字母前加一个 & 符号. 当菜单显示时, 通过按下键盘上相应的按键可以选择这样的菜单项. 要显示一个原义的 & 符号, 指定两个连续的 & 符号, 例如: Save && Exit

菜单和菜单项的名称长度最多可达 260 个字符.

引用一个现有的菜单或菜单项时, 名称不区分大小写但必须包含 & 符号. 例如: &Open

使用 Menu, tray, add (即省略其他所有参数) 可以给菜单添加分隔线. 不过, 当前不能单独删除分隔线. 要变通解决此问题, 可以使用 Menu, tray, DeleteAll 然后重新添加自定义菜单项.

新的菜单项总是添加到菜单的底部. 对于托盘菜单: 要把您的菜单项放到标准菜单项的上面, (在添加完自定义菜单项后) 执行 Menu, tray, NoStandard, 接着执行 Menu, tray, Standard.

不能使用任何菜单子命令单独地操作标准菜单项, 例如 "Pause Script" 和 "Suspend Hotkeys".

如果一个菜单项已完全变成空的 -- 例如使用 Menu, MyMenu, DeleteAll -- 则它无法被显示. 如果托盘菜单变成空的, 右击和双击托盘菜单将没有效果 (此时通常使用 #NoTrayIcon 更好).

如果一个菜单项的子程序已经运行而用户再次选择相同的菜单项, 将创建一个新 线程 运行相同的子程序, 并中断之前的线程. 想要缓冲这样的事件到以后执行, 在子程序的首行使用 Critical (不过, 这样也将缓冲/延迟其他线程例如按下的热键).

每当通过菜单项运行子程序时, 它会使用设置例如 SendMode 的默认值开始. 这些默认值可以在 自动执行段 改变.

内置变量 A_ThisMenuItem 和 A_ThisMenuItemPos 分别包含了最近用户选择的自定义菜单项的名称和位置 (如果没有则为空). 同样地, A_ThisMenu 是选择的 A_ThisMenuItem 的菜单名称. 当创建的菜单内容不总是相同时这些变量很有用. 在这种情况下, 通常最好把所有这样的菜单项指向相同的标签并让此标签引用上面的变量来决定执行什么动作.

要让非热键, 非 GUI 脚本持续运行 -- 例如仅包含自定义菜单或菜单项的脚本 -- 使用 #Persistent.

相关

GUI, 线程, Thread, Critical, #NoTrayIcon, Gosub, Return, SetTimer, #Persistent

示例

; 示例 #1: This is a working script that adds a new menu item to the bottom of the tray icon menu.

#Persistent ; Keep the script running until the user exits it.
Menu, tray, add ; Creates a separator line.
Menu, tray, add, Item1, MenuHandler ; Creates a new menu item.
return MenuHandler: MsgBox You selected %A_ThisMenuItem% from menu %A_ThisMenu%. return

; 示例 #2: This is a working script that creates a popup menu that is displayed when the user presses the Win-Z hotkey.

; Create the popup menu by adding some items to it.
Menu, MyMenu, Add, Item1, MenuHandler Menu, MyMenu, Add, Item2, MenuHandler Menu, MyMenu, Add ; Add a separator line.

; Create another menu destined to become a submenu of the above menu.
Menu, Submenu1, Add, Item1, MenuHandler Menu, Submenu1, Add, Item2, MenuHandler

; Create a submenu in the first menu (a right-arrow indicator). When the user selects it, the second menu is displayed.
Menu, MyMenu, Add, My Submenu, :Submenu1 Menu, MyMenu, Add ; Add a separator line below the submenu.
Menu, MyMenu, Add, Item3, MenuHandler ; Add another menu item beneath the submenu.
return ; End of script's auto-execute section.

MenuHandler: MsgBox You selected %A_ThisMenuItem% from the menu %A_ThisMenu%. return #z::Menu, MyMenu, Show ; i.e. press the Win-Z hotkey to show the menu.

; 示例 #3: This is a working script that demonstrates some of the various menu commands.

#Persistent #SingleInstance menu, tray, add ; separator
menu, tray, add, TestToggle&Check menu, tray, add, TestToggleEnable menu, tray, add, TestDefault menu, tray, add, TestStandard menu, tray, add, TestDelete menu, tray, add, TestDeleteAll menu, tray, add, TestRename menu, tray, add, Test return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TestToggle&Check: menu, tray, ToggleCheck, TestToggle&Check menu, tray, Enable, TestToggleEnable ; Also enables the next test since it can't undo the disabling of itself.
menu, tray, add, TestDelete ; Similar to above.
return TestToggleEnable: menu, tray, ToggleEnable, TestToggleEnable return TestDefault: if default = TestDefault { menu, tray, NoDefault default = } else { menu, tray, Default, TestDefault default = TestDefault } return TestStandard: if standard <> n { menu, tray, NoStandard standard = n } else { menu, tray, Standard standard = y } return TestDelete: menu, tray, delete, TestDelete return TestDeleteAll: menu, tray, DeleteAll return TestRename: if NewName <> renamed { OldName = TestRename NewName = renamed } else { OldName = renamed NewName = TestRename } menu, tray, rename, %OldName%, %NewName% return Test: MsgBox, You selected "%A_ThisMenuItem%" in menu "%A_ThisMenu%". return
; 示例 #4: This is a working script that adds icons to its menu items.
Menu, FileMenu, Add, Script Icon, MenuHandler Menu, FileMenu, Add, Suspend Icon, MenuHandler Menu, FileMenu, Add, Pause Icon, MenuHandler Menu, FileMenu, Icon, Script Icon, %A_AhkPath%, 2 ;Use the 2nd icon group from the file
Menu, FileMenu, Icon, Suspend Icon, %A_AhkPath%, -206 ;Use icon with resource identifier 206
Menu, FileMenu, Icon, Pause Icon, %A_AhkPath%, -207 ;Use icon with resource identifier 207
Menu, MyMenuBar, Add, &File, :FileMenu Gui, Menu, MyMenuBar Gui, Add, Button, gExit, Exit This Example Gui, Show MenuHandler: Return Exit: ExitApp


OutputDebug

发送字符串到调试器(如果有的话)以显示。

OutputDebug, Text

参数

Text 要发送到调试器以显示的文本。此文本可以包含换行符(`n)来启用新的一行。另外，单个较长的行可以通过连续部分分解为多个较短的部分。

注意

如果脚本运行进程中没有设置调试器，那么系统调试器会显示该字符。如果系统调试器未激活，此命令就不起什么作用了。

DebugView 是一个样本调试器，其免费并且可从 www.sysinternals.com 获取。

也可参考：其他调试方法

相关命令

FileAppend, continuation sections

示例

OutputDebug, %A_Now%: 由于窗口 "%TargetWindowTitle%" 不存在，进程被终止。


PixelGetColor

获取指定的 x,y 坐标处像素的颜色.

PixelGetColor, OutputVar, X, Y [, Alt|Slow|RGB]

参数

OutputVar | 变量名称, 用于保存十六进制的蓝绿红 (BGR) 格式的颜色 ID. 例如, 紫色的颜色 ID 为 0x800080, 因为其蓝色和红色通道的强度为 80, 而绿色通道的强度为 00.
X, Y | 目标像素的 X 和 Y 坐标, 可以为 表达式. 如果没有使用 CoordMode, 默认情况下坐标相对于活动窗口.
Alt|Slow|RGB | 此参数可以包含零个或多个下列单词.如果含有多个单词, 它们之间请用空格分隔 (例如 Alt RGB). Alt [v1.0.43.10+]: 用另一种方法获取颜色, 当在特殊类型的窗口中正常的方法获取到无效或错误的颜色时, 应考虑使用这种方法.此方法比正常方法大约慢 10%. Slow [v1.0.43.10+]: 使用一种更精细复杂的方法获取颜色, 在某些全屏应用程序中其他方法失败时, 此方法可能有效. 此方法比正常方法大约慢三倍. 请注意: Slow 方法优先于 Alt 方法, 所以此时不需要指定 Alt. RGB: 获取 RGB 格式的颜色值而不是 BGR 格式. 即交换了其中的红色和蓝色的通道. 要让获取的颜色适用于 WinSet, Gui, Progress, 和 SplashImage, 这很有用.

ErrorLevel

如果出现错误, ErrorLevel 被设置为 1, 否则为 0.

备注

像素必须是可见的; 换句话说, 无法获取隐藏在其他窗口背后的窗口的像素颜色. 而在鼠标指针下方的像素颜色通常可以被检测出来. 例外情况是游戏的指针, 在大多数情况下它会隐藏在它下方的任何像素.

使用 Window Spy (从托盘图标菜单打开) 或者参照本页底部的示例可以确定当前屏幕上的颜色.

已知的局限:

  • 在 部分透明 或其中某种颜色透明 (TransColor) 的窗口中实际获取的是它后面窗口的颜色而不是它自己的颜色..
  • 在某些应用程序中 PixelGetColor 可能得不到准确的结果. 如果发生这种情况, 请尝试在最后那个参数中指定单词 Alt 或 Slow.

相关

PixelSearch, ImageSearch, CoordMode, MouseGetPos

示例

^!z::  ; Control+Alt+Z hotkey.
MouseGetPos, MouseX, MouseY
PixelGetColor, color, %MouseX%, %MouseY%
MsgBox The color at the current cursor position is %color%.
return


PixelSearch

在屏幕的一个区域中搜索指定颜色所在的像素.

PixelSearch, OutputVarX, OutputVarY, X1, Y1, X2, Y2, ColorID [, Variation, Fast|RGB]

参数

OutputVarX/Y | 变量名称, 用于保存首个匹配 ColorID 的像素的 X 和 Y 坐标(如果没发现匹配, 此变量被置空). 如果没有使用 CoordMode, 默认情况下坐标相对于活动窗口. 这两个参数中其中一个或两个可以为空, 此时使用 ErrorLevel (见后面) 可以确定是否找到匹配.
X1, Y1 | 需要搜索的矩形区域左上角的 X 和 Y 坐标, 可以为 表达式. 如果没有使用 CoordMode, 默认情况下坐标相对于活动窗口.
X2, Y2 | 需要搜索的矩形区域右下角的 X 和 Y 坐标, 可以为 表达式.如果没有使用 CoordMode, 默认情况下坐标相对于活动窗口.
ColorID | 需要搜索的十进制或十六进制颜色 ID, 使用蓝绿红 (BGR) 格式, 可以为 表达式. 颜色 ID 可以使用 Window Spy (可以从托盘菜单打开) 或 PixelGetColor 确定. 例如: 0x9d6346
Variation | 一个介于 0 和 255 (包含的) 之间的数字, 用于表示此颜色红/绿/蓝通道强度在每个方向上允许的渐变值 (可以为 表达式). 此参数用于需要寻找的颜色渐变值可能变化时. 如果指定 255 为浮动的渐变值, 将匹配所有颜色. 默认渐变值为 0.
Fast|RGB | 此参数可以包含单词 Fast, RGB, 或同时包含两个 (同时包含时它们之间请用空格分隔即 Fast RGB). Fast: 使用快速的搜索方法, 在大多数情况下此方法可以明显减少搜索时消耗的 CPU 时间. 尽管此方法支持颜色深度低至 8位 (256色), 但在 24位或 32位颜色深度下此快速方法执行的更好. 如果屏幕的颜色深度为 16 位或更低, Variation 参数在慢速模式和快速模式的行为可能会有轻微的差异. 最后, 快速模式按行搜索屏幕(从上往下)而不是按列. 因此,如果屏幕上有多个匹配的像素, 快速模式可能找到一个和慢速模式不同的像素. RGB: 把 ColorID 解释为 RGB 值而不是 BGR. 即交换了其中的红色和蓝色的通道.

ErrorLevel

如果在指定的区域找到指定的颜色, 则 ErrorLevel 被设置为 0, 没有找到则设置为 1, 而如果在命令执行过程中遇到问题使搜索无法进行则设置为 2.

备注

搜索的目标区域必须是可见的; 换句话说, 无法搜索隐藏在其他窗口背后的窗口区域.而在鼠标指针下方的像素颜色通常可以被检测出来.例外情况是游戏的指针, 在大多数情况下它会隐藏在它下方的任何像素.

对于慢速模式: 默认情况下从区域左上角的像素开始搜索, 在垂直方向上检查下面所有像素以寻找匹配. 如果没有找到匹配, 继续往右逐列搜索, 直至找到一个匹配的像素. 通过交换参数列表中 X1 和 X2 的位置, 可以使默认的从左往右搜索反向进行. 换句话说, 如果 X1 大于 X2, 搜索从右往左进行, 从 X1 开始. 同样, 如果 Y1 大于 Y2, 则从区域底部而不是顶部开始搜索每列像素. 最后, 当需要搜索的目标区域很大而且快速的重复搜索, 这可能会占用大量的 CPU 时间. 为了减轻这种情况, 请保持目标区域的大小为最小值.

相关

PixelGetColor, ImageSearch, CoordMode, MouseGetPos

示例

PixelSearch, Px, Py, 200, 200, 300, 300, 0x9d6346, 3, Fast
if ErrorLevel
    MsgBox, That color was not found in the specified region.
else
    MsgBox, A color within 3 shades of variation was found at X%Px% Y%Py%.


SetEnv

SetEnv (Var = Value)

为一个 变量 赋值。

SetEnv, Var, Value
Var = Value

参数

Var | 变量 的名称。变量中存储了指定的 值 。
Value | 需要存储的值，可以是字符串或数字。如果字符串太长，可以使用 continuation section/字符串分段 的方法将它分为几个短小的段落，这样可以增加代码的可读性和可维护性。

注意

默认情况下，任何在 值 的开头和结尾处的空格和Tab是被忽略的，不会存入变量中。要避免这种情况，可以在赋值之前使用 AutoTrim Off 命令。但是，Tab在任何情况下都是被忽略的。要想保留Tab，可以使用内置变量 %A_Tab% 。

命令的名字“SetEnv”容易使人产生误解，保留它仅仅是为了兼容 AutoIt v2 。和 AutoIt v2 不同，AutoHotkey 并不将变量存储在系统环境中，因为这样性能比较差而且系统限制这样的变量最大为 32K 。使用 EnvSet 命令来设置一个 环境变量 ，而不是 SetEnv 。

可以设置变量为空来释放它所占用的内存。例如 var = 。

这个命令，以及所有接收 OutputVar 参数的命令都可以创建一个 数组 ，只要让 OuputVar 包含一个对其它变量的引用就行了。例如 array%i% = 123 。查看 数组 获取更多信息。

相关命令

AutoTrim, EnvSet, EnvAdd, EnvSub, EnvMult, EnvDiv, If, Arrays

示例

Var1 = This is a string.
Color2 = 450
Color3 = %Var1%
Array%i% = %A_TICKCOUNT%


SysGet

获取屏幕分辨率、多监视器信息、系统对象的尺寸以及其他系统属性。

SysGet, OutputVar, Sub-command [, Param3]

参数

OutputVar | 用于存放结果的变量名。
Sub-command | 参见下表。
Param3 | 除非在下面有注明，否则省略该参数。

Sub-commands

MonitorCount: 获取监视器的总数。与下表提到的 SM_CMONITORS 不同，MonitorCount 包括所有的监视器，甚至是那些没有被用作桌面一部分的监视器。在 Windows 95/NT 中该数总是为 1 。

MonitorPrimary: 获取主监视器的数量，单监视器系统中该值为 1 。在 Windows 95/NT 中主监视器总是为 1 。

Monitor [, N] : 获取监视器 N (如果 N 省略，将使用主监视器)的边界坐标。此信息将被存储于以 OutputVar 开头的 4 个变量内。如果 N 太高或接收信息时有问题，所有变量将被置空。举个例子：
SysGet, Mon2, Monitor, 2
MsgBox, 左: %Mon2Left% -- 上: %Mon2Top% -- 右: %Mon2Right% -- 下 %Mon2Bottom%.

在一个 函数 中，要创建一组全局而非局部的变量，则在使用此命令前先将 Mon2 声明为全局变量。(相反在 assume-global 函数中同样如此)。

MonitorWorkArea [, N]: 同上，不过该区域不包括任务栏及其他已注册的桌面工具栏。

MonitorName [, N]: 监视器 N(如果 N 省略，将使用主监视器)的操作系统名称。

(数值): 指定 Sub-command 为下表中的一个数来接收相应的值。以下的例子会将鼠标按钮数储存到名为 "MouseButtonCount" 的变量里：
SysGet, MouseButtonCount, 43

常用的

数值 | 说明
80 | SM_CMONITORS: 桌面上的监视器个数(不包括 "non-display pseudo-monitors(不显示的伪监视器)")。Windows 95/NT: 接收到的值总是 0 。
43 | SM_CMOUSEBUTTONS: 鼠标按钮数(未安装鼠标则为 0 )。
16, 17 | SM_CXFULLSCREEN, SM_CYFULLSCREEN: 主监视器上全屏窗口的客户区长宽，以像素为单位。
61, 62 | SM_CXMAXIMIZED, SM_CYMAXIMIZED: 主监视器上已最大化的顶层窗口的默认尺寸，以像素为单位。
59, 60 | SM_CXMAXTRACK, SM_CYMAXTRACK: 具有标题栏和边框的窗口的默认最大尺寸，以像素为单位。 相当于整个桌面的尺寸。用户拖动一个窗口的边框不可超出这个尺寸。
28, 29 | SM_CXMIN, SM_CYMIN: 一个窗口的最小宽高，以像素为单位。
57, 58 | SM_CXMINIMIZED, SM_CYMINIMIZED: 已最小化窗口的尺寸，以像素为单位。
34, 35 | SM_CXMINTRACK, SM_CYMINTRACK: 一个窗口的最小跟踪宽度，以像素为单位。用户拖动一个窗口的边框不可小于这个尺寸。 一个窗口可以通过处理 WM_GETMINMAXINFO 消息来覆盖这些值。
0, 1 | SM_CXSCREEN, SM_CYSCREEN: 主监视器屏幕的宽高，以像素为单位。这些值与内置变量 A_ScreenWidth 和 A_ScreenHeight 相同。
78, 79 | SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN: 虚拟屏幕的宽高，以像素为单位。虚拟屏幕是所有显示器的边界矩形。 SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN 这两个度量值是虚拟屏幕的左上角坐标。 Windows NT, Windows 95: 接收到的值总是 0 。
19 | SM_MOUSEPRESENT: 鼠标已安装则该值非零，否则为零。
75 | SM_MOUSEWHEELPRESENT: 带滚轮的鼠标已安装则该值非零，否则为零。Windows 95: 接收到的值总是 0 。
63 | SM_NETWORK: 如果提供网络支持，最低有效位被设置；否则，该位被清零。其他位被保留 以备将来使用。
8193 | SM_REMOTECONTROL: 该系统度量值用于 Terminal Services(终端服务) 环境。若当前会话被远程控制，该值非零； 否则为零。Windows 2000/NT, Windows Me/98/95: 接收到的值总是 0 。
4096 | SM_REMOTESESSION: 该系统度量值用于 Terminal Services(终端服务) 环境。若调用线程与一个终端服务的客户会话相关联，返回值非零； 若调用线程与终端服务的控制台会话相关联，返回值为零； 控制台会话未必是物理上的控制台。 Windows NT 4.0 SP3 及更早版本, Windows Me/98/95: 接收到的值总是 0 。
70 | SM_SHOWSOUNDS: 如果用户要求一个应用程序在原本只会提供声音信息的场合下同时提供可视化信息，该值非零；否则为零。
8192 | SM_SHUTTINGDOWN: 若当前会话正在关闭，该值非零；否则为零。Windows 2000/NT, Windows Me/98/95: 接收到的值总是 0 。
23 | SM_SWAPBUTTON: 如果鼠标左右键的意义被交换，该值非零；否则为零。
76, 77 | SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN: 虚拟屏幕的左上角坐标。虚拟屏幕是所有显示器的边界矩形。 相比之下， SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN 度量值(在上面，离这儿好几行)是虚拟屏幕的长和宽。Windows NT, Windows 95: 接收到的值总是 0 。

不常用的

数值 | 说明
56 | SM_ARRANGE: 一系列标志，指定系统是如何排列最小化窗口的。要获得更多信息请参阅 MSDN 。
67 | SM_CLEANBOOT: 指定系统是如何启动的： 0 正常启动 1 失败-安全启动 2 失败-带网络的安全启动
5, 6 | SM_CXBORDER, SM_CYBORDER: 窗口边框的宽高，以像素为单位。对于有 3D 外观的窗口而言，该值与 SM_CXEDGE 相等。
13, 14 | SM_CXCURSOR, SM_CYCURSOR: 光标的宽高，以像素为单位。系统无法创建其他大小的光标。
36, 37 | SM_CXDOUBLECLK, SM_CYDOUBLECLK: 围绕一个双击序列中第一次点击位置的矩形的宽高，以像素为单位。第二次点击只有发生在这个矩形内才会被系统认为这两次点击是一次双击。(两次点击还必须发生在指定的时间内。)
68, 69 | SM_CXDRAG, SM_CYDRAG: 以一个拖拽点为中心的矩形的宽高，在拖拽操作开始之前允许鼠标指针在该矩形内作有限的移动。这些值均以像素为单位。这允许用户可以方便地点击和释放鼠标按钮而不会在无意中开始一个拖拽操作。
45, 46 | SM_CXEDGE, SM_CYEDGE: 3D 边框的尺寸，以像素为单位。这些是 SM_CXBORDER 和 SM_CYBORDER 针对 3D 的副本。
7, 8 | SM_CXFIXEDFRAME, SM_CYFIXEDFRAME (与 SM_CXDLGFRAME, SM_CYDLGFRAME 同义): 带标题栏却不能改变大小的窗口的边框厚度，以像素为单位。SM_CXFIXEDFRAME 是水平边界的高度，SM_CYFIXEDFRAME 是垂直边界的宽度。
83, 84 | SM_CXFOCUSBORDER, SM_CYFOCUSBORDER: 控件焦点矩形的左右边缘的宽度(以像素为单位)和上下边缘的高度。Windows 2000/NT, Windows Me/98/95: 接收到的值总是 0 。
21, 3 | SM_CXHSCROLL, SM_CYHSCROLL: 水平滚动条上的箭头位图的宽度，以像素为单位；和水平滚动条的高度，以像素为单位。
10 | SM_CXHTHUMB: 水平滚动条上滑块的宽度，以像素为单位。
11, 12 | SM_CXICON, SM_CYICON: 一个图标的默认宽高，以像素为单位。
38, 39 | SM_CXICONSPACING, SM_CYICONSPACING: 大图标视图中一个项目单元格的尺寸，以像素为单位。每当调整位置时每个项目都会对齐到该大小的矩形中，这些值总是大于等于 SM_CXICON 和 SM_CYICON 。
71, 72 | SM_CXMENUCHECK, SM_CYMENUCHECK: 默认的菜单复选标记位图的尺寸，以像素为单位。
54, 55 | SM_CXMENUSIZE, SM_CYMENUSIZE: 菜单栏按钮(例如在多文档界面中用到的子窗口的关闭按钮)的尺寸，以像素为单位。
47, 48 | SM_CXMINSPACING SM_CYMINSPACING: 最小化窗口的单元格的尺寸，以像素为单位。每当调整位置时每个项目都会对齐到该大小的矩形中，这些值总是大于等于 SM_CXMINIMIZED 和 SM_CYMINIMIZED。
30, 31 | SM_CXSIZE, SM_CYSIZE: 窗口标题文字或标题栏中按钮的宽高，以像素为单位。
32, 33 | SM_CXSIZEFRAME, SM_CYSIZEFRAME: 可调大小的窗口的边框厚度，以像素为单位。SM_CXSIZEFRAME 是水平边界的高度，SM_CYSIZEFRAME 是垂直边界的宽度。与 SM_CXFRAME 和 SM_CYFRAME 同义。
49, 50 | SM_CXSMICON, SM_CYSMICON: 小图标的建议尺寸，以像素为单位。小图标往往出现在窗口标题和小图标视图中。
52, 53 | SM_CXSMSIZE SM_CYSMSIZE: 小标题栏按钮的尺寸，以像素为单位。
2, 20 | SM_CXVSCROLL, SM_CYVSCROLL: 垂直滚动条的宽度，以像素为单位；和垂直滚动条上的箭头位图的高度，以像素为单位。
4 | SM_CYCAPTION: 标题栏区域的高度，以像素为单位。
18 | SM_CYKANJIWINDOW: 对于双字节字符集版本的系统，这是屏幕右下角 Kanji 窗口的高度，以像素为单位。
15 | SM_CYMENU: 单行菜单栏的高度，以像素为单位。
51 | SM_CYSMCAPTION: 小标题栏的高度，以像素为单位。
9 | SM_CYVTHUMB: 垂直滚动条上滑块的高度，以像素为单位。
42 | SM_DBCSENABLED: 如果 User32.dll 支持 DBCS，该值非零；否则为零。Windows Me/98/95: 如果安装了双字节字符集(DBCS)版本的 User.exe，该值非零；否则为零。
22 | SM_DEBUG: 如果安装了调试版本的 User.exe，该值非零；否则为零。
82 | SM_IMMENABLED: 如果 输入法管理器/输入法编辑器 功能已开启，该值非零；否则为零。Windows NT, Windows Me/98/95: 接收到的值总是 0 。 SM_IMMENABLED 指示系统是否准备在 Unicode 应用程序上使用基于 Unicode 的输入法。要确保一个 language-dependent(语言依赖) 的输入法可用，检查 SM_DBCSENABLED 与系统的 ANSI 代码页。否则 ANSI 到 Unicode 的转换可能无法正确执行，或者有些组件如字体或注册表设置可能不会被提供。
87 | SM_MEDIACENTER: 如果当前操作系统是 Windows XP, Media Center Edition(媒体中心版)，该值非零；否则为零。
40 | SM_MENUDROPALIGNMENT: 如果下拉菜单是与其对应的菜单栏项目靠右对齐的，该值非零；如果菜单是左对齐的，则为零。
74 | SM_MIDEASTENABLED: 如果系统开启了希伯来语和阿拉伯语的支持，该值非零；否则为零。
41 | SM_PENWINDOWS: 如果 Microsoft Windows for Pen Computing 扩展已安装，该值非零；否则为零。
44 | SM_SECURE: 如果提供安全支持，该值非零；否则为零。
81 | SM_SAMEDISPLAYFORMAT: 如果所有显示器拥有相同的颜色格式，该值非零；否则为零。注意两个显示器可以有相同的色深，但是不同的颜色格式。举个例子，红色、绿色、蓝色像素可能被分别用不同的位数进行编码，或者那些位可能位于一个像素颜色值中的不同地方。Windows NT, Windows 95: 接收到的值总是 0 。
73 | SM_SLOWMACHINE: 在 Windows NT/2000/XP 及以后版本，该值总是 0 。在 Windows 95/98/ME 下，只有计算机至少符合以下情况之一才不为 0 ：拥有一个 386 处理器、拥有少于 6M 的内存、拥有一块要求低速的显卡。
86 | SM_TABLETPC: 如果当前操作系统是 Windows XP Tablet PC edition(平板电脑版)，该值非零；否则为零。

注意

内置变量 A_ScreenWidth 和 A_ScreenHeight 包含主监视器的尺寸，以像素为单位。

相关命令

DllCall, WinGet

示例

; 示例 #1:
SysGet, MouseButtonCount, 43
SysGet, VirtualScreenWidth, 78
SysGet, VirtualScreenHeight, 79

; 示例 #2: 这是一个可用脚本，显示每一个监视器的信息：
SysGet, MonitorCount, MonitorCount
SysGet, MonitorPrimary, MonitorPrimary
MsgBox, 监视器数量:`t%MonitorCount%`n主监视器:`t%MonitorPrimary%
Loop, %MonitorCount%
{
    SysGet, MonitorName, MonitorName, %A_Index%
    SysGet, Monitor, Monitor, %A_Index%
    SysGet, MonitorWorkArea, MonitorWorkArea, %A_Index%
    MsgBox, 监视器:`t#%A_Index%`n名称:`t%MonitorName%`n左:`t%MonitorLeft% (%MonitorWorkAreaLeft% 工作)`n上:`t%MonitorTop% (%MonitorWorkAreaTop% 工作)`n右:`t%MonitorRight% (%MonitorWorkAreaRight% 工作)`n下:`t%MonitorBottom% (%MonitorWorkAreaBottom% 工作)
}


Thread

设置 线程 的优先级或是否可以被中断. 它也可以临时禁用所有的 计时器.

Thread, NoTimers [, false]
Thread, Priority, n
Thread, Interrupt [, Duration, LineCount]

Thread, NoTimers [, false]: 防止当前线程被任何 计时器 中断, 直至 当前线程 结束, 或者执行 "Thread, NoTimers, false", 或者被另一个允许计时器的线程中断(这样的情况下计时器在它结束前可以中断正在中断的线程).

如果在自动执行段 (脚本顶部) 中没有使用 "Thread NoTimers", 所有线程都可以被计时器中断 (尽管后面的 "Thread Interrupt" 仍然会生效). 相反, 如果自动执行段中打开了 NoTimers 却从没有关闭它, 每个新 线程 (例如 热键, 自定义菜单项, 或 计时器) 都不会被计时器中断.

不论默认的设置如何, 当脚本没有其他线程时计时器总是能执行 (除非使用了 Pause 命令).

"Thread, NoTimers" 相当于 "Thread, NoTimers, true". 此外, 由于 true/false 参数是一个 表达式, 计算结果非零值解析为真, 而 0 则为假.

Thread, Priority, n: 指定 n 为介于 -2147483648 和 2147483647 之间的一个整数(或一个 表达式) 表示当前线程的新优先级. 此命令不会影响其他线程.详见 Threads.

由于其缓冲事件的能力, 一般优先考虑 "Critical" 命令而不是 "Thread Priority".

相关提示, 整个脚本的操作系统优先级可以这样改变, 示例: Process , Priority,, High

Thread, Interrupt [, Duration, LineCount]: 应该谨慎使用此命令, 因为大多数脚本在默认的设置附近时执行得更一致.

默认情况下, 每个新运行的线程在开始 15 毫秒的 持续时间 或在开始的 1000 个脚本 行数 时都是不可中断的, 无论首先遇到哪个. 这使得线程有机会完成而不是立即被另一个等待运行的线程中断 (例如缓冲的 热键 或一系列即将运行的 定时的子程序).

如果持续时间或行数其中一个为 0, 每个新运行的线程会被立即中断. 如果其中一个为 -1, 此参数将使得线程不能被中断. 这两个组件的最大值都为 2147483647.

中断设置是全局的, 这意味着所有后续线程都将服从它, 即使此设置在 自动执行部分 外的某个地方被改变了. 然而, 被中断过的线程 则不受影响因为它们不可中断的时期已经期满(说明:Thread, Interrupt仅设置新线程创建时不可中断的那个时期,而被中断过的线程已经过了这个时期即随时都可能被中断, 所以不受此设置影响). 同样, 只有在改变 LineCount 时 当前线程 是不可中断的, 它才会受影响, 因为此时新的 LineCount 对当前线程有效.

在 当前线程 不可中断时如果按下 热键 或选择了 自定义菜单项, 这些事件将被缓冲. 换句话说, 到当前线程结束或变得可中断时(无论先遇到哪个)它才会运行.例外的情况是当当前线程在结束前变得可中断, 并且它的 优先级 高于缓冲的事件; 此时缓冲的事件不再缓冲而丢弃了.

无论此设置如何, 当一个线程显示 MsgBox, InputBox, FileSelectFile, 或 FileSelectFolder 对话框时都将变成不可中断的.

两个参数中其中每个都可以留空, 这样保持设置不变.

备注

由于更大的伸缩性和缓冲事件的能力, 命令 "Critical" 通常比 "Thread Interrupt" 和 "Thread Priority" 更有效.

相关

Critical, Threads, Hotkey, Menu, SetTimer, Process

示例

Thread, priority, 1 ; Make priority of current thread slightly above average.
Thread, interrupt, 0  ; Make each newly launched thread immediately interruptible:
Thread, interrupt, 50, 2000  ; Make each thread interruptible after 50ms or 2000 lines, whichever comes first.


UrlDownloadToFile

从 Internet(国际互联网) 下载一个文件。

UrlDownloadToFile, URL, Filename

参数

URL | 要下载的文件的 URL(统一资源定位符) 。例如，http://someorg.org 可能取得那个组织的欢迎页面。
Filename | 下载到一个文件: 指定要在本地创建的文件名称，如果绝对路径未指定将假设在 %A_WorkingDir% 。任何已经存在的文件将被新文件覆盖。 下载到一个变量: 在 www.autohotkey.com/forum/topic10466.html 有一个可调用的函数，你可以复制并粘贴到你的脚本中。

ErrorLevel

如果遇到一个问题 ErrorLevel 被设为 1 ，否则是 0 。

注意

即使远程文件不存在下载也可能显示成功。这是因为许多网络服务器发送了一个错误页面代替了缺失的文件。此错误页面会代替 Filename 被储存。

必须安装 Internet Explorer 3 或更高的版本来使此功能运作。防火墙或者多个网卡的存在可能导致此功能失败。而且，一些网站可能阻止这样的下载。

缓存:

  • 在 v1.0.44.07+ ，URL 直接从远程服务器获取(也就是，决不从 Internet Explorer 的缓存取得)。要允许缓存，在 URL 前加 *0 后跟一个空格；例如：*0 http://someorg.org 。星号后面的零可以由任何有效的 dwFlags 数值代替；有关详情，请在 www.microsoft.com 以 InternetOpenUrl 搜索。
  • 在比 1.0.44.07 更早的版本中，每当可能时就从缓存获取文件。要避免这种情况，在 URL 结尾指定一个有问题的字串。例如：http://www.someorg.org/doc.html?fakeParam=42 。注意：如果你频繁地下载同个文件，问题字串应该使其有变化。

代理服务器: 如果已经在 Microsoft Internet Explorer 的设置里设定了一个代理服务器，UrlDownloadToFile 会使用它来访问 Internet 。

相关命令

FileRead, FileCopy

示例

UrlDownloadToFile, http://www.autohotkey.com/download/CurrentVersion.txt, C:\AutoHotkey Latest Version.txt
UrlDownloadToFile, http://someorg.org/archive.zip, C:\SomeOrg's Archive.zip


Click

Click [v1.0.43+]

在指定坐标处点击鼠标按钮. 它还可以按下鼠标按钮, 转动鼠标滚轮或移动鼠标.

这里有一些常见用法的例子 (所有逗号都是可选的):

Click (单独的) | 在鼠标光标的当前位置点击一次鼠标左键.
Click 44, 55 | 在 44, 55 坐标 (基于 CoordMode) 处点击一次鼠标左键.
Click right 44, 55 | 与上述相同, 不过这里点击鼠标右键.
Click 2 | 在光标的当前位置点击两次鼠标左键 (即双击).
Click down | 按下鼠标左键不放.
Click up right | 释放鼠标右键.
Click %x% %y% | 由于 click 不支持 表达式, 所以变量应该括在百分号中.

Click 后可以跟零个或多个下列项. 每个项之间至少需要一个空格, tab 和/或逗号分隔. 除了 ClickCount 必须放在坐标后面 (如果使用了坐标的话), 各项可以按任何顺序出现.

X, Y: 在点击前, 鼠标光标要移动到的 x/y 坐标. 坐标相对于活动窗口, 除非曾使用 CoordMode 改变了这个设置. 如果省略, 那么使用光标的当前位置.

按钮名称: Left (默认), Right, Middle (或仅使用这些名称的首个字母); 或鼠标的第四或第五个按钮 (X1 或 X2), 需要 Windows 2000/XP 或更高版本才支持. 注意: 与 MouseClick 不同, 这里左键和右键的行为在所有系统上都是一致的, 即使用户通过系统控制面板交换了按钮的功能.

鼠标滚轮 (此项在 Windows 9x 上无效): 指定 WheelUp 或 WU 来向上转动滚轮 (远离您的方向); 指定 WheelDown 或 WD 来向下转动滚轮 (靠近您的方向). 在 v1.0.48+, 还可以指定 WheelLeft (或 WL) 或 WheelRight (或 WR) (不过它们在 Windows Vista 以前的系统上无效). 对于 ClickCount (下面的), 指定滚轮要转动的格数. 然而, 有些程序不接受鼠标滚轮转动的格数 ClickCount 大于 1 的情况. 对于这些程序, 请参考下面的例子使用 Loop:

Loop 5
    Click WheelUp

ClickCount: 鼠标要点击的次数 (例如: Click 2 ... Click 100, 200, 2). 如果省略, 那么点击鼠标一次. 如果指定了坐标, 那么 ClickCount 必须放在坐标后面. 指定零 (0) 来移动而不点击鼠标 (例如: Click 100, 200, 0).

Down 或 Up: 这两个单词通常省略, 此时每次点击包括按下事件和接着的弹起事件. 否则, 指定 Down (或字母 D) 来按下鼠标按钮不放. 之后, 使用单词 Up (或字母 U) 来释放鼠标按钮.

Relative: 使用单词 Rel 或 Relative 会把指定的 X 和 Y 坐标视为当前鼠标位置的偏移. 换句话说, 会把光标从当前位置往右移动 X 像素 (负值则往左) 且往下移动 Y 像素 (负值则往上).

备注

Click 通常比 MouseClick 更好, 因为它不受用户通过系统控制面板对左右键功能交换的设置的影响.

Click 使用的发送模式由 SendMode 设置. 要忽略此模式进行特殊的点击, 请使用特定的 Send 命令, 例如: SendEvent {Click, 100, 200}

要执行 shift-click 或 control-click, 使用 Send {Click} 方法通常是最简单的. 例如:

Send +{Click 100, 200}  ; Shift+LeftClick
Send ^{Click 100, 200, right}  ; Control+RightClick

与 Send 不同, Click 不会自动释放修饰键 (Control, Alt, Shift 和 Win). 例如, 如果现在 Control 键处于按下的状态, 那么 Click 会产生 control-click 但 Send {Click} 会产生普通的点击.

SendPlay 模式 生成的鼠标事件可以比其他模式适应更大范围的游戏. 此外, 某些应用程序和游戏在鼠标移动过快时可能会跟踪困难, 此时可以使用 SetDefaultMouseSpeed 减慢速度 (但仅在 SendEvent 模式 中有效).

可以使用 BlockInput 命令防止用户对鼠标的任何物理操作扰乱由鼠标命令生成的模拟鼠标事件. 不过, 在 SendInput 和 SendPlay 模式中通常不需要这个命令, 因为它们会自动延迟用户对鼠标的物理操作到发送之后.

这是自动延迟到每次鼠标 click-down 和 click-up 之后 (不适用于在 SendInput 模式 中转动鼠标滚轮的情况). 使用 SetMouseDelay 可以改变延迟的时间.

相关

Send {Click}, SendMode, CoordMode, SetDefaultMouseSpeed, SetMouseDelay, MouseClick, MouseClickDrag, MouseMove, ControlClick, BlockInput

示例

Click  ; 在鼠标光标的当前位置点击鼠标左键.
Click 100, 200  ; 在指定坐标处点击鼠标左键.
Click 100, 200, 0  ; 移动而不点击鼠标.
Click 100, 200 right  ; 点击鼠标右键.
Click 2  ; 执行双击.
Click down  ; 按下鼠标左键不放.
Click up right  ; 释放鼠标右键.


ControlClick

向指定控件发送一个鼠标点击或鼠标滚轮事件。

ControlClick [, Control-or-Pos, WinTitle, WinText, WhichButton, ClickCount, Options, ExcludeTitle, ExcludeText]

参数

Control-or-Pos

如果此 参数(parameter)为空，目标窗口的最顶端控件将被点击(如果窗口没有控件则点击窗口本身)。如果有参数，则分为以下两种模式。

模式 1 (坐标): 被指定的X和Y坐标相对于目标窗口的左上角。X坐标必须位于Y坐标的前面，并且他们之间至少要有一个空格或者制表符把他们隔开。例如: X55 Y33。如果有一个控件位于这个指定的坐标处，则将发送鼠标事件到该坐标处(控件将被点击)。如果此处没有控件，则目标窗口自身会被发送鼠标事件(也许并不会产生效果，取决于这个窗口)。在这种情况下,Options参数(parameter)里的X和Y选项将被忽略。

模式 2 (控件的 ClassNN 或 文本): 可以是控件的名称/文本或 ClassNN (控件的 classname(类名)和序号)，它们都可以通过 Window Spy 来确定。当使用名称/文本时，matching behavior (匹配模式)通过 SetTitleMatchMode 决定。

默认情况下，模式2 优先于模式1。打比方，有这样的一个控件，它的文本或ClassNN是这样的格式: "Xnnn Ynnn"，这种情况下模式2将会生效。如果想要使用模式1(坐标)并且避免这种情况的发生，请在Options中指定Pos一词。例如: ControlClick, x255 y152, WinTitle,,,, Pos

如果要通过控件的HWND (句柄)来操作, 请在此参数(parameter)上留空并在WinTitle上指定ahk_id %控件句柄% (这样仍可以作用于隐藏的控件即使 DetectHiddenWindows 设定为 Off)。控件的HWND可以通过以下方式来获取: ControlGet Hwnd, MouseGetPos, 或者 DllCall。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果这个参数和另外 3 个参数(WinText，ExcludeTitle，ExcludeText)都被忽略，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个窗口参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个变量要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数(parameter)，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
WhichButton

要发送的鼠标事件: LEFT(左键), RIGHT(右键), MIDDLE(中键) (或者取这些单词的首字母)。如果忽略或留空，将点击左键。

Windows 2000/XP 及以上：X1 (X按键1，第4个鼠标按键) 和 X2 (X按键2,第5个鼠标按键) 是被支持的。

Windows NT/2000/XP 及以上：WheelUp (or WU) 和 WheelDown (or WD) 是被支持的。在这种情况下， ClickCount 是滚轮滚动的次数。

Windows Vista 及以上 [v1.0.48+]：WheelLeft (or WL) 和 WheelRight (or WR) 是被支持的 (它们在旧的操作系统中没有效果)。 在这种情况下， ClickCount 是滚轮滚动的次数。
ClickCount | 发送鼠标点击事件的次数，可以使用 expression(表达式)。如果忽略或者留空，默认次数为 1 。
Options

一个选项字母的序列，包含零个或更多的选项字母。例如: d x50 y25

NA [v1.0.45+]: 可能提高可靠性。参考下面的 reliability (可靠性)。

D: 按住鼠标按键并不放开(产生一个按下的事件)。如果 D 和 U 两个选项都不存在的话，则将发送一个完整的点击(按下再放开)。

U: 放开鼠标按键(产生一个放开的事件)。如果 D 已经存在则不能同时使用这个选项 (反之亦然)。

Pos: 在 Options 的任何位置指定 Pos 一词，以无条件地使用X/Y坐标模式，就像在上面 Control-or-Pos 参数里描述的那样。

Xn: n指定要点击的X坐标，相对于控件的左上角。如果没有指定，则点击会被发送到控件的横向中点。

Yn: n指定要点击的Y坐标，相对于控件的左上角。如果没有指定，则点击会被发送到控件的纵向中点。

请对 X 和 Y 选项使用十进制(而非十六进制)数字。
ExcludeTitle | 标题含有此参数值的窗口将不被考虑。
ExcludeText | 文本含有此参数值的窗口将不被考虑。

ErrorLevel

如果出现问题，ErrorLevel 值将被设置为 1 ，否则为 0 。

reliability (可靠性)

提高可靠性 -- 特别是当用户正在使用鼠标的时候进行 ControlClick -- 请尝试一下的两点或其一 :

1) 在 ControlClick 之前使用 SetControlDelay -1 。这样可以避免在点击时鼠标按键被按住，以降低用户对鼠标操作时对脚本运行造成的干扰。

2) 在任何地方指定 NA 在第6个参数 (Options)，如下所示:

SetControlDelay -1
ControlClick, Toolbar321, WinTitle,,,, NA

"NA" 可以避免激活目标窗口，也可以避免它的输入处理和脚本的相混淆，而这可以免除物理鼠标移动带来的干扰 (通常是在目标窗口没有激活时)。然而，这个方法可能对所有类型的窗口和控件都无效。

注意

不是所有的程序都会响应一个 ClickCount 大于 1 的鼠标滚轮事件。对于这些程序，请使用一个循环来发送一个级数大于 1 的滚轮事件，就像这个使其滚动 5 级的例子:

Loop, 5
    ControlClick, Control, WinTitle, WinText, WheelUp

窗口的标题和包含的文本是区分大小写的。隐藏的窗口是不会被检测到的，除非 DetectHiddenWindows 被打开(DetectHiddenWindows On)。

相关命令

SetControlDelay, Control, ControlGet, ControlGetText, ControlMove, ControlGetPos, ControlFocus, ControlSetText, ControlSend, Click

示例

ControlClick, OK, Some Window Title  ; 点击OK按钮。
ControlClick, x55 y77, WinTitle  ;点击一个设置的坐标。注意X和Y之间的空隙(至少一个空格或者制表符，没有逗号)。
; 下面的方法可能会提高可靠性并且减少其他不好的效果:
SetControlDelay -1
ControlClick, Toolbar321, WinTitle,,,, NA x192 y10  ; 在 NA 模式下点击相对于一个指定控件的坐标。


MouseClick

点击或按住一个鼠标按键，或者滚动鼠标滚轮。注意：一般来说，Click/点击 命令 更加灵活和易用。

MouseClick [, WhichButton , X, Y, ClickCount, Speed, D|U, R]

参数

WhichButton

需要点击的按钮：Left/左键(默认)，Right/右键，Middle/中键(或取这些单词的首字母)，某些鼠标有第三个或第四个键( X1 和 X2 )的话，必须要 Windows2000 以上的版本才支持。例如：MouseClick, X1 。如果省略该参数则默认为左键。

滚动鼠标滚轮：在 Windows NT/2000/XP 或之后d版本中，使用 WheelUp 或者 WU 向上滚动滚轮(远离你)，使用 WheelDown 或 WD 向下滚动滚轮(面向你)。在 1.0.48+ 版本中，分别使用 WheelLeft (或 WL) 或 WheelRight (或 WR) 来向左或向右滚动滚轮 (但是在 Windows Vista 之前的操作系统中没有效果)。ClickCount 参数表示滚动滚轮的次数。

如果要自动适应用户在控制面板里面对鼠标左右键的交换，使用 Click/点击 命令 来替换。
X, Y | 鼠标点击位置的横坐标和纵坐标，可以使用 expressions/表达式 。坐标默认是相对于当前的窗口，除非设置了不同的 CoordMode/坐标模式 。如果省略该参数，则默认为当前鼠标位置。
ClickCount | 鼠标点击次数，可以使用 expressions/表达式 。如果省略该参数，则默认点击 1 次。
Speed

鼠标移动的速度，从 0(最快)到 100(最慢)，可以是 expression/表达式 。注意：设置为 0 的时候，鼠标会立即移动到目标位置。如果省略，默认使用 SetDefaultMouseSpeed/设置鼠标默认移动速度 设置的速度，如果没有设置，则使用 2 。

Speed 参数在 SendInput/SendPlay 模式 中是无效的，在这两种模式中会直接移动鼠标到目标位置(即使 SetMouseDelay/设置鼠标延时 中有一种模式适用于 SendPlay 模式)。如果需要显示鼠标移动轨迹——比如在向观众演示的时候——可以使用 SendEvent {Click 100, 200) 或者 SendMode Event/发送模式事件 。(也可同时设置 BlockInput/阻止输入)。
D|U

如果省略该参数，每一次点击都会由一次“down/按下”事件和一次“up/释放”事件组成。单独使用的话：
D = 按住鼠标按键不放(也就是说产生了一次“down/按下”事件)。
U = 释放鼠标按键(也就是说产生了一次“up/释放”事件)。
R | 如果这个参数使用了字母 R 的话，坐标轴参数 X 和 Y 会被当作当前鼠标位置的偏移来处理。也就是说，鼠标会根据设置的坐标参数从当前位置开始往右移 X 像素(如果设置了负值则是往左移)，以及往下移 Y 像素(如果设置了负值则是往上移)。

注意

这个命令使用的发送模式由 SendMode/发送模式 来设置。

更推荐使用 Click/点击 命令 ，因为：

  1. 它自动适应用户在控制面板中对鼠标左右键的交换。
  2. 它一般更容易使用。

如果需要模拟 Shift + 点击，或者 Ctrl + 点击，在点击命令之前和之后使用 Send 命令。例如：

; 范例 #1:
Send, {Control down}
MouseClick, left, 55, 233
Send, {Control up}
; 范例 #2:
Send, {Shift down}
MouseClick, left, 55, 233
Send, {Shift up}

在某些游戏中，SendPlay 模式 比其它的模式具有更好的兼容性。在某些程序或者游戏中，如果鼠标移动速度过快，它们可能无法识别鼠标的移动，这时候可以使用 SetDefaultMouseSpeed/设置鼠标默认移动速度 来减慢鼠标的移动速度(不过只能在 SendEvnet 模式 中有效)。

有些程序不接受 ClickCount 大于1的情况，对于这些程序，可以使用一个如下的 Loop/循环 来解决：

Loop 5
    Click WheelUp

BlockInput/阻止输入 命令可以防止用户在脚本运行过程中因移动或点击鼠标而造成脚本错误。不过在 SendInput 和 SendPlay 模式中一般不需要使用这个命令，因为它们本身就自动推迟了用户对鼠标的操作。

在每次鼠标按下和鼠标释放之后都会有一个自动的延时(除了 SendInput 模式 和滚动鼠标滚轮)，使用 SetMouseDelay/设置鼠标延时 来改变延时的长度。

相关命令

CoordMode, SendMode, SetDefaultMouseSpeed, SetMouseDelay, Click, MouseClickDrag, MouseGetPos, MouseMove, ControlClick, BlockInput

示例

; 在鼠标当前位置双击：
MouseClick, left
MouseClick, left

; 和上面一样：
MouseClick, left, , , 2

; 移动到指定的坐标位置然后点击右键一次：
MouseClick, right, 200, 300

; 这里用2个热键模拟了滚动鼠标滚轮：
#up::MouseClick, WheelUp, , , 2  ; 滚动2格
#down::MouseClick, WheelDown, , , 2


MouseClickDrag

点击并按住指定的鼠标按键，移动鼠标到目标位置，释放鼠标按键。

MouseClickDrag, WhichButton, X1, Y1, X2, Y2 [, Speed, R]

参数

WhichButton

需要点击的按钮：Left/左键（默认），Right/右键，Middle/中键（或取这些单词的首字母），某些鼠标有第三个或第四个键的话，必须要 Windows2000 以上的版本才支持：使用 X1 代表第四个键，X2 代表第五个键。例如：MouseClickDrag, X1, ...

如果要自动适应用户在控制面板里面对鼠标左右键的交换，使用 Click/点击 命令 来替换。
X1, Y1 | 鼠标开始拖动位置的横坐标和纵坐标，可以使用 expressions/表达式（鼠标会在开始拖动前移动到该坐标）。坐标默认是相对于当前的窗口，除非设置了不同的 CoordMode/坐标模式 。如果省略该参数，则默认为当前鼠标位置。
X2, Y2 | 鼠标需要拖动到的目标位置的横坐标和纵坐标，可以使用 expressions/表达式。坐标默认是相对于当前的窗口，除非设置了不同的 CoordMode/坐标模式 。
Speed

鼠标移动的速度，从 0（最快）到 100（最慢），可以是 expression/表达式 。注意：设置为 0 的时候，鼠标会立即移动到目标位置。如果省略，默认使用 SetDefaultMouseSpeed/设置鼠标默认移动速度 设置的速度，如果没有设置，则使用 2 。

Speed 参数在 SendInput/SendPlay 模式 中是无效的，在这两种模式中会直接移动鼠标到目标位置（即使 SetMouseDelay/设置鼠标延时 中有一种模式适用于 SendPlay 模式）。如果需要显示鼠标移动轨迹——比如在向观众演示的时候——可以使用 SendEvent {Click 100, 200) 或者 SendMode Event/发送模式事件 。（也可同时设置 BlockInput/阻止输入）。
R

如果这个参数使用了字母 R 的话，坐标轴参数 X1 和 Y1 会被当作当前鼠标位置的偏移来处理。也就是说，鼠标会根据设置的坐标参数从当前位置开始往右移 X1 像素（如果设置了负值则是往左移），以及往下移 Y1 像素（如果设置了负值则是往上移）。

相似的，坐标轴参数 X2 和 Y2 会被当作坐标轴参数 X1 和 Y1 的偏移来处理。例如，下面的这个例子鼠标会首先从开始位置向右和向下移动 5 像素 ，然后再从这个位置向右和向下拖动 10 像素 ：MouseClickDrag, Left, 5, 5, 10, 10, , R

注意

这个命令使用的发送模式由 SendMode/发送模式 来设置。

拖动鼠标这个操作同样可以由多条 Send/发送 命令来完成，这样比较灵活，因为可以指定发送的模式。例如：

SendEvent {Click 6, 52, down}{Click 45, 52, up}

使用 Send/发送 命令的另外一个好处是，和 MouseClickDrag 不同，它可以自动适应用户在控制面板中对鼠标左右键的交换。

在某些游戏中，SendPlay 模式 比其它的模式具有更好的兼容性。但是，SendPlay 模式下的鼠标拖动，在 RichEdit/富文本 控件中（可能还有其它的），例如 WordPad 和 Metapad ，可能不能正常工作。

在某些程序或者游戏中，如果鼠标移动速度过快，它们可能无法识别鼠标的移动，这时候可以使用 speed 参数或 SetDefaultMouseSpeed/设置鼠标默认移动速度 来减慢鼠标的移动速度（不过只能在 SendEvnet 模式 中有效）。

BlockInput/阻止输入 命令可以防止用户在脚本运行过程中因移动或点击鼠标而造成脚本错误。不过在 SendInput 和 SendPlay 模式中一般不需要使用这个命令，因为它们本身就自动推迟了用户对鼠标的操作。

在每次鼠标按下和鼠标释放之后都会有一个自动的延时（除了 SendInput 模式 ）。这个延时同样会发生在每次鼠标移动之后。使用 SetMouseDelay/设置鼠标延时 来改变延时的长度。

相关命令

CoordMode, SendMode, SetDefaultMouseSpeed, SetMouseDelay, Click, MouseClick, MouseGetPos, MouseMove, BlockInput

示例

MouseClickDrag, left, 0, 200, 600, 400

; 下面的例子打开了画图并且画了一个小房子：
Run, mspaint.exe
WinWaitActive, ahk_class MSPaintApp,, 2
if ErrorLevel
    return
MouseClickDrag, L, 150, 250, 150, 150
MouseClickDrag, L, 150, 150, 200, 100
MouseClickDrag, L, 200, 100, 250, 150
MouseClickDrag, L, 250, 150, 150, 150
MouseClickDrag, L, 150, 150, 250, 250
MouseClickDrag, L, 250, 250, 250, 150
MouseClickDrag, L, 250, 150, 150, 250
MouseClickDrag, L, 150, 250, 250, 250


MouseGetPos

返回鼠标的当前位置，以及鼠标当前悬停的窗口和控件（可选）。

MouseGetPos, [OutputVarX, OutputVarY, OutputVarWin, OutputVarControl, 1|2|3]

参数

OutputVarX/Y | 这两个变量存储了当前鼠标的横坐标和纵坐标。坐标默认相对于当前窗口，需要的话可以使用 CoordMode/坐标模式 来更改屏幕的坐标相对位置。
OutputVarWin | 这个变量存储了当前鼠标悬停的窗口的 unique ID number/唯一ID ，如果无法检测到窗口，则该变量为空。 即使窗口未处于激活状态，仍能获取它的信息。不过隐藏窗口无法被侦测到。
OutputVarControl | 这个变量存储了当前鼠标悬停的控件的名称（ClassNN）。如果无法检测到控件，则该变量为空。 控件的名称和使用 Window Spy（v1.0.14版以上）所获取的控件名称是一样的（可能和老版本的 Window Spy 不一样）。不过和 Window Spy 不同的是，使用 MouseGetPos 检测控件不需要该控件所在的窗口处于激活状态。
1|2|3 | 如果省略了，默认值是 0 。否则，可以按如下所示的功能指定一个值： 1：使用一种更简单的方式来获取 OutputVarControl 。这种方式在多文档界面（MDI）的程序（例如 SysEdit 或 TextPad ）中可以准确的获取激活或置顶的子窗口信息。但是，它对于其它的情况，例如获取 GroupBox/控件组 中的控件，就不那么准确了。 2 [v1.0.43.06+]：在 OutputVarControl 中存储 control's HWND/窗口句柄 而不是 ClassNN。 3 [v1.0.43.06+]：同时包含 1 和 2 的功能。

注意

如果不需要，任何参数都是可以省略的。

相关命令

CoordMode, WinGet, SetDefaultMouseSpeed, Click

示例

MouseGetPos, xpos, ypos
Msgbox, The cursor is at X%xpos% Y%ypos%.

; 这个例子允许你通过移动鼠标来查看
; 鼠标悬停的窗口的信息
#Persistent
SetTimer, WatchCursor, 100
return

WatchCursor:
MouseGetPos, , , id, control
WinGetTitle, title, ahk_id %id%
WinGetClass, class, ahk_id %id%
ToolTip, ahk_id %id%`nahk_class %class%`n%title%`nControl: %control%
return


MouseMove

移动鼠标。

MouseMove, X, Y [, Speed, R]

参数

X, Y | 鼠标需要移动到的目标位置的横坐标和纵坐标，可以使用 expressions/表达式 。坐标默认相对于当前激活窗口，可以通过设置 CoordMode/坐标模式 来修改。
Speed

鼠标移动的速度，从 0（最快）到 100（最慢），可以是 expression/表达式 。注意：设置为 0 的时候，鼠标会立即移动到目标位置。如果省略，默认使用 SetDefaultMouseSpeed/设置鼠标默认移动速度 设置的速度，如果没有设置，则使用 2 。

Speed 参数在 SendInput/SendPlay 模式 中是无效的，在这两种模式中会直接移动鼠标到目标位置（即使 SetMouseDelay/设置鼠标延时 中有一种模式适用于 SendPlay 模式）。如果需要显示鼠标移动轨迹——比如在向观众演示的时候——可以使用 SendEvent {Click 100, 200) 或者 SendMode Event/发送模式事件 。（也可同时设置 BlockInput/阻止输入）。
R | 如果使用了这个参数使用了字母 R 的话，坐标轴参数 X 和 Y 会被当作当前鼠标位置的偏移来处理。也就是说，鼠标会根据设置的坐标参数从当前位置开始往右移 X 像素（如果设置了负值则是往左移），以及往下移 Y 像素（如果设置了负值则是往上移）。

注意

这个命令使用的发送模式由 SendMode/发送模式 来设置。

在某些游戏中，SendPlay 模式 比其它的模式具有更好的兼容性。在某些程序或者游戏中，如果鼠标移动速度过快，它们可能无法识别鼠标的移动，这时候可以使用 SetDefaultMouseSpeed/设置鼠标默认移动速度 来减慢鼠标的移动速度（不过只能在 SendEvent 模式 中有效）。

BlockInput/阻止输入 命令可以防止用户在脚本运行过程中因移动或点击鼠标而造成脚本错误。不过在 SendInput/SendPlay 模式 中一般不需要使用这个命令，因为它们本身就自动推迟了用户对鼠标的操作。

每个鼠标移动事件后都会有一个自动的延时（除了 SendInput 模式 ），使用 SetMouseDelay/设置鼠标延时 来改变延时的长度。

这是另外一种移动鼠标的方式，它在一些多显示器环境下会运行得更好：

DllCall("SetCursorPos", int, 100, int, 400)  ; 第一个数值是横坐标，第二个数值是纵坐标（相对于屏幕）。

顺便说一下，这里有一个暂时隐藏鼠标的例子 hide-cursor example 。

相关命令

CoordMode, SendMode, SetDefaultMouseSpeed, SetMouseDelay, Click, MouseClick, MouseClickDrag, MouseGetPos, BlockInput

示例

; 移动鼠标到一个新位置
MouseMove, 200, 100

; 缓慢的移动鼠标（速度50），从当前位置往右20像素，往下30像素
MouseMove, 20, 30, 50, r


SetDefaultMouseSpeed

设置鼠标默认速度，如果下列命令没有指定鼠标速度的话，则使用默认速度：Click 以及 MouseMove/MouseClick/MouseClickDrag 。

SetDefaultMouseSpeed, Speed

参数

Speed 鼠标移动的速度，从 0（最快）到 100（最慢），可以是 expression/表达式 。注意：设置为 0 的时候，鼠标会立即移动到目标位置。

注意

SetDefaultMouseSpeed 在 SendInput/SendPlay 模式 中是无效的，在这两种模式中会直接移动鼠标到目标位置（不过 SetMouseDelay 命令 中有一个参数可以设置 SendPlay 模式中的延时）。如果需要显示鼠标移动轨迹——比如在向观众演示的时候——可以使用 SendEvent {Click 100, 200) 或者 SendMode 事件 。（也可同时设置 BlockInput/阻止输入）。

如果没有使用这个命令，默认鼠标速度是 2 。内置变量 A_DefaultMouseSpeed 保存了当前设置。

MouseClick ，MouseMove ，以及 MouseClickDrag 都有一个参数来设定自己的鼠标速度。

不论 Speed 参数是否大于 0 ，SetMouseDelay 命令设置的延时都会对鼠标速度产生影响，鼠标每移动一点就会延时一次。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将该命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

SetMouseDelay, SendMode, Click, MouseClick, MouseMove, MouseClickDrag, SetWinDelay, SetControlDelay, SetKeyDelay, SetKeyDelay

示例

SetDefaultMouseSpeed, 0 ; 立即移动鼠标。


SetMouseDelay

设置两次鼠标操作类命令间的延时。

SetMouseDelay, Delay [, Play]

参数

Delay | 延时时间，单位毫秒。可以是一个 expression/表达式 。使用 -1 表示无延时，使用 0 表示最小延时（但是，如果使用了 Play 参数的话，0 和 -1 都表示无延时）。如果没有设置，在 SendEvent 模式中默认是 10 ，在 SendPlay 模式 中默认是 -1 。
Play [v1.0.43+] | 这个参数使用单词 Play 的话，表示这是为 SendPlay 模式 设置的延时，而不是一般的 Send/SendEvent 模式。如果脚本中从未使用过这个参数，则 SendPlay 模式的延时永远是 -1 。

注意

脚本在执行了每个鼠标操作类命令之后，会有一个自动的延时（休眠）。这些命令包括：Click 以及 MouseMove/MouseClick/MouseClickDrag (except for SendInput mode). 这样做的目的是提高脚本的可靠性，因为一个窗口一般无法响应太过频繁的鼠标事件。

根据系统的时间精度，设置的延时可能会被四舍五入为最近的整十数字。例如在 XP 中，1 到 10 之间的延时（包括 10 ）都等效于 10 （NT 和 2000 中也是这样）。

设置延时为 0 的话相当于执行了命令 Sleep(0) ，它会将当前脚本的剩余时间片分配给有需要的进程。如果没有进程需要，延时 0 就相当于完全没有延时。

内置变量 A_MouseDelay 保存了当前对 Send/SendEvent 模式的设置（没有内置变量保存 SendPlay 模式 的设置）。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将该命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

SetDefaultMouseSpeed, Click, MouseMove, MouseClick, MouseClickDrag, SendMode, SetKeyDelay, SetControlDelay, SetWinDelay, SetBatchLines

示例

SetMouseDelay, 0


Process

对一个进程执行下面的其中一个操作: 检查是否存在; 改变优先级; 关闭; 等待关闭.

Process, Cmd, PID-or-Name [, Param3]

参数

Cmd

下列单词的其中一个:

Exist: 如果一个匹配的进程存在则设置 ErrorLevel 为该进程 ID (PID) , 否则设置为 0. 如果 PID-or-Name 参数为空, 将获取脚本自己的 PID . 获取脚本自己的 PID 的一个单行方法是 PID := DllCall("GetCurrentProcessId")

Close: 如果成功终止一个匹配的进程, ErrorLevel 被设置为该进程原来的进程 ID (PID). 否则(没有找到匹配的进程或者在终止匹配进程的过程中出现了问题),它被设置为0.当一个进程被意外终止时 -- 可能在一个致命点中断它的工作或者导致窗口中没有保存数据的丢失 (如果有的话) -- 只有当无法使用 WinClose 命令作用于它的窗口上来关闭相应进程时才应该使用这种方法.

List: 尽管 List 还不支持, 示例段 中的例子演示了通过 DllCall获取进程列表的方法.

Priority: 改变首个匹配进程的优先级为 Param3 (如同任务管理器中看到的那样)同时设置 ErrorLevel 为该进程 ID (PID). 如果 PID-or-Name 参数为空, 将改变脚本自己的优先级. 没有找到匹配的进程或者在改变匹配进程的优先级过程中出现了问题, ErrorLevel 将被设置为0.

Param3 应该为下列字母或单词的其中一个: L (或 Low), B (或 BelowNormal), N (或 Normal), A (或 AboveNormal), H (或 High), R (或 Realtime). 因为在 Windows 95/98/Me/NT4中, BelowNormal 和 AboveNormal 不被支持, 所以在这些系统中将自动使用 normal 代替它们. 注意: 任何不是设计为实时运行的进程如果设置为实时的优先级可能降低系统的稳定性.

Wait: 在 Param3 指定的秒数 (可以包含小数点) 中检查一个匹配的进程是否存在. 如果 Param3 省略, 命令将无限期等待. 如果找到一个匹配的进程, ErrorLevel 被设置为该进程的进程 ID (PID). 如果命令超时, ErrorLevel 被设置为 0 .

WaitClose: 在 Param3 指定的秒数 (可以包含小数点) 中检查所有匹配的进程是否关闭.如果 Param3 省略, 命令将等待不确定的时间.如果所有的匹配进程都关闭了, ErrorLevel 将被设置为 0. 如果命令超时, ErrorLevel 被设置为仍然存在的第一个匹配进程的进程 ID (PID) .

PID-or-Name

该参数可以是一个数字 (PID) 或者如同下面描述的进程名. 它可以留空来改变脚本自己的优先级.

PID: 进程 ID, 唯一标识一个特定进程的数字 (只有在该进程的生存期这个数字才是有效的). 新运行的进程的 PID 可以通过 Run 命令获取. 同样的, 一个窗口的 PID 可以通过 WinGet 命令获取. Process 命令自身也可以用来获取 PID.

Name: 一个进程的名称通常和它的可执行文件名称相同 (不含路径), 例如 notepad.exe 或 winword.exe. 因为一个名称可能匹配多个正在运行的进程, 只会对第一个进程进行操作. 名称的大小写不敏感.
Param3 查看上面的 Cmd 获取细节.

ErrorLevel

查看上面的 Cmd 获取细节.

备注

对于 Wait 和 WaitClose: 每隔 100 毫秒检查目标进程一次; 目标进程满足条件时, 命令不再继续等待. 换句话说, 这时不会等待超时时间到期, 而是立即像上面描述的那样设置 ErrorLevel, 然后继续往后执行脚本. 此外, 当该命令处于等待状态时, 新的 线程 可以通过 热键, 自定义菜单项, 或 计时器 启动.

在 Windows NT4 系统上, Process 命令需要 PSAPI.DLL文件, 通常该文件存在于 AutoHotkey 的安装目录 (即不需要为 NT 系统进行额外的安装步骤). 然而, 在 Windows NT4 中执行含有该命令的 已编译脚本 时, 需要在脚本所在目录或系统的 PATH 变量的路径中包含一个 PSAPI.DLL 文件的副本 (尽管某些 NT4 系统可能含有该 DLL 文件).

相关

Run, WinGet, WinClose, WinKill, WinWait, WinWaitClose, IfWinExist

示例

; Example #1:
Run Notepad.exe, , , NewPID
Process, priority, %NewPID%, High
MsgBox The newly launched notepad's PID is %NewPID%.

?

; Example #2:

Process, wait, Notepad.exe, 5.5
NewPID = %ErrorLevel%  ; Save the value immediately since ErrorLevel is often changed.
if NewPID = 0
{
    MsgBox The specified process did not appear within 5.5 seconds.
    Return
}
; Otherwise:
MsgBox A matching process has appeared (Process ID is %NewPID%).
Process, priority, %NewPID%, Low
Process, priority, , High  ; Have the script set itself to high priority.
WinClose Untitled - Notepad
Process, WaitClose, %NewPID%, 5
if ErrorLevel ; The PID still exists.
    MsgBox The process did not close within 5 seconds.

?

; Example #3: A hotkey to change the priority of the active window's process:

#z:: ; Win+Z hotkey
WinGet, active_pid, PID, A
WinGetTitle, active_title, A
Gui, 5:Add, Text,, Press ESCAPE to cancel, or double-click a new`npriority level for the following window:`n%active_title%
Gui, 5:Add, ListBox, vMyListBox gMyListBox r5, Normal|High|Low|BelowNormal|AboveNormal
Gui, 5:Add, Button, default, OK
Gui, 5:Show,, Set Priority
return

5GuiEscape:
5GuiClose:
Gui, Destroy
return

MyListBox:
if A_GuiEvent <> DoubleClick
    return
; else fall through to the next label:
5ButtonOK:
GuiControlGet, MyListBox
Gui, Destroy
Process, Priority, %active_pid%, %MyListBox%
if ErrorLevel
    MsgBox Success: Its priority was changed to "%MyListBox%".
else
    MsgBox Error: Its priority could not be changed to "%MyListBox%".
return

?

; Example #4: Retrieves a list of running processes via DllCall then shows them in a MsgBox.

d = `n  ; string separator
s := 4096  ; size of buffers and arrays (4 KB)

Process, Exist  ; sets ErrorLevel to the PID of this running script
; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
VarSetCapacity(ti, 16, 0)  ; structure of privileges
NumPut(1, ti, 0)  ; one entry in the privileges array...
; Retrieves the locally unique identifier of the debug privilege:
DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "Int64P", luid)
NumPut(luid, ti, 4, "int64")
NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
; Update the privileges of this process with the new access token:
DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0)
DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
c := 0  ; counter for process idendifiers
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
{
   id := NumGet(a, A_Index * 4)
   ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
   VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
   e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
   DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
   if (n && e)  ; if image is not null add to list:
      l .= n . d, c++
}
DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
;Sort, l, C  ; uncomment this line to sort the list alphabetically
MsgBox, 0, %c% Processes, %l%


Run / RunWait

运行一外部程序。与 Run 不同，RunWait 会等待运行的程序结束再继续下一行命令。

Run, Target [, WorkingDir, Max|Min|Hide|UseErrorLevel, OutputVarPID]

参数

Target

运行一文档、网址、可执行文件（.exe, .com, .bat 等等）、快捷方式(.lnk)或系统动作（见备注）。如果 Target 是个本地文件并且没有给它指定路径，A_WorkingDir 将先被搜索。如果没在那找到匹配的文件，系统将查找并且运行假如是被整合的(“已知”)文件，例如通过被包含在 PATH 文件夹其中的一个。（译注：PATH 文件夹应该指的是操作系统环境变量中的 PATH，被包含在这个 PATH 中的文件夹下的文件，都可以按 Win 键+R 后直接输入文件名来运行）

要传递参数，将他们立即添加在程序或文档名字后面。如果一参数包含空格，将其用双引号括起是最安全的（虽然它也能在某些情况下不需要他们而运作）。
WorkingDir 被运行项目的工作目录。不要将名称括在双引号中即使它包含空格。如果此参数忽略，脚本所在的工作目录(A_WorkingDir)将被使用。
Max|Min|Hide
UseErrorLevel

如果此参数忽略，Target 将只被正常地运行。或者，它能包含一个或多个这些单词：

Max: 最大化运行

Min: 最小化运行

Hide: 隐藏运行（以上任一个不能组合使用）

注意：一些程序（例如 Calc.exe）不遵守请求的启动状态，因此 Max/Min/Hide 将无效。

UseErrorLevel: UseErrorLevel 可单独被指定或加在以上单词后（将它与其他单词用空格分开）。如果命令运行失败，此选项跳过提示对话框，设置 ErrorLevel 为单词 ERROR，并允许当前线程继续。如果命令运行成功，RunWait 将 ErrorLevel 设置为程序的退出代码，Run 设置其为零。

当 UseErrorLevel 被指定时，变量 A_LastError 被设置成操作系统的 GetLastError() 函数的结果。A_LastError 是一个在 0 与 4294967295 之间的数字（总为十进制格式，不是十六进制）。零（0）意味着成功，除此之外其他数字意味着运行失败。每一数字相当于一个特定的错误状态（要取得一个列表，在 www.microsoft.com 以“system error codes”搜索）。与 ErrorLevel 相同，A_LastError 是一个独立线程设定；也就是说，被其他线程打断并不能改变它。但是 A_LastError 也能被 DllCall 设定。
OutputVarPID

变量的名字用来储存最近运行的程序的唯一 Process ID (PID)。如果 PID 不能被定义，变量将为空，其通常发生在一个系统动作、文档或快捷方式被运行，而不是一个直接可执行的文件。RunWait 也支持此参数，尽管它的 OutputVarPID 必须在另一个线程核实（否则，PID 将因为进程在 RunWait 下一行执行的时候终止而无效）。

在 Run 命令取得一个 PID 后，任何由进程创建的窗口可能还不存在。为了等待至少一个窗口被创建，使用 WinWait ahk_pid %OutputVarPID%

ErrorLevel

Run: 不设置 ErrorLevel 除非使用了 UseErrorLevel(上面的)，这样的话，ErrorLevel 在命令执行失败时被设置成单词 ERROR 或者在成功时设置为 0。

RunWait: 将 ErrorLevel 设为程序的退出代码（一个标记成 32 位的整数型）。如果使用了 UseErrorLevel 且命令执行失败，则 ErrorLevel 被存作单词 ERROR。

备注

不同于 Run，RunWait 会等到 Target 关闭或者退出，这时 ErrorLevel 被设为程序的退出代码（作为一个标记为 32 位的整数型）。即使有些程序仍在运行，RunWait 也会马上出现返回；这些程序创建了另外的进程。

如果 Target 包含任何逗号，它们一定要像下面的例子里出现的三次一样被转义：

Run rundll32.exe shell32.dll`,Control_RunDLL desk.cpl`,`, 3  ;打开 控制面板 > 显示 > 设置

当通过 Comspec (即 cmd.exe，译注：命令解释程序 cmd.exe 的路径变量) 运行一个程序时--可能因为你需要重定向此程序的输入或输出--如果可执行文件的路径或名字包含空格，整个字串应该被一对外引号括起来。下例中，外引号用红色表示，所有的内引号用黑色表示：
Run %comspec% /c ""C:\My Utility.exe" "param 1" "second param" >"C:\My File.txt""

如果 Target 不能被运行，将显示一个错误提示窗口，这之后脚本会表现为像遇到了一个 Exit 命令。为了避免此情况，在第三个参数里包含 UseErrorLevel 字串。

如果 Target 是一个精确的路径，性能可能有细微地改善，例如 Run, C:\Windows\Notepad.exe "C:\My Documents\Test.txt" 而不是 Run, C:\My Documents\Test.txt

特殊的 CLSID 文件夹可以通过 Run 被打开。例如：

Run ::{20d04fe0-3aea-1069-a2d8-08002b30309d}  ;打开“我的电脑”文件夹。
Run ::{645ff040-5081-101b-9f08-00aa002f954e}  ;打开回收站。

系统动作相当于在资源管理器中一个文件的右键菜单动作可用。如果一个文件没有一个动作来运行，这特殊的文件类型的默认动作（通常是“打开”）将被使用。如果指定了，这动作应该跟在 target 文件名的后面。下列动作是当前被支持的：

properties | 为指定文件显示资源管理器的属性窗口。例如：Run, properties "C:\My File.txt" 注意：当脚本终止的时候属性窗口会自动关闭。为避免这种情况，使用 WinWait 来等待窗口出现，然后用 WinWaitClose 等待用户去关闭它。
find | 打开一个资源管理器的搜索助理窗口或者在指定文件夹的查找文件窗口。例如：Run, find D:\
explore | 在指定文件夹打开一个资源管理器窗口。例如：Run, explore %A_ProgramFiles%
edit | 打开一个指定的文件来编辑。如果指定的文件类型没有“编辑”动作与之关联，它可能不起作用。例如：Run, edit "C:\My File.txt"
open | 打开指定的文件 (一般不需要，因为这是大多数文件类型的默认动作)。例如：Run, open "My File.txt"
print | 使用与之关联的应用程序来打印指定的文件，如果有的话。例如：Run, print "My File.txt"

当 RunWait 在等待状态时，新的线程能通过热键，自定义菜单项或者定时器来运行。

相关命令

RunAs, Process, Exit, CLSID List, DllCall

范例

Run, Notepad.exe, C:\My Documents, max

Run, mailto:someone@domain.com?subject=This is the subject line&body=This is the message body's text.
Run, ReadMe.doc, , Max UseErrorLevel  ;以最小化运行并且如果失败则不显示对话框。
if ErrorLevel = ERROR
    MsgBox 无法启动文档。

RunWait, %comspec% /c dir c:\ >>c:\DirTest.txt, , min
Run, c:\DirTest.txt
Run, properties c:\DirTest.txt

Run, www.autohotkey.com ;也就是说能运行任何 URL。
Run, mailto:someone@somedomain.com  ;这将打开默认的 e-mail 程序。

Run ::{20d04fe0-3aea-1069-a2d8-08002b30309d}  ;打开“我的电脑”文件夹。
Run ::{645ff040-5081-101b-9f08-00aa002f954e}  ;打开回收站。

;连续执行多个命令，在每个命令之间用“&&”：
Run, %comspec% /c dir /b > C:\list.txt && type C:\list.txt && pause


RunAs

为所有随后要使用的 Run 和 RunWait 指定一组用户凭证。需要 Windows 2000/XP 或之后版本。

RunAs [, User, Password, Domain]

参数

User | 如果省略了此参数以及所有其它参数，RunAs 特性将被关闭，这将使 Run 和 RunWait 恢复到它们默认的特性。不然它就是将被创建的新进程所属的用户名。
Password | User 的密码。
Domain | User 的域。要使用本地账户的话，将此留空。如果那样不行，试着使用 @你的计算机名称。

注意

只支持 Windows XP/2000 或之后版本；此命令对其它操作系统无效。NT4 用户应该从 NT 资源工具箱中安装并使用 SU 命令代替。

此命令只会通知 AutoHotkey 对所有随后要使用的 Run 和 RunWait 使用(或不使用)轮流的用户凭证。

ErrorLevel 不会被此命令改变。如果指定了一个无效的 User, Password, 或 Domain，Run 和 RunWait 将显示一个错误消息来解释问题所在(除非它们的 UseErrorLevel 选项处于有效状态)。

当 RunAs 特性生效时，Run 和 RunWait 将不能启动文档、URL 或系统动作。换言之，要启动的文件必须是一个可执行文件。

要使用此命令，"Secondary Logon" 服务必须设为手动或者自动(如果设为手动，操作系统应该能够在需要时自动地启用此服务)。

相关命令

Run, RunWait

示例

RunAs, Administrator, MyPassword
Run, RegEdit.exe
RunAs  ;重设为普通特性。


Shutdown

关机、重启或注销操作系统。

Shutdown, Code

参数

Code 一组 shutdown 代码如下所列。

注意

shutdown 代码是下列数值的一个组合：

Logoff (注销) | 0
Shutdown (关机) | 1
Reboot (重启) | 2
Force (强制) | 4
Power down (切断电源) | 8
Suspend/Hibernate (挂起/休眠) | 请看此页面底部的 DllCall 示例 。

将需要的数值相加。例如，要关机并切断电源的代码将是 9 (关机 + 切断电源 = 1 + 8 = 9)。或者，也能指定一个像 1+8 这样的 expression(表达式) 。

"Force" 数值(4) 强制关闭所有打开的应用程序。它仅仅应该在一个紧急情况时使用，因为它可能导致任何打开的应用程序丢失数据。

"Power down" 数值 关闭操作系统并且切断电源。

一个相关的提示，当操作系统关闭或用户通过 OnExit 注销时，脚本能探测到。

相关命令

Run, ExitApp, OnExit

示例

; 强制重启 (重启 + 强制 = 2 + 4 = 6):
Shutdown, 6

; 调用 Windows API 函数 "SetSuspendState" 来使操作系统挂起或者休眠。
; Windows 95/NT4: 由于此函数不存在，下面的调用将无效。
; 参数 #1: 传递 1 来代替 0 进行休眠而不是挂起。
; 参数 #2: 传递 1 来代替 0 立即进行挂起而不是询问每个应用程序获得许可。
; 参数 #3: 传递 1 来代替 0 去禁止所有的唤醒事件。
DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)


RegDelete

从注册表中删除一个子键或一个值。

RegDelete, RootKey, SubKey [, ValueName]

参数

RootKey | 只能是 HKEY_LOCAL_MACHINE 、HKEY_USERS 、HKEY_CURRENT_USER 、HKEY_CLASSES_ROOT 、HKEY_CURRENT_CONFIG 其中之一（或者它们的缩写，例如 HKLM ）。要访问远程注册表，在前面加上电脑名和一个冒号，例如：\\workstation01:HKEY_LOCAL_MACHINE
SubKey | 子键的名字（例如 Software\SomeApplication）。
ValueName | 需要删除的项的名字。如果省略，整个 SubKey 将会被删除。要删除 Subkey 的默认值 —— 也就是在 RegEdit 中显示为“(Default)/默认”的值 —— 这个参数使用 AHK_DEFAULT 。

ErrorLevel

如果遇到问题，ErrorLevel/错误级别 被设置为 1 ，否则为 0 。

注意

对注册表进行删除操作可能会引发潜在的问题 —— 使用前请三思！

要返回多个注册表值或对多个注册表值进行操作，推荐使用 registry-loop 。

要获取访问远程注册表的详细资料，可以查看 registry-loop 中的注释。

相关命令

RegRead, RegWrite, Registry-loop, IniDelete

示例

RegDelete, HKEY_LOCAL_MACHINE, Software\SomeApplication, TestValue


RegRead

从注册表中读取一个值。

RegRead, OutputVar, RootKey, SubKey [, ValueName]

参数

OutputVar | 存储返回值的变量名。如果获取值失败，它会被设置为空，同时 ErrorLevel/错误级别 被设置为 1 。
RootKey | 只能是 HKEY_LOCAL_MACHINE 、HKEY_USERS 、HKEY_CURRENT_USER 、HKEY_CLASSES_ROOT 、HKEY_CURRENT_CONFIG 其中之一（或者它们的缩写，例如 HKLM ）。要访问远程注册表，在前面加上电脑名和一个冒号，例如：\\workstation01:HKEY_LOCAL_MACHINE
SubKey | 子键的名字（例如 Software\SomeApplication）。
ValueName | 需要读取的项的名称。如果省略，将返回 Subkey 的默认值，也就是在 RegEdit 中显示为“(Default)/默认”的值。如果没有默认值（也就是 RegEdit 中显示“value not set/数值未设置”），OutputVar 被设置为空，同时 ErrorLevel/错误级别 被设置为 1 。

ErrorLevel/错误级别

如果遇到问题（例如读取不存在的键或值），ErrorLevel/错误级别 被设置为 1 ，否则为 0 。

注意

目前只支持这些类型的值：REG_SZ/字符串值 ，REG_EXPAND_SZ/可扩充字符串值 ，REG_MULTI_SZ/多字符串值 ，REG_DWORD/DWORD值 ，以及 REG_BINARY/二进制值 。

REG_DWORD/DWORD 类型的值总是被转换为正的十进制数字。

REG_BINARY/二进制 类型的值最多只能读取 64KB ，其它类型的值则没有限制。但是在 Windows 95/98/ME 下，所有类型的值最多只能读取 64KB（ Win9x 的注册表不能存储过大的数据）。

当读取 REG_BINARY/二进制 类型的值的时候，会返回一个16进制的字符串。例如，REG_BINARY/二进制 值为 01,a9,ff,77 ，读取出来的结果为 01A9FF77 。

当读取一个 REG_MULTI_SZ/多字符串 类型的值的时候，值的每一个部分以换行符分隔（`n）。如果值为空，OutputVar 被设置为空。FileSelectFile 中的示例演示了怎么将 OutputVar 分解为各个独立的部分。注意：Windows 95 不支持 REG_MULTI_SZ/多字符串 类型的值。

要返回多个注册表值或对多个注册表值进行操作，推荐使用 registry-loop 。

要获取访问远程注册表的详细资料，可以查看 registry-loop 中的注释。

相关命令

RegDelete, RegWrite, Registry-loop, IniRead

示例

RegRead, OutputVar, HKEY_LOCAL_MACHINE, SOFTWARE\Microsoft\Windows\CurrentVersion, ProgramFilesDir
MsgBox, Program files are in: %OutputVar%

; 下面的例子返回一个注册表值的类型（例如 REG_SZ/字符串值 或 REG_DWORD/DWORD值）。
MsgBox % RegKeyType("HKCU", "Environment", "TEMP")
return

RegKeyType(RootKey, SubKey, ValueName)  ; 这个函数返回指定值的类型。
{
    Loop, %RootKey%, %SubKey%
        if (A_LoopRegName = ValueName)
            return A_LoopRegType
    return "Error"
}


RegWrite

写入一个值到注册表中。

RegWrite, ValueType, RootKey, SubKey [, ValueName, Value]

参数

ValueType | 只能是 REG_SZ ，REG_EXPAND_SZ ，REG_MULTI_SZ ，REG_DWORD 或者 REG_BINARY 。
RootKey | 只能是 HKEY_LOCAL_MACHINE 、HKEY_USERS 、HKEY_CURRENT_USER 、HKEY_CLASSES_ROOT 、HKEY_CURRENT_CONFIG 其中之一（或者它们的缩写，例如 HKLM ）。要访问远程注册表，在前面加上电脑名和一个冒号，例如：\\workstation01:HKEY_LOCAL_MACHINE
SubKey | 子键的名字（例如 Software\SomeApplication）。如果 SubKey 不存在，将会自动创建（在它的父类之下，如果有的话）。如果 SubKey 留空，将把值直接写入到 RootKey 中（某些系统会拒绝将值直接写入 HKEY_CURRENT_USER 根键之下）。
ValueName | 需要写入值的项的名称。如果留空或省略，默认修改的是 Subkey 的默认值，也就是在 RegEdit 中显示为“(Default)/默认”的值
Value | 需要写入的值。如果省略，默认是一个空字符串，或 0 ，这个取决于 ValueType 。如果写入的文本过长，可以使用 continuation section/字符串分段 的方法将它分为几个短小的段落，这样可以增加代码的可读性和可维护性。

ErrorLevel

如果遇到问题，ErrorLevel/错误级别 被设置为 1 ，否则为 0 。

注意

如果 ValueType 是 REG_DWORD ，Value 的取值范围是 -2147483648 到 4294967295（0xFFFFFFFF）。

REG_BINARY/二进制 和 REG_MULTI_SZ/多字符串 类型的值最多只能写入 64KB ，其它类型的值则没有限制。但是在 Windows 95/98/ME 下，所有类型的值最多只能写入 64KB 。如果超过 64KB ，则超过范围之后的数据将不会被写入。也就是说，在一个比较大的字符串中，只有最开始的 64KB 数据会被写入注册表。

当写入一个 REG_BINARY/二进制 类型的值的时候，使用一个16进制的字符串。例如，REG_BINARY/二进制 值为 01,a9,ff,77 ，写入的字符串为 01A9FF77 。

当写入一个 REG_MULTI_SZ/多字符串 类型的值的时候，你必须使用换行符（`n）来分隔各个部分，最后一个部分的结尾可以不使用换行符。任何一个部分都不能为空。也就是说，不要在一行中连着使用两个换行符（`n`n），因为这样会写入一个 shorter-than-expected/比预期短 的值。注意：Windows 95 不支持 REG_MULTI_SZ/多字符串 类型的值。

要返回多个注册表值或对多个注册表值进行操作，推荐使用 registry-loop 。

要获取访问远程注册表的详细资料，可以查看 registry-loop 中的注释。

相关命令

RegDelete, RegRead, Registry-loop, IniWrite

示例

RegWrite, REG_SZ, HKEY_LOCAL_MACHINE, SOFTWARE\TestKey, MyValueName, Test Value
RegWrite, REG_BINARY, HKEY_CURRENT_USER, Software\TEST_APP, TEST_NAME, 01A9FF77
RegWrite, REG_MULTI_SZ, HKEY_CURRENT_USER, Software\TEST_APP, TEST_NAME, Line1`nLine2


SoundBeep

从个人计算机的扬声器发出一个音调。

SoundBeep [, Frequency, Duration]

参数

Frequency | 声音的频率，可以是一个 表达式。必须是 37 和 32767 之间的一个数字。如果省略，频率将为 523。
Duration | 声音持续的时间，以毫秒计 (可以是一个 表达式)。如果省略，持续时间将为 150。

注意

等声音结束脚本才会继续。此外，发音期间系统的响应可能被减慢。

在 Windows 9x 上，Frequency 和 Duration 参数被忽略。取而代之，声卡将播放系统默认的事件声音。如果计算机没有声卡，扬声器将播放一个标准的哔音。

要生成一个标准的系统声音而不是个人计算机扬声器的哔音，请看 SoundPlay 命令中的星号模式。

相关命令

SoundPlay

示例

SoundBeep  ; 播放默认的音高和持续时间。
SoundBeep, 750, 500  ; 以更高的音调播放半秒钟。


SoundGet

从音频设备中获取多种设置 (主静音, 主音量, 等等)

SoundGet, OutputVar [, ComponentType, ControlType, DeviceNumber]

参数

OutputVar | 用来保存获取的设置的变量名称, 可以是一个在 0 到 100 (包含的)之间的浮点数或者单词 ON 或 OFF (仅在 ControlTypes/控制类型 为 ONOFF, MUTE, MONO, LOUDNESS, STEREOENH, 或 BASSBOOST 时使用). 如果在获取设置时遇到问题, 变量将被置空. 浮点数的格式, 比如它的小数位数, 由 SetFormat 命令决定.
ComponentType

如果省略或为空, 默认值为单词 MASTER. 否则, 它可以是下列单词的其中一个: MASTER (与 SPEAKERS 含义相同), DIGITAL, LINE, MICROPHONE, SYNTH, CD, TELEPHONE, PCSPEAKER, WAVE, AUX, ANALOG, HEADPHONES, 或 N/A. 如果音频设备缺少指定的 ComponentType/组件类型, ErrorLevel 将表明有问题.

在某些混音器中标为 Auxiliary 的组件可能需要作为 ANALOG 而不是 AUX 进行访问.

如果一个设备含有同种 组件类型 的多个实例(例如两种类型的 LINE), 通常首个包含播放设置, 第二个包含录制设置. 要访问首个实例外的其他实例, 在该参数后附加一个冒号和数字. 例如: Analog:2 表示 analog 组件的第二个实例.
ControlType | 如果省略或为空, 默认值为 VOLUME. 否则, 它可以是下列单词的其中一个: VOLUME (或 VOL), ONOFF, MUTE, MONO, LOUDNESS, STEREOENH, BASSBOOST, PAN, QSOUNDPAN, BASS, TREBLE, EQUALIZER, 或者是有效的控制器类型的数字 (请看 声卡分析脚本). 如果指定的 组件类型 缺少指定的 控制类型, ErrorLevel 将表明有问题.
DeviceNumber | 如果省略此参数, 默认值为 1 (第一个音频设备), 通常是系统默认的录制和播放设备.可以通过指定一个大于 1 的数字来操作其他的音频设备. 此参数可以是一个 表达式.

ErrorLevel

如果命令成功执行 ErrorLevel 被设置为 0.否则它被设置为下列短语的其中一个:

Invalid Control Type or Component Type
Can't Open Specified Mixer
Mixer Doesn't Support This Component Type
Mixer Doesn't Have That Many of That Component Type
Component Doesn't Support This Control Type
Can't Get Current Setting

备注

在 Windows Vista 或更高版本的系统上, SoundGet 命令获取脚本自己的设置, 而不是活动窗口的. 此问题可能会在未来的版本中解决. 要绕弯解决此问题, 在 "AutoHotkey.exe" (或 已编译脚本)文件的属性对话框中, 改变兼容性设置为 "Windows XP".

为了发现安装在系统上的音频设备 (混音器) 的功能 -- 例如可用的组件类型和控制类型 -- 请运行 声卡分析脚本.

使用 SoundSet 命令可以改变设置.

相关

SoundSet, SoundGetWaveVolume, SoundSetWaveVolume, SoundPlay

示例

SoundGet, master_volume
MsgBox, Master volume is %master_volume% percent.

SoundGet, master_mute, , mute
MsgBox, Master Mute is currently %master_mute%.

SoundGet, bass_level, Master, bass
if ErrorLevel
    MsgBox, Error Description: %ErrorLevel%
else
    MsgBox, The BASS level for MASTER is %bass_level% percent.

SoundGet, microphone_mute, Microphone, mute
if microphone_mute = Off
    MsgBox, The microphone is not muted.


SoundGetWaveVolume

获取一个音频设备的波形输出音量。

SoundGetWaveVolume, OutputVar [, DeviceNumber]

参数

OutputVar | 储存了取得的音量等级的变量名称，它是一个包括 0 到 100 的浮点数。如果在获取音量的过程中遇到问题，此变量将为空。浮点数的格式比如它的小数位数，由 SetFormat 命令决定。
DeviceNumber | 如果省略此参数，其默认为 1 (第一个音频设备)，通常是系统默认的录音和播放设备。可以通过指定一个大于 1 的数字来操作其他的音频设备。

ErrorLevel

如果出现问题，ErrorLevel 将设为 1，其他情况为 0。

注意

SoundGetWaveVolume 还不被 Windows Vista 支持；它将使 OutputVar 为空。

可以通过 SoundSetWaveVolume 设定当前波形输出音量的等级。其他设置例如总音量、合成器、麦克风、静音、高音和低音可以用 SoundSet 和 SoundGet 进行设定和获取。

相关命令

SoundSetWaveVolume, SoundSet, SoundGet, SoundPlay

示例

SoundGetWaveVolume, OutputVar
MsgBox,当前的波形输出音量的等级为 %OutputVar%`%。


SoundPlay

播放一个音频、视频或者其他支持的文件类型。

SoundPlay, Filename [, wait]

参数

Filename | 要被播放的文件名称，如果绝对路径未指定将假设在 %A_WorkingDir% 。 要发出标准的系统声音，像下面显示的那样在一个星号后面指定一个数字。注意：wait 参数在此模式中无效。 *-1: 简单的哔哔声。如果声卡不可用，此声音将使用主板扬声器来生成。 *16: 手型(停止/错误声) *32: 问号声 *48: 感叹声 *64: 星号(消息声)
wait | 如果省略，当文件在播放时脚本的 current thread(当前线程) 将移动到下一个命令。要避免这样，指定此参数为 1 或者是单词 WAIT ，这能使当前线程在继续前等待文件播放结束。甚至在等待时，新的 threads 也能通过 hotkey 、custom menu item 或者 timer 来启动。 已知限制：如果省略 WAIT 参数，操作系统可能会认为播放的文件“在使用中”直到脚本关闭或者直到另一个文件被播放(甚至一个不存在的文件)。

ErrorLevel

如果遇到一个问题 ErrorLevel 设为 1 ，否则是 0 。

注意

所有的 Windows 操作系统都能够播放 .wav 文件。不过，如果操作系统没有安装正确的编解码器或者功能，那么其他文件(.mp3 、.avi 等) 可能无法播放。

如果一个文件正在播放并且当前脚本播放了第二个文件，那么第一个文件将停止播放以便第二个文件能播放。在一些操作系统上，即使当一个完全独立的脚本播放一个新的文件时，特定的文件类型也可能停止播放。

要停止一个当前播放的文件，像这个例子一样，在一个不存在的文件名称上使用 SoundPlay：SoundPlay, Nonexistent.avi

如果脚本退出，任何由它启动的当前正在播放的文件将会停止。

相关命令

SoundBeep, SoundGet, SoundSet, SoundGetWaveVolume, SoundSetWaveVolume, MsgBox, Threads

示例

SoundPlay, %A_WinDir%\Media\ding.wav


SoundSet

改变音频设备的多种设置 (主静音, 主音量, 等)

SoundSet, NewSetting [, ComponentType, ControlType, DeviceNumber]

参数

NewSetting

从 -100 到 100 (包含的)之间的百分率数字 (它可以是一个浮点数或 表达式). 如果数值以加号或者减号开头, 当前的音量等级 将往上或者往下调指示的数值. 否则, 音量将明确地设置为 NewSetting 指示的等级.

对于只有两种可能的设置的 控制类型 而言 -- 即 ONOFF, MUTE, MONO, LOUDNESS, STEREOENH, and BASSBOOST -- 任何正数都将开启设置, 而 0 则将关闭. 然而, 如果数值以加号或者减号开头, 设置将被切换 (设置为和当前状态相反).
ComponentType

如果省略或为空, 默认值为单词 MASTER. 否则, 它可以是下列单词的其中一个: MASTER (与 SPEAKERS 含义相同), DIGITAL, LINE, MICROPHONE, SYNTH, CD, TELEPHONE, PCSPEAKER, WAVE, AUX, ANALOG, HEADPHONES, 或 N/A. 如果音频设备缺少指定的 ComponentType/组件类型, ErrorLevel 将表明有问题.

在某些混音器中标为 Auxiliary 的组件可能需要作为 ANALOG 而不是 AUX 进行访问.

如果一个设备含有同种 组件类型 的多个实例(例如两种类型的 LINE), 通常首个包含播放设置, 第二个包含录制设置.要访问首个实例外的其他实例, 在该参数后附加一个冒号和数字.例如: Analog:2 表示 analog 组件的第二个实例.
ControlType | 如果省略或为空, 默认值为 VOLUME. 否则, 它可以是下列单词的其中一个: VOLUME (或 VOL), ONOFF, MUTE, MONO, LOUDNESS, STEREOENH, BASSBOOST, PAN, QSOUNDPAN, BASS, TREBLE, EQUALIZER, 或者是有效的控制器类型的数字 (请看 声卡分析脚本).如果指定的 组件类型 缺少指定的 控制类型, ErrorLevel 将表明有问题.
DeviceNumber | 如果省略此参数, 默认值为 1 (第一个音频设备), 通常是系统默认的录制和播放设备.可以通过指定一个大于 1 的数字来操作其他的音频设备.此参数可以是一个 表达式.

ErrorLevel

如果命令成功执行 ErrorLevel 被设置为 0.否则它被设置为下列短语的其中一个:

Invalid Control Type or Component Type
Can't Open Specified Mixer
Mixer Doesn't Support This Component Type
Mixer Doesn't Have That Many of That Component Type
Component Doesn't Support This Control Type
Can't Get Current Setting
Can't Change Setting

备注

在 Windows Vista 或更高版本的系统上, SoundSet 和 SoundGet 命令仅对脚本自己有效 (此问题可能会在未来的版本中解决). 至少有两种方法可以绕弯解决这个问题:

1) 在 "AutoHotkey.exe" (或 已编译脚本)文件的属性对话框中, 改变兼容性设置为 "Windows XP".

2) 使用发送音量控制键的脚本来改变整个系统的主音量. 例如:

Send {Volume_Up}  ; Raise the master volume by 1 interval (typically 5%).
Send {Volume_Down 3}  ; Lower the master volume by 3 intervals.
Send {Volume_Mute}  ; Mute/unmute the master volume.

为了发现安装在系统上的音频设备 (混音器) 的功能 -- 例如可用的组件类型和控制类型 -- 请运行 声卡分析脚本.

当 SoundSet 命令改变组件的音量时, 该组件的所有声道 (例如左和右) 都被设置为相同的等级. 换句话说, 任何原来的不平衡的声道设置会丢失. 使用 SoundSetWaveVolume 命令设置 WAVE 组件可以避免此问题, 它在改变音量等级时会尝试维持原有的声道平衡.

使用 SoundGet 命令可以获取一个设置的当前数值.

相关

SoundGet, SoundGetWaveVolume, SoundSetWaveVolume, SoundPlay

示例

; BASIC EXAMPLES:
SoundSet, 50  ; Set the master volume to 50%
SoundSet +10  ; Increase master volume by 10%
SoundSet -10  ; Decrease master volume by 10%
SoundSet, 1, Microphone, mute  ; mute the microphone
SoundSet, +1, , mute  ; Toggle the master mute (set it to the opposite state)
SoundSet, +20, Master, bass  ; Increase bass level by 20%.
if ErrorLevel
    MsgBox, The BASS setting is not supported for MASTER.

?

; SOUNDCARD ANALYSIS
; Use the following script to discover your soundcard's capabilities (component types and control types).
; It displays the results in a simple ListView.

SetBatchLines -1
SplashTextOn,,, Gathering Soundcard Info...

; Most of the pure numbers below probably don't exist in any mixer, but they're queried for completeness.
; The numbers correspond to the following items (in order): CUSTOM, BOOLEANMETER, SIGNEDMETER, PEAKMETER,
; UNSIGNEDMETER, BOOLEAN, BUTTON, DECIBELS, SIGNED, UNSIGNED, PERCENT, SLIDER, FADER, SINGLESELECT, MUX,
; MULTIPLESELECT, MIXER, MICROTIME, MILLITIME
ControlTypes = VOLUME,ONOFF,MUTE,MONO,LOUDNESS,STEREOENH,BASSBOOST,PAN,QSOUNDPAN,BASS,TREBLE,EQUALIZER,0x00000000, 0x10010000,0x10020000,0x10020001,0x10030000,0x20010000,0x21010000,0x30040000,0x30020000,0x30030000,0x30050000,0x40020000,0x50030000,0x70010000,0x70010001,0x71010000,0x71010001,0x60030000,0x61030000

ComponentTypes = MASTER,HEADPHONES,DIGITAL,LINE,MICROPHONE,SYNTH,CD,TELEPHONE,PCSPEAKER,WAVE,AUX,ANALOG,N/A

; Create a ListView and prepare for the main loop:
Gui, Add, Listview, w400 h400 vMyListView, Component Type|Control Type|Setting|Mixer
LV_ModifyCol(4, "Integer")
SetFormat, Float, 0.2  ; Limit number of decimal places in percentages to two.

Loop  ; For each mixer number that exists in the system, query its capabilities.
{
    CurrMixer := A_Index
    SoundGet, Setting,,, %CurrMixer%
    if ErrorLevel = Can't Open Specified Mixer  ; Any error other than this indicates that the mixer exists.
        break
    ; For each component type that exists in this mixer, query its instances and control types:
    Loop, parse, ComponentTypes, `,
    {
        CurrComponent := A_LoopField
        ; First check if this component type even exists in the mixer:
        SoundGet, Setting, %CurrComponent%,, %CurrMixer%
        if ErrorLevel = Mixer Doesn't Support This Component Type
            continue  ; Start a new iteration to move on to the next component type.
        Loop  ; For each instance of this component type, query its control types.
        {
            CurrInstance := A_Index
            ; First check if this instance of this instance even exists in the mixer:
            SoundGet, Setting, %CurrComponent%:%CurrInstance%,, %CurrMixer%
            ; Checking for both of the following errors allows this script to run on older versions:
            if ErrorLevel in Mixer Doesn't Have That Many of That Component Type,Invalid Control Type or Component Type
                break  ; No more instances of this component type.
            ; Get the current setting of each control type that exists in this instance of this component:
            Loop, parse, ControlTypes, `,
            {
                CurrControl := A_LoopField
                SoundGet, Setting, %CurrComponent%:%CurrInstance%, %CurrControl%, %CurrMixer%
                ; Checking for both of the following errors allows this script to run on older versions:
                if ErrorLevel in Component Doesn't Support This Control Type,Invalid Control Type or Component Type
                    continue
                if ErrorLevel  ; Some other error, which is unexpected so show it in the results.
                    Setting := ErrorLevel
                ComponentString := CurrComponent
                if CurrInstance > 1
                    ComponentString = %ComponentString%:%CurrInstance%
                LV_Add("", ComponentString, CurrControl, Setting, CurrMixer)
            }  ; For each control type.
        }  ; For each component instance.
    }  ; For each component type.
}  ; For each mixer.

Loop % LV_GetCount("Col")  ; Auto-size each column to fit its contents.
    LV_ModifyCol(A_Index, "AutoHdr")

SplashTextOff
Gui, Show
return

GuiClose:
ExitApp


SoundSetWaveVolume

更改一个音频设备的波形输出音量。

SoundSetWaveVolume, Percent [, DeviceNumber]

参数

Percent | 包括 -100 至 100 的百分率数值 (它可以是一个浮点数或者表达式)。如果数值以加号或者减号开头，当前的音量等级将往上或者往下调指示的数值。否则，音量将明确地设置为 Percent 指示的等级。
DeviceNumber | 如果省略此参数，其默认为 1 (第一个音频设备)，通常是系统默认的录音和播放设备。可以通过指定一个大于 1 的数字来操作其他的音频设备。

ErrorLevel

如果遇到问题，ErrorLevel 设为 1，其他情况为 0。

注意

SoundSetWaveVolume 在 Windows Vista 上不起作用(可能会在将来的版本中得到解决)。下面是一种更改整个系统的总音量的方法：

Send {Volume_Up}  ;将总音量增加 1 个音程 (一般是 5%)。
Send {Volume_Down 3}  ;将总音量降低 3 个音程。
Send {Volume_Mute}  ;将总音量静音/取消静音。

当前的波形输出音量的等级可通过 SoundGetWaveVolume 来获取。其他设置例如总音量、合成器、麦克风、静音、高音和低音可以用 SoundSet 和 SoundGet 进行设定和获取。

与 SoundSet 不同，此命令在更改音量等级时会尝试维持现有的声道(例如左和右)平衡。

相关命令

SoundGetWaveVolume, SoundSet, SoundGet, SoundPlay

示例

SoundSetWaveVolume, 50  ;将波形音量设为一半。
SoundSetWaveVolume, -10  ;将当前的等级减少 10 (例如 80 将变成 70)。
SoundSetWaveVolume, +20  ;将当前的等级增加 20。


FormatTime

转换 YYYYMMDDHH24MISS 时间戳到指定的日期/时间格式.

FormatTime, OutputVar [, YYYYMMDDHH24MISS, Format]

参数

OutputVar | 用于保存结果的变量名称.
YYYYMMDD... | 此参数留空,则使用当前的本地日期和时间. 否则, 请指定 YYYYMMDDHH24MISS 格式的时间戳中所有或主要的部分. 如果时间戳中日期和/或时间部分是无效的 -- 例如平年的二月29日 -- 在 OutputVar 中日期和/或时间将被忽略. 尽管仅支持 1601 到 9999 年份, 早于1601年的时间戳仍然可以生成格式化的时间, 不过仅有其中的时间部分有效.
Format | 如果省略, 默认格式为长日期后接着时间, 它们都将根据当前用户区域设置进行格式化. 例如: 4:55 PM Saturday, November 27, 2004 否则, 请指定下面的一个或多个日期-时间格式, 以及任何原义的空格和标点符号 (逗号不需要转义; 它们可以正常使用). 在后面的例子中, 请注意 M 必须为大写: M/d/yyyy h:mm tt

日期格式 (区分大小写)

d | 不含前导零的天数 (1 - 31)
dd | 含前导零的天数 (01 – 31)
ddd | 在当前的用户语言里星期几的简称 (例如 Monday)
dddd | 在当前的用户语言里星期几的全称 (例如 Monday)
M | 含前导零的月份 (1 – 12)
MM | 含前导零的月份 (01 – 12)
MMM | 在当前的用户语言里月份的简称 (例如 Jan)
MMMM | 在当前的用户语言里月份的全称 (例如 January)
y | 不含世纪的年份, 不含前导零 (0 – 99)
yy | 不含世纪的年份, 含前导零 (00 - 99)
yyyy | 含世纪的年份. 例如: 2005
gg | 当前用户区域设置的时代/纪元字符串(如果没有则为空)

时间格式 (区分大小写)

h | 不含前导零的小时数; 十二小时制格式 (1 - 12)
hh | 含前导零的小时数; 十二小时制格式 (01 – 12)
H | 不含前导零的小时数; 二十四小时制格式 (0 - 23)
HH | 含前导零的小时数; 二十四小时制格式 (00– 23)
m | 不含前导零的分钟数 (0 – 59)
mm | 含前导零的分钟数 (00 – 59)
s | 不含前导零的秒数 (0 – 59)
ss | 含前导零的秒数 (00 – 59)
t | 单字符时间标记, 例如 A 或 P (取决于区域设置)
tt | 多字符时间标记, 例如 AM 或 PM (取决于区域设置)

下列格式必须 单独 使用; 即在 Format 参数中不能含有其他格式或文本. 这些格式不区分大小写.

(Blank) | 留空 Format 参数则生成长日期后跟着时间. 例如, 在某些区域设置中它可能看起来像这样 4:55 PM Saturday, November 27, 2004
Time | 当前用户区域设置的时间表示, 例如 5:26 PM
ShortDate | 当前用户区域设置的短日期表示, 例如 02/29/04
LongDate | 当前用户区域设置的长日期表示, 例如 Friday, April 23, 2004
YearMonth | 当前用户区域设置的年份和月份格式, 例如 February, 2004
YDay | 不含前导零的年份的天数 (1 – 366)
YDay0 | 含前导零的年份的天数 (001 – 366)
WDay | 星期的天数 (1 – 7). 星期日为 1.
YWeek | ISO 8601 中规定的完全年份和周数. 例如: 200453. 如果新年里的含有1月1日的星期含有四天或更多, 那么它被称为是第一星期. 否则, 它是前一年的最后一周, 并且下一周才是新年的第一周. 因此, 1月4日和1月的首个星期四总是在第一周.

附加选项

下列选项可以紧跟在 YYYYMMDDHH24MISS 格式的时间戳参数后 (如果没有时间戳, 它们也可以单独使用). 在下面的例子中, 请注意最后的四项间没有逗号:

FormatTime, OutputVar, 20040228 LSys D1 D4

R: 与上述功能相反. 让日期在时间之前 (仅当 Format 为空时才有意义).

Ln: 如果此选项 不 存在, 则使用当前用户区域设置来格式化字符串. 要使用系统的区域设置, 请指定 LSys. 要使用特定的区域设置, 请指定字母 L 后面跟着十六进制或十进制的区域设置标识符 (LCID). 关于如何构建 LCID 的信息, 请在 www.microsoft.com 上搜索下列短语: Locale Identifiers

Dn: 日期选项. 请指定 n 为下列数字的其中一个:
0: 强制使用默认选项. 这也使得短日期生效.
1: 使用短日期 (仅当 Format 为空时才有意义; 与 2 和 8 不兼容).
2: 使用长日期 (仅当 Format 为空时才有意义; 与 1 和 8 不兼容).
4: 使用备用日历Use alternate calendar (如果有).
8: 使用年份-月份格式 (仅当 Format 为空时才有意义; 与 1 和 2 不兼容). 需要Windows 2000或更高版本的系统.
0x10: 为从左到右的阅读顺序布局添加标记. 仅在 Windows 2000 或更高版本的系统上才有效.
0x20: 为从右到左的阅读顺序布局添加标记. 仅在 Windows 2000 或更高版本的系统上才有效.
0x80000000: Do not obey any overrides the user may have in effect for the system's default date format.
0x40000000: 使用系统 ANSI 代码页而不是区域设置代码页进行字符串转换.

Tn: 时间选项. 请指定 n 为下列数字的其中一个:
0: 强制使用默认选项.这也使得分钟数和秒数被显示.
1: 省略分钟数和秒数.
2: 省略秒数.
4: 省略时间标记 (例如 AM/PM).
8: 始终使用二十四小时制而不是十二小时制.
12: 上面两种参数的组合.
0x80000000: Do not obey any overrides the user may have in effect for the system's default time format.
0x40000000: 使用系统 ANSI 代码页而不是区域设置代码页进行字符串转换.

请注意: Dn 和 Tn 参数可以重复多次以使多个选项生效, 例如: FormatTime, OutputVar, 20040228 D2 D4 T1 T8

备注

从 Format 到 OutputVar 的转录时, 你希望原义转录的字母和数字必须包含在单引号中, 例如: 'Date:' MM/dd/yy 'Time:' hh:mm:ss tt

相比之下, 非字母数字字符, 例如空格,制表符,换行符 (`n), 斜杠,冒号,逗号和其他标点不需要包围在单引号中. 例外情况是单引号字符本身: 要产生原义的单引号, 请使用四个连续的单引号 (''''), 或仅使用两个引号如果它们已经包含在外部的一对引号中.

如果 Format 参数中同时包含日期和时间元素, 它们不能混用. 换句话说, 此字符串应该可分成两半: 一半时间,一半日期. 例如, 一个包含 "hh yyyy mm" 的格式字符串不会产生期望的结果, 因为它在两个时间元素间包含日期元素.

当 Format 参数中包含数值的天数 (d 或 dd) 跟着月份的全称 (MMMM), 则使用月份名称的所有格形式 (如果当前语言有所有格形式的话).

如果 Format 包含超过 2000 个字符, OutputVar 将被置空.

相关提示, 日期和时间的加减可以使用 EnvAdd 和 EnvSub 命令进行.

相关

要进行反向的转换 -- 即 从 一个格式化的日期/时间 转到 YYYYMMDDHH24MISS 格式 -- 请参阅 www.autohotkey.com/forum/topic20405.html

请参考: Gui DateTime control, SetFormat, Transform, 内置的日期和时间变量, FileGetTime

示例

FormatTime, TimeString
MsgBox The current time and date (time first) is %TimeString%.

FormatTime, TimeString, R
MsgBox The current time and date (date first) is %TimeString%.

FormatTime, TimeString,, Time
MsgBox The current time is %TimeString%.

FormatTime, TimeString, T12, Time
MsgBox The current 24-hour time is %TimeString%.

FormatTime, TimeString,, LongDate
MsgBox The current date (long format) is %TimeString%.

FormatTime, TimeString, 20050423220133, dddd MMMM d, yyyy hh:mm:ss tt
MsgBox The specified date and time, when formatted, is %TimeString%.

FormatTime, TimeString, 200504, 'Month Name': MMMM`n'Day Name': dddd
MsgBox %TimeString%

FormatTime, YearWeek, 20050101, YWeek
MsgBox January 1st of 2005 is in the following ISO year and week number: %YearWeek%

?

; Change the date-time stamp of a file:
FileSelectFile, FileName, 3,, Pick a file
if FileName =  ; The user didn't pick a file.
    return
FileGetTime, FileTime, %FileName%
FormatTime, FileTime, %FileTime%   ; Since the last parameter is omitted, the long date and time are retrieved.
MsgBox The selected file was last modified at %FileTime%.

?

; The following function converts the specified number of seconds into the corresponding
; number of hours, minutes, and seconds (hh:mm:ss format).

MsgBox % FormatSeconds(7384)  ; 7384 = 2 hours + 3 minutes + 4 seconds. It yields: 2:03:04

FormatSeconds(NumberOfSeconds)  ; Convert the specified number of seconds to hh:mm:ss format.
{
    time = 19990101  ; *Midnight* of an arbitrary date.
    time += %NumberOfSeconds%, seconds
    FormatTime, mmss, %time%, mm:ss
    return NumberOfSeconds//3600 ":" mmss  ; This method is used to support more than 24 hours worth of sections.
}


IfInString / IfNotInString

检查 变量 是否包含指定的字符串.

IfInString, var, SearchString
IfNotInString, var, SearchString
Position := InStr(Haystack, Needle [, CaseSensitive?, StartingPos]]) ; 参见 InStr() 函数 了解详细信息.

参数

var | 为寻找匹配而被搜索的 变量 名称.
SearchString | 要搜索的字符串. 如果没有启用 StringCaseSense, 那么匹配过程不区分大小写.

备注

内置变量 %A_Space% 和 %A_Tab% 分别包含单个空格和单个 tab 字符, 单独搜索这些字符时它们可能很有用.

另一个命令可以和此命令在同一行. 换句话说, 这两个语句是等同的:

IfInString, MyVar, abc, Gosub, Process1
IfInString, MyVar, abc
    Gosub, Process1

不过, 除命名命令外的其他项不支持与此命令在相同行. 例如:

IfInString, MyVar, abc, found := true  ; 无效的.

相关

InStr(), RegExMatch(), StringGetPos, StringCaseSense, IfEqual, if var in/contains MatchList, if var between, if var is type, 区块, Else

示例

Haystack = abcdefghijklmnopqrs
Needle = abc
IfInString, Haystack, %Needle%
{
    MsgBox, The string was found.
    return
}
else
    Sleep, 1


If var [not] in/contains value1,value2,...

If var [not] in value1,value2,...
If var [not] contains value1,value2,...

检查 变量的 内容是否匹配列表中的某项.

if Var in MatchList
if Var not in MatchList

if Var contains MatchList
if Var not contains MatchList

参数

Var 需要被检查的 变量 名称. 对于 "in" 运算符, 需要准确匹配列表中的某项. 对于 "contains" 运算符, 会更容易形成匹配: 只要列表中的某项作为子字符串包含于 Var 中.
MatchList

逗号分隔的字符串列表, 其中的每个字符串都将与 Var 的内容进行比较以寻找匹配. 在分隔逗号周围的任何空格或 tab 都是有意义的, 表示它们也是匹配字符串的一部分. 例如, 如果 MatchList 被设置为 ABC , XYZ, 这时 Var 必须包含带有尾随空格的 ABC 或带有前导空格的 XYZ 才形成匹配.

在匹配列表中两个连续的逗号产生单个文字逗号. 例如, 后面的匹配列表会在 string1 的末尾产生单个文字逗号: If Var In string1,,,string2. 同样地, 后面的匹配列表仅包含其中含有一个文字逗号的单个项目: If Var In single,,item. 要在列表中包含空的项目, 那么像这个例子那样把逗号作为首个字符: If Var In ,string1,string2 (用于 "contains" 运算符时, 由于在所有字符串中都可以找到空项, 所以空项将总是会形成匹配).

因为 MatchList 中的每一项并不是作为独立的参数, 所以此列表可以完整的包含在一个变量中. 事实上, 如果此列表的长度超过 16383, 那么列表的全部或部分必须包含在变量中以变量表示, 因为这个长度是任何脚本行的最大长度. 例如, MatchList 可以由 of %List1%,%List2%,%List3%, 其中的每个子列表包含了用来匹配词组的一个大的列表.

列表中任何长度超过 16384 字符的单个项目, 超出长度的那些字符将被视为一个新列表项. 因此, 通常最好避免包含这样的项目.

备注

比较总是按字母顺序进行, 而不是作为数字. 例如, 字符串 "11" 不会匹配列表项 "11.0".

除了支持搜索多个字符串 (其中任何一个都将形成匹配) 外, "contains" 运算符的作用与 IfInString/IfNotInString 相同.

可以使用 "StringCaseSense On" 来设置在比较时区分大小写.

如果 MatchList 较长, 可以通过 延续片段 的方法将其分解成较短的几行, 这样可以增加可读性和可维护性.

运算符 "between", "is", "in" 和 "contains" 不支持用于 表达式 中.

相关

if var between, IfEqual/Greater/Less, IfInString, StringCaseSense, 区块, Else

示例

if var in exe,bat,com
    MsgBox The file extension is an executable type.

if var in 1,2,3,5,7,11 ; 避免在列表中添加了空格.
    MsgBox %var% is a small prime number.

if var contains 1,3  ; 注意这里把值作为字符串而不是数字进行比较.
    MsgBox Var contains the digit 1 or 3 (Var could be 1, 3, 10, 21, 23, etc.)

if var in %MyItemList%
    MsgBox %var% is in the list.

InputBox, UserInput, Enter YES or NO
if UserInput not in yes,no
    MsgBox Your input is not valid.

WinGetTitle, active_title, A
if active_title contains Address List.txt,Customer List.txt
    MsgBox One of the desired windows is active.
if active_title not contains metapad,Notepad
    MsgBox But the file is not open in either Metapad or Notepad.


Sort

以字母, 数字或随机顺序排列变量的内容 (可以选择是否移除重复项).

Sort, VarName [, Options]

参数

VarName | 内容需要排序的变量名称.
Options | 见下表.

选项

由下列字母中的零个或多个组成的字符串 (顺序任意, 中间用空格隔开是可选的):

C: 区分大小写的排序 (如果 N 选项同时存在则此选项被忽略). 如果 C 和 CL 两个选项同时省略, 在排序中大写字母 A-Z 被视为等同于它们相应的小写形式.

CL [v1.0.43.03+]: 依据当前用户区域设置的不区分大小写的排序. 例如, 大多数英语和西欧地区把字母 A-Z 和 ANSI 字母例如 ? 和 ü 等同于它们的小写形式. 这种方法也使用"单词排序", 它把单词中的连字符和撇号例如 "coop" 和 "co-op" 保持在一起. 根据需要排序的项目内容, 它的执行情况比不敏感的默认方法差了 1 到 8 倍.

Dx: 指定 x 作为分隔符, 它决定了 VarName 中每个项目的开始和结束. 如果此选项不存在, x 默认为换行符 (`n), 这样当 VarName 中每行以 LF (`n) 或 CR+LF (`r`n) 结束时可以正确的排序.

F MyFunction [v1.0.47+]: 根据 MyFunction 中的标准进行自定义排序(尽管这样的排序需要更长的时间). 使用字母 "F" 跟着可选的空格/制表符,再跟着 函数 名, 可以对列表中的任意两项进行比较. 此函数必须接受两个或三个参数. 当函数判断出首个参数大于第二个, 它应该返回一个正整数; 当判断出两个参数相等, 应该返回 0, "", 或不返回; 否则, 它应该返回一个负整数. 如果返回值中含有小数点, 这部分被忽略 (例如 0.8 等同于 0). 如果含有第三个参数, 它接受原始/未排序列表中第二个项目相对于第一个的偏移(字符数)(请参看示例). 最后, 此函数使用和脚本相同的全局设置 (例如 StringCaseSense), Sort 命令会调用它的设置.

请注意: F 选项会使得除 D, Z, 和 U 外的其他选项被忽略 (尽管如此 N, C, 和 CL 仍会影响对于 重复项 的检测). 并且, 当指定的函数出现下列情况时不会进行排序: 1) 函数不存在; 2) 接受的参数个数少于两个; 或 3) 首个或第二个参数是 ByRef 类型的.

N: 数字排序: 把每个项目看成数字而不是字符串进行排序 (例如, 如果此选项不存在, 根据字母顺序字符串 233 被认为是小于字符串 40). 十进制和十六进制字符串 (例如 0xF1) 都被认为是数字. 不是以数字开始的字符串在排序中被看成是零. 把数字作为64位浮点值进行处理, 这样可以考虑到小数部分的每位数字(如果有的话).

Pn: 根据第 n 个位置的字符进行排序(n 不能使用十六进制数). 如果此选项不存在, n 默认为 1, 这是首个字符的位置. 在字符串间排序比较时从它们的第 n 个字符开始. 如果 n 大于某个字符串的长度, 在排序中此字符串被看成是空的. 和选项 N (数字排序)一起使用时, 此时使用字符串的字符位置, 它不一定和数字位的位置相同.

R: 逆向排序 (根据其他选项进行字母或数字排序).

Random: 随机排序. 此选项会使得除 D, Z, 和 U 外的其他选项被忽略 (尽管如此 N, C, 和 CL 仍会影响对于重复项的检测). 示例:

Sort, MyVar, Random
Sort, MyVar, Random Z D|

U: 移除列表中的重复项使得每个项都是唯一的. ErrorLevel 被设置为移除的项目数 (如果没有则为 0). 如果 C 选项存在, 项目的大小写必须匹配才被看成是等同的. 如果 N 选项存在, 像 2 这个项目将被看成是 2.0 的一个副本. 如果 Pn 或 \ (反斜杠) 选项存在, 整个项目必须相同才看成重复项, 而不仅是用于排序的子字符串. 如果 Random 或 F Function 选项存在, 仅删除排序结果中彼此相邻的重复项(说明:这句中"F Function"在原英文帮助中中间的不是空格而是斜杠,我觉得可能是错误). 例如, 对 "A|B|A" 进行随机排序, 结果中可能包含一个或两个 A.

Z: 要理解此选项, 请考虑内容为 RED`nGREEN`nBLUE`n 的变量. 如果 Z 选项不存在, 最后的换行符 (`n) 被认为是最后那个项目的一部分, 因此变量中只有三个项目. 不过当指定了选项 Z, 最后的 `n (如果存在) 将被认为分隔了列表最后的一个空项目, 因此变量中有四个项目 (最后一个是空的).

\: 根据每个项目中最后的反斜杠后面的子字符串进行排序. 如果项目中不含有反斜杠, 则使用整个项目作为排序的子字符串. 此选项在排序单独的文件名称有用 (即不包含其路径), 例如在下面的例子中, 排序后 AAA.txt 行在 BBB.txt 行的上面, 因为在排序中它们的目录被忽略了:
C:\BBB\AAA.txt
C:\AAA\BBB.txt
请注意: 当反斜杠选项存在时 N 和 P 选项被忽略.

备注

此命令常用于排序包含行列表的变量, 其中的每行以新行符 (`n) 结束. 得到含有行列表的变量的一个方法是使用 FileRead 命令装载整个文件.

如果 VarName 是 Clipboard 并且剪贴板中包含文件 (例如从打开的资源管理器窗口中复制的文件), 这些文件将被它们文件名排序后的列表覆盖. 换句话说, 操作后剪贴板将不再包含文件本身.

仅当 U 选项存在时此命令才会改变 ErrorLevel 的值.

变量所使用的最大内存空间可以通过 #MaxMem 增加.

对一个占用大内存的变量进行排序后当它的内容不再需要时, 您可以清空它来释放占用的内存, 例如 MyVar =

相关

FileRead, file-reading loop, parsing loop, StringSplit, RegisterCallback(), clipboard, #MaxMem

示例

MyVar = 5,3,7,9,1,13,999,-4
Sort MyVar, N D,  ; Sort numerically, use comma as delimiter.
MsgBox %MyVar%   ; The result is -4,1,3,5,7,9,13,999

; The following example sorts the contents of a file:
FileRead, Contents, C:\Address List.txt
if not ErrorLevel  ; Successfully loaded.
{
    Sort, Contents
    FileDelete, C:\Address List (alphabetical).txt
    FileAppend, %Contents%, C:\Address List (alphabetical).txt
    Contents =  ; Free the memory.
}

; The following example makes Win+C a hotkey to copy files from an open
; Explorer window and put their sorted filenames onto the clipboard:
cClipboard = ; Must be blank for detection to work.
Send ^c
ClipWait 2
if ErrorLevel
    return
Sort Clipboard
MsgBox Ready to be pasted:`n%Clipboard%
return

; The following examples demonstrate custom sorting via a callback function.
MyVar = def`nabc`nmno`nFGH`nco-op`ncoop`ncop`ncon`n
Sort, MyVar, F StringSort
StringSort(a1, a2)
{
    return a1 > a2 ? 1 : a1 < a2 ? -1 : 0  ; Sorts alphabetically based on the setting of StringCaseSense.
}

MyVar = 5,3,7,9,1,13,999,-4
Sort, MyVar, F IntegerSort D,
IntegerSort(a1, a2)
{
    return a1 - a2  ; Sorts in ascending numeric order.  This method works only if the difference is never so large as to overflow a signed 64-bit integer.
}

MyVar = 1,2,3,4
Sort, MyVar, F ReverseDirection D,  ; Reverses the list so that it contains 4,3,2,1
ReverseDirection(a1, a2, offset)
{
    return offset  ; Offset is positive if a2 came after a1 in the original list; negative otherwise.
}


StringCaseSense

决定在字符串比较的时候是否区分大小写（默认是“不区分大小写”）。

StringCaseSense, On|Off|Locale

参数

On|Off|Locale

On：字符串比较的时候区分大小写。这个设置也让 expression equal sign operator (=) 以及 InStr() 的大小写不敏感模式按照下面的 locale 方式进行处理。

Off：不区分大小写，字母 A-Z 被认为和小写字母相同。为了保持高效和向后兼容性，这个是所有脚本的默认设置（使用 Locale 比使用 Off 慢 1 - 8 倍，取决于被比较的字符串）。

Locale [v1.0.43.03+]：字符串不区分大小写，并且服从区域规则。例如，大多数英国以及西欧地区，不仅将 A-Z 等同于它们所对应的小写字母，同时也将 ANSI 字母比如 Ä 和 Ü 也等同于它们所对应的小写形式。

注意

这个设置适用于：

  • Expression comparison operators/字符串比较符号（除了 ==）。但是，由于 equal-sign operator (=) 总是不区分大小写的，当 StringCaseSense 设置为 On 的时候，它使用 Locale 模式。
  • IfInString ，tringGetPos ，以及 InStr() 。但是 InStr() 在 CaseSensitive 参数是 true 的时候，该设置不起作用。
  • StringReplace
  • if var in/contains MatchList ，if var between ，以及 IfEqual and its family 。

内置变量 A_StringCaseSense 存储了当前的设置（单词 On ，Off ，或者 Locale ）。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将 StringCaseSense 的设置重置为默认值。要更改 StringCaseSense 的默认值，可以将命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

IfEqual, IfInString, if var between, StringReplace, StringGetPos

示例

StringCaseSense Locale


StringGetPos

返回指定的子字符串在一个字符串中的位置。

StringGetPos, OutputVar, InputVar, SearchText [, L#|R#, Offset]
Position := InStr(Haystack, Needle [, CaseSensitive?, StartingPos]) ; 具体请查看 InStr() 函数 。

参数

OutputVar | 存储子字符串在 InputVar 中的位置的变量名。在 StringGetPos 命令中，第一个字符的位置是 0 ，而在 InStr() 函数中第一个字符的位置是 1 。
InputVar | 需要被查找的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。
SearchText | 查找的文本。不区分大小写，除非打开了 StringCaseSense 。
L#|R# | 当 SearchText 在 InputVar 中出现不止一次的时候，这个参数决定查找的方向。如果省略该参数，将从 InputVar 的左边开始查找，直到找到首个匹配的结果。如果该参数使用 1 或者 R ，将从 InputVar 的右边开始查找，直到找到首个匹配的结果。 要查找非首个匹配，在字母 L 或 R 后跟上相应的数字。例如，要从右边开始查找第四个匹配的结果，指定参数 r4 。注意：如果指定的数字小于或等于 0 ，不会找到匹配的结果。
Offset | 偏移。从左边或右边（取决于上面的参数）开始跳过多少个字符再开始查找。如果省略，默认是 0 。例如，下面的例子会从左边第十个字符开始查找：StringGetPos, OutputVar, InputVar, abc, , 9 。这个参数可以是一个 expression/表达式 。

ErrorLevel

当 InputVar 中未包含 SearchText 的时候 ErrorLevel/错误级别 被设置为 1 ，包含的时候设置为 0 。

注意

与 StringMid 以及 InStr() 不同的是，在 StringGetPos 中第一个字符的位置是 0 。

返回的位置总是相对于 InputVar 的第一个字符的，而与是否使用 L#|R# 以及 Offset 参数无关。例如，字符串 “abc”在 123abc789 中的位置永远是 3 ，不管使用了什么参数。

如果在指定的条件下，在 InputVar 中未能找到 SearchText ，OutputVar 会被设置为 -1 ，ErrorLevel 会被设置为 1 。

使用 SplitPath 可以更容易将一个文件路径分解为目录，文件名，扩展名。

内置变量 %A_Space% 和 %A_Tab% 包含了一个单独的空格和一个单独的制表符。当你需要单独搜索空格或制表符，或者在 SearchText 的开头或结尾使用空格或制表符的时候会非常有用。

相关命令

InStr(), RegExMatch(), IfInString, if var in/contains MatchList, StringCaseSense, StringReplace, SplitPath, StringLeft, StringRight, StringMid, StringTrimLeft, StringTrimRight, StringLen, StringLower, StringUpper, if var is type

示例

Haystack = abcdefghijklmnopqrs
Needle = def
StringGetPos, pos, Haystack, %Needle%
if pos >= 0
    MsgBox, The string was found at position %pos%.

; 示例 #2：
; 将一个完整的文件路径分解为各个组成部分。
; 注意，使用 StringSplit 或者
; parsing loop 会更加方便，这里只是举个例子。
FileSelectFile, file, , , Pick a filename in a deeply nested folder:
if file <>
{
    StringLen, pos_prev, file
    pos_prev += 1 ; 调整位置到最后一个字符之后。
    Loop
    {
        ; 从右边开始查找第N个匹配
        StringGetPos, pos, file, \, R%A_Index%
        if ErrorLevel
            break
        length := pos_prev - pos - 1
        pos_prev := pos
        pos += 2  ; 为了使用StringMid进行调整。
        StringMid, path_component, file, %pos%, %length%
        MsgBox Path component #%a_index% (from the right) is:`n%path_component%
    }
}


StringLeft / StringRight

从一个字符串的左边或右边开始提取一定数量的字符。

StringLeft, OutputVar, InputVar, Count
StringRight, OutputVar, InputVar, Count
NewStr := SubStr(String, StartPos [, Length]) ; 具体请查看 SubStr() 函数 。

参数

OutputVar | 存储从 InputVar 中提取出来的子字符串的变量名。
InputVar | 被提取的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。
Count | 需要提取的字符数量，可以是 expression/表达式 。如果 Count 小于或等于 0 ， OutputVar 会被设置为空。如果 Count 超过 InputVar 的长度，OutputVar 会被设置为和 InputVar 相同。

注意

在这个命令以及所有其它命令中，OutputVar 可以和 InputVar 相同。

相关命令

SubStr(), StringMid, StringTrimLeft, StringTrimRight, IfInString, StringGetPos, StringLen, StringLower, StringUpper, StringReplace

示例

String = This is a test.
StringLeft, OutputVar, String, 4  ; 在OutputVar中存储“This”
StringRight, OutputVar, String, 5  ; 在OutputVar中存储“test.”


StringLen

获取字符串长度。

StringLen, OutputVar, InputVar
Length := StrLen(String)

参数

OutputVar | 存储字符串长度的变量名。
InputVar | 需要统计长度的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。

注意

如果 InputVar 的内容是由 ClipboardAll 获得的，那么 StringLen 将会返回它的总大小。

相关命令

StrLen(), IfInString, StringGetPos, StringMid, StringTrimLeft, StringTrimRight, StringLeft, StringRight, StringLower, StringUpper, StringReplace

示例

StringLen, length, InputVar
MsgBox, The length of InputVar is %length%.

MsgBox % "The length of MyVar is " . StrLen(MyVar)


StringLower / StringUpper

将一个字符串中的英文字母全部转换为大写或小写。

StringLower, OutputVar, InputVar [, T]
StringUpper, OutputVar, InputVar [, T]

参数

OutputVar | 存储转换后字符串的变量名。
InputVar | 需要进行转换的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。
T | 如果这个参数使用字母 T ，字符串将被转换为标题格式。例如，“GONE with the WIND”将被转换成“Gone With The Wind”。

注意

要判断一个字符或字符串是否全部是大写或小写字母，可以使用“if var is [not] upper/lower”。

在这个命令以及所有其它命令中，OutputVar 可以和 InputVar 相同。

相关命令

IfInString, StringGetPos, StringMid, StringTrimLeft, StringTrimRight, StringLeft, StringRight, StringLen, StringReplace

示例

StringUpper, String1, String1  ; 就是说 output 和 input 可以相同。
StringLower, String2, String2


StringMid

从字符串中指定的位置返回一个或多个字符。

StringMid, OutputVar, InputVar, StartChar [, Count , L]
NewStr := SubStr(String, StartPos [, Length]) ; 具体请查看 SubStr() 函数 。

参数

OutputVar | 存储从 InputVar 中提取出来的子字符串的变量名。
InputVar | 被提取的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。
StartChar | 提取的起始位置，可以是 expression/字符串 。和 StringGetPos 不同，1 代表第一个字符。如果 StartChar 小于1，会自动设置为 1 。如果 StartChar 大于字符串长度，OutputVar 会被设置为空。
Count

在 v1.0.43.10 之后的版本中，这个参数如果省略或留空，默认是一个足够存储所有字符的值。

否则，该参数表示需要提取的字符数量，可以是 expression/表达式。如果 Count 小于或等于 0 ，OutputVar 会被设置为空。如果 Count 超过 InputVar 从 StartChar 开始之后的字符数量，OutputVar 会被设置为 InputVar 从 StartChar 开始之后的所有字符。
L

使用字母 L 可以从 StartChar 开始向左边提取字符，而不是默认的向右边。在下面的例子中，OutputVar 存储的是 Red ：
InputVar = The Red Fox
StringMid, OutputVar, InputVar, 7, 3, L

如果使用了 L 这个参数，同时 StartChar 小于 1 ，OutputVar 会被设置为空。如果 StartChar 大于 InputVar 的长度，只有处于 InputVar 之中的字符会被提取。例如，下面的例子中 OutputVar 存储的是 Fox ：
InputVar = The Red Fox
StringMid, OutputVar, InputVar, 14, 6, L

注意

在这个命令以及所有其它命令中，OutputVar 可以和 InputVar 相同。

相关命令

SubStr(), StringLeft, StringRight, StringTrimLeft, StringTrimRight, IfInString, StringGetPos, StringLen, StringLower, StringUpper, StringReplace

示例

Source = Hello this is a test.
StringMid, the_word_this, Source, 7, 4


StringReplace

替换字符串中指定的子字符串为新的字符串。

StringReplace, OutputVar, InputVar, SearchText [, ReplaceText, ReplaceAll?]

参数

OutputVar | 存储替换后的字符串的变量名。
InputVar | 需要进行替换的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。
SearchText | 被替换的文本。不区分大小写，除非打开了 StringCaseSense 。
ReplaceText | 替换的文本。替换 SearchText 中的内容。如果省略或留空，SearchText 会被替换为空。也就是说，它在 OutputVar 中会被省略。
ReplaceAll? | 如果省略，只有第一个匹配 SearchText 的子字符串会被替换。如果这个参数是 1 、A 或者 All ，则所有匹配的子字符串都将被替换。 使用单词 UseErrorLevel 的话可以在 ErrorLevel/错误级别 中存储被替换的子字符串的数量（如果没有任何子字符串被替换则是 0 ）。UseErrorLevel 包含了“All”的作用。

ErrorLevel

当最后一个参数是 UseErrorLevel 的时候，ErrorLevel/错误级别 中会存储被替换的子字符串的数量（如果没有任何子字符串被替换则是 0 ）。否则，当 InputVar 中未包含 SearchText 的时候 ErrorLevel/错误级别 被设置为 1 ，包含的时候设置为 0 。

注意

在这个命令以及所有其它命令中，OutputVar 可以和 InputVar 相同。

内置变量 %A_Space% 和 %A_Tab% 包含了一个单独的空格和一个单独的制表符。当你需要单独搜索空格或制表符，或者在 SearchText 的开头或结尾使用空格或制表符的时候会非常有用。

在 v1.0.45 版本中，为了改进性能和内存利用，AllSlow 参数已过时。虽然仍然可以指定它，但是不会有任何效果。

相关命令

RegExReplace(), IfInString, StringCaseSense, StringLeft, StringRight, StringMid, StringTrimLeft, StringTrimRight, StringLen, StringLower, StringUpper, StringGetPos, if var is type

示例

; 在剪贴板中移除换行：
StringReplace, clipboard, clipboard, `r`n, , All

; 用加号替换所有空格：
StringReplace, NewStr, OldStr, %A_SPACE%, +, All

; 移除字符串中的所有空行：
Loop
{
    StringReplace, MyString, MyString, `r`n`r`n, `r`n, UseErrorLevel
    if ErrorLevel = 0  ; 不需要再进行替换。
        break
}


StringSplit

使用指定的分隔符将一个字符串分割为一个字符串数组。

StringSplit, OutputArray, InputVar [, Delimiters, OmitChars]

参数

OutputArray

array/数组 名，存储 InputVar 分割成的子字符串。例如，如果这个参数使用 MyArray ，那么变量 MyArray0 会存储分割出来的子字符串的数量（如果未能分割则是 0 ），MyArray1 会存储分割出来的第一个子字符串，MyArray2 会存储分割出来的第二个子字符串，以此类推。

在一个 function/函数 内，要创建一个全局数组而不是局部数组，需要在函数内将 MyArray0 declare/声明 为全局变量（反过来在设置了 assume-global 的函数中要创建一个局部数组则需要将 MyArray0 声明为局部变量）。
InputVar 被分割的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。注意：InputVar 不能与 OutputArray 中的变量重名。
Delimiters

分隔符。如果这个参数留空或省略，InputVar 中的每一个字符都将作为一个子字符串被分割。

否则，Delimiters 可以包含一个或多个字符（区分大小写），每个字符都用来判断从哪里分割 InputVar 。因为分隔符不被认为是子字符串的一部分，所以分隔符不会存入 OutputArray 中。另外，如果在 InputVar 中，一对分隔符之间什么也没有，则相应的数组元素会被设置为空。

例如：`,（转义的逗号）可以将字符串按逗号分割。相似的，%A_Tab%%A_Space% 可以将 InputVar 按空格或制表符分割。

如果需要使用一个字符串作为分隔符，而不是单个字符，首先使用 StringReplace 将文本中与字符串分隔符相同的内容替换为一个在文本中未出现过的字符。参考这个例子，它使用 <br> 作为分隔符：

StringReplace, NewHTML, HTMLString, <br>, ``, All  ; 将所有 <br> 替换为重音符号。
StringSplit, MyArray, NewHTML, ``  ; 再使用重音符号分割字符串。
OmitChars

可选参数，一组字符（区分大小写）。分割出来的字符串数组中每一个元素的开头和结尾如果包含这些字符，这些字符将被移除。例如，如果 OmitChars 参数指定 %A_Space%%A_Tab% ，则所有数组元素中开头和结尾（中间的除外）的所有空格和制表符将被移除。

如果 Delimiters 参数留空，则 OmitChars 表明哪些字符将从数组中移除。

和其它命令的最后一个参数不同，逗号在 OmitChars 中需要转义（`,）。

注意

如果 OutputArray 指定的数组已存在，该命令会替换其中 N 个元素的值。N 是 InputVar 分割出来的子字符串数量。超过 N 之后的元素的值将不会被更改。因此，为了安全最好使用数组第一个元素（MyArray0）来判断到底产生了多少个数组元素。

空格和制表符会被保留，除非使用它们做分隔符。在 AutoTrim 打开的情况下（默认打开），可以将变量赋值给自己来自动移除两端的空格和制表符。例如：MyArray1 = %MyArray1%

如果需要分割的字符串具有标准的 CSV（逗号分隔值）格式，可以使用 parsing loop 内置的 CSV 处理功能。

分割字符串之前需要将字符串排序的话，使用 Sort 命令。

如果你不需要将分割出来的子字符串存储在内存中的话，建议使用 parsing loop —— 特别是 InputVar 比较大的时候，这样将会节省大量内存。例如：

Colors = red,green,blue
Loop, parse, Colors, `,
    MsgBox Color number %A_Index% is %A_LoopField%.

相关命令

Parsing loop, Arrays, Sort, SplitPath, IfInString, StringGetPos, StringMid, StringTrimLeft, StringTrimRight, StringLen, StringLower, StringUpper, StringReplace

示例

TestString = This is a test.
StringSplit, word_array, TestString, %A_Space%, .  ; 删除句号。
MsgBox, The 4th word is %word_array4%.

Colors = red,green,blue
StringSplit, ColorArray, Colors, `,
Loop, %ColorArray0%
{
    this_color := ColorArray%a_index%
    MsgBox, Color number %a_index% is %this_color%.
}


StringTrimLeft / StringTrimRight

从一个字符串的左边或右边移除指定数量的字符。

StringTrimLeft, OutputVar, InputVar, Count
StringTrimRight, OutputVar, InputVar, Count
NewStr := SubStr(String, StartPos [, Length]) ; 具体请查看 SubStr() 函数 。

参数

OutputVar | 存储 InputVar 裁减后的字符串的变量名。
InputVar | 被裁减的字符串变量名。不要在变量名外加百分号，除非你想使用变量中的 内容 作为变量名。
Count | 需要裁减的字符数量，可以是 expression/表达式。如果 Count 小于或等于 0 ，OutputVar 会被设置为与 InputVar 相同。如果 Count 超过 InputVar 的长度，OutputVar 会被设置为空。

注意

在这个命令以及所有其它命令中，OutputVar 可以和 InputVar 相同。

相关命令

SubStr(), StringMid, StringLeft, StringRight, IfInString, StringGetPos, StringLen, StringLower, StringUpper, StringReplace

示例

String = This is a test.
StringTrimLeft, OutputVar, String, 5  ; 在OutputVar中存储“is a test.”
StringTrimRight, OutputVar, String, 6  ; 在OutputVar中存储“This is a”


StrPut / StrGet

StrPut() / StrGet() [AHK_L 46+]

复制字符串到内存地址或来自内存地址, 并可以对其在指定代码页间进行转换.

StrPut(String [, Encoding = None ] )
StrPut(String, Address [, Length] [, Encoding = None ] )
StrGet(Address [, Length] [, Encoding = None ] )

参数

String | 任何字符串. 也可以接受数字.
Address | 字符串将被写入或读取的地址.
Length | 需读取/写入的字符的最大数目, 需要时包含空终止符. 参见返回值.
Encoding | 用于 StrGet 的源编码或用于 StrPut 的目标编码; 例如, "UTF-8", "UTF-16" 或 "CP936". 如果 Address 和 Length 都没有指定, 那么数值标识符必须加上 "CP" 前缀. 指定空字符串或 "CP0" 则使用系统默认 ANSI 代码页.

返回值

对每个函数, 无效的参数会让它们返回空字符串.

StrPut 返回写入的字符数, 如果没有指定 Address 则返回以字符数表示的必须的缓冲区大小, 如果遇到错误则返回 0. 如果 Length 小于源字符串的长度, 那么函数失败且返回 0. 如果 Length 准确等于源字符串的长度, 那么字符串不包含空终止符; 否则返回的数目包含空终止符.

StrGet 返回所请求的进行必要转换后的字符串.

备注

注意 StrPut 的 String 参数或 StrGet 的返回值总是为当前可执行程序的 原生编码, 而 Encoding 则指定写入的或从指定 Address 读取的字符串编码. 如果未指定 Encoding, 则对字符串进行简单长度计算或复制而不进行转换.

如果需要在代码页之间转换, 那么需要的缓存大小可能不同于源 String 的大小.

需要兼容于 AutoHotkey Basic 的脚本仍可以使用 StrPut 和 StrGet, 此时它们是由安装在 函数库 中的 相应的脚本文件 提供的. 这些脚本可以在 AutoHotkey 社区论坛 中找到.

相关

脚本兼容性, FileEncoding, VarSetCapacity()

示例

Length 或 Encoding 都可以在 Address 后直接指定, 不过此时 Encoding 必须用非数值表示:

strA := StrGet(addressA, "cp0")     ; OK
strA := StrGet(addressA, length, 0) ; OK
strA := StrGet(addressA, 0)         ; 错误

可以调用一次 StrPut 来计算字符串在特殊编码时需要的缓冲区大小, 然后再进行编码并把字符串写入缓冲区. 如果您常用 StrPut 操作变量, 那么考虑把此函数添加到您 库 中:

StrPutVar(string, ByRef var, encoding)
{
    ; 确定容量.
    VarSetCapacity( var, StrPut(string, encoding)
        ; StrPut 返回字符数, 但 VarSetCapacity 需要字节数.
        * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    ; 复制或转换字符串.
    return StrPut(string, &var, encoding)
}


Trim

Trim [AHK_L 31+]

移除字符串的开始和/或末尾的字符.

Result :=  Trim(String, OmitChars = " `t")
Result := LTrim(String, OmitChars = " `t")
Result := RTrim(String, OmitChars = " `t")

参数

String | 任何字符串值或变量. 不支持数字.
OmitChars | 一个可选的从 String 的开始和/或末尾排除的字符列表 (区分大小写). 如果省略, 空格和 Tab 将被移除.

示例

text := "  text  "
MsgBox % "No trim:`t '" text "'"
    . "`nTrim:`t '" Trim(text) "'"
    . "`nLTrim:`t '" LTrim(text) "'"
    . "`nRTrim:`t '" RTrim(text) "'"
MsgBox % LTrim("00000123","0")


Control

对控件作出多种改变.

Control, Cmd [, Value, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

Cmd, Value | 见下表.
Control

可以是 ClassNN (控件的类名和实例号) 或控件的名称/文本, 他们都可以通过 Window Spy 来确定.当使用名称/文本时, 匹配模式由 SetTitleMatchMode 决定.如果此参数为空, 将使用目标窗口的顶层控件.

要对一个控件的 HWND (窗口句柄) 进行操作, 请将 Control 参数留空同时在 WinTitle 参数中指定 ahk_id %ControlHwnd% (即使 DetectHiddenWindows 为 OFF, 这样也适用于隐藏的控件) .获取控件的 HWND 的典型方法是使用 ControlGet Hwnd, MouseGetPos, 或 DllCall 命令.
WinTitle | 目标窗口的标题或标题中的部分文字 (匹配模式由 SetTitleMatchMode 决定).如果此参数和后面三个参数都忽略, 默认目标是 上一次匹配窗口.如果此参数是字母 A, 同时省略后面三个参数, 则以当前的活动窗口为目标.要用窗口的类名进行匹配, 请指定 ahk_class ExactClassName (Window Spy 中可以显示类名).要用窗口的 进程标识符 (PID) 进行匹配, 请指定 ahk_pid %PID变量%.要使用 窗口组 进行匹配, 请指定 ahk_group GroupName.要使用窗口的 唯一 ID 进行匹配, 请指定 ahk_id %VarContainingID%.要减小检测范围, 请指定 多重条件.例如: My File.txt ahk_class Notepad
WinText | 如果使用这个参数, 则它应该是目标窗口中某个文本元素的子字符串 (在 Window Spy 中会显示窗口中的文本元素).隐藏文本只有当 DetectHiddenText 设置为 ON 的时候才能检测到.
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被排除.
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被排除.

Cmd, Value

Cmd 和 Value 参数相互依赖, 其用法描述如下.

Check: 打开 (选中) 单选框或复选框.

Uncheck: 关闭单选框或复选框.

Enable: 启用之前禁用的控件.

Disable: 禁用或灰化控件.

Show: 显示之前隐藏的控件.

Hide: 隐藏控件. 另外, 如果你还想同时禁用控件的快捷键 (加下划线的字母), 请通过 "Control Disable" 命令禁用控件.

Style,N 或 ExStyle,N: 分别改变控件的样式或扩展样式. 如果 N 中的首个字符是加号或减号, 则会增加或移除 N 中指定的样式(可同时指定多个样式, 下同). 如果首个字符是脱字符 (^), 则会切换 N 中指定的样式.如果首个字符是数字, 则控件原来的样式被完全覆盖; 也就是说变成 N 中指定的样式. 如果没有匹配的目标窗口/控件或者不能应用指定样式的时候 (这种情况多出现在 Windows 9x 系统上) ErrorLevel 被设置为 1.

改变某些样式后需要使用 WinSet Redraw 重绘整个窗口. 此外, 样式列表 列出了一些样式代码. 例如：

Control, Style, ^0x800000, Edit1, WinTitle  ; Set the WS_BORDER style to its opposite state.

ShowDropDown: 拉下组合框使得它的选项可见.

HideDropDown: 功能与上述命令相反.

TabLeft [, Count] 和 TabRight [, Count]: 在 SysTabControl32 控件中向左或向右移动一个或多个标签页. 如果 Count 省略或为空, 则假定为 1. 想要直接用数字选择标签页, 用比你希望选择的标签页编号小 1 的数字替换下面的数字 5. 换句话说, 0 选择首个标签页, 1 选择第二个, 依此类推:

SendMessage, 0x1330, 5,, SysTabControl321, WinTitle  ; 0x1330 is TCM_SETCURFOCUS.
Sleep 0  ; This line and the next are necessary only for certain tab controls.
SendMessage, 0x130C, 5,, SysTabControl321, WinTitle  ; 0x130C is TCM_SETCURSEL.

Add, String: 将 String 作为一个新的条目添加到列表框和组合框 (和其他可能的类型) 的底部.

Delete, N: 删除列表框或组合框中的第 N 个条目. 对首个条目 N 为 1, 对第二个为 2, 依此类推.

Choose, N: 设置列表框或组合框中的选区为第 N 个条目. 对首个条目 N 为 1, 对第二个为 2, 依此类推. 要选择或取消选择 多选 列表框中的所有项目, 请参照此例:

PostMessage, 0x185, 1, -1, ListBox1, WinTitle  ; Select all listbox items. 0x185 is LB_SETSEL.

ChooseString, String: 设置列表框或组合框中的选区为开始部分匹配 String 的首个条目. 搜索不区分大小写.例如, 如果列表框/组合框包含条目 "UNIX Text", 指定单词 unix (小写) 足以选中它.

EditPaste, String: 在编辑控件的光标处/插入位置粘贴 String (此功能不会影响 clipboard 的内容).

ErrorLevel

如果出现错误, ErrorLevel 被设置为 1, 否则为 0.

备注

为了提高可靠性, 在每次使用此命令后都自动地有一个延迟. (Style 和 ExStyle 除外). 这个延迟可以通过 SetControlDelay 改变.

要获取当前鼠标所指向控件的名称, 请使用 MouseGetPos.

窗口中的标题和文字是大小写敏感的.要检测隐藏窗口, 必须打开 DetectHiddenWindows.

相关

SetControlDelay, ControlGet, GuiControl, ControlGetText, ControlSetText, ControlMove, ControlGetPos, ControlClick, ControlFocus, ControlSend, WinSet

示例

Control, HideDropDown, , ComboBox1, Some Window Title


ControlFocus

在一个窗口特定的控件上设置输入焦点。

ControlFocus [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

Control

可以是控件的名称/文本或 ClassNN (控件的类名和序号)，它们都可以通过 Window Spy 来确定。当使用名称/文本时，匹配模式通过 SetTitleMatchMode 决定。如果此参数为空或省略，目标窗口的顶端控件将被使用。

要对一个控件的 HWND (窗口句柄)进行操作，将 Control 参数留空并为 WinTitle 参数指定 ahk_id %ControlHwnd% (这样即使当 DetectHiddenWindows 是 Off 状态，它也能对隐藏的控件起作用)。一个控件的 HWND 往往由 ControlGet Hwnd 、MouseGetPos 或 DllCall 取得。

WinTitle | 目标窗口的标题或副标题(匹配模式由 SetTitleMatchMode 决定)。如果此参数和后面的3个参数被省略，Last Found Window(最近找到的窗口) 将被使用。如果此参数是字母 A 并且后面的三个参数被省略，激活的窗口将被使用。要使用一个窗口类，指定 ahk_class 确切的类名(通过 Window Spy 显示)。要使用一个 process identifier (PID)(进程标识符)，指定 ahk_pid %包含PID的变量% 。要使用一个 window group(窗口组)，指定 ahk_group GroupName 。要使用一个窗口的 unique ID number(唯一标识符编号)，指定 ahk_id %包含ID的变量% 。通过指定 multiple criteria(多个条件) 缩小搜索范围。 例如：My File.txt ahk_class Notepad
WinText | 如果用到，此参数必须是目标窗口的一个单独 text element(文本对象)的 substring(子字串) (像内置的 Window Spy 工具显示的一样)。如果 DetectHiddenText 是 ON 的状态，隐藏的文本对象将被探测。
ExcludeTitle
标题含有此参数值的窗口将不被考虑。
ExcludeText
文本含有此参数值的窗口将不被考虑。

ErrorLevel

如果遇到一个问题 ErrorLevel 设为 1 ，否则是 0 。

注意

要生效，控件的窗口一般来说必须不能最小化或者隐藏。

为了改善可靠性，在每次使用此命令后都自动地有一个延迟。这个延迟可以通过 SetControlDelay 来改变。

要探测鼠标当前悬停处的控件的名称，使用 MouseGetPos 命令。

窗口标题和文本是区分大小写的。隐藏的窗口将不被探测，除非 DetectHiddenWindows 已被打开。

相关命令

SetControlDelay, ControlGetFocus, Control, ControlGet, ControlMove, ControlGetPos, ControlClick, ControlGetText, ControlSetText, ControlSend

示例

ControlFocus, OK, Some Window Title  ; 在 OK 按键上设置焦点


ControlGet

获取控件的各种类型的信息.

ControlGet, OutputVar, Cmd [, Value, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 用于保存 Cmd 结果的变量名称.
Cmd, Value | 见下表.
Control

可以是 ClassNN (控件的类名和实例号) 或控件的名称/文本, 他们都可以通过 Window Spy 来确定.当使用名称/文本时, 匹配模式由 SetTitleMatchMode 决定.如果此参数为空, 将使用目标窗口的顶层控件.

要对一个控件的 HWND (窗口句柄) 进行操作, 请将 Control 参数留空同时在 WinTitle 参数中指定 ahk_id %ControlHwnd% (即使 DetectHiddenWindows 为 OFF, 这样也适用于隐藏的控件) .获取控件的 HWND 的典型方法是使用 ControlGet Hwnd, MouseGetPos, 或 DllCall 命令.
WinTitle | 目标窗口的标题或标题中的部分文字 (匹配模式由 SetTitleMatchMode 决定).如果此参数和后面三个参数都忽略, 默认目标是 上一次匹配窗口.如果此参数是字母 A, 同时省略后面三个参数, 则以当前的活动窗口为目标.要用窗口的类名进行匹配, 请指定 ahk_class ExactClassName (Window Spy 中可以显示类名).要用窗口的 进程标识符 (PID) 进行匹配, 请指定 ahk_pid %PID变量%.要使用 窗口组 进行匹配, 请指定 ahk_group GroupName.要使用窗口的 唯一 ID 进行匹配, 请指定 ahk_id %VarContainingID%.要减小检测范围, 请指定 多重条件.例如: My File.txt ahk_class Notepad
WinText | 如果使用这个参数, 则它应该是目标窗口中某个文本元素的子字符串 (在 Window Spy 中会显示窗口中的文本元素).隐藏文本只有当 DetectHiddenText 设置为 ON 的时候才能检测到.
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被排除.
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被排除.

Cmd, Value

Cmd 和 Value 参数相互依赖, 其用法描述如下.

List: 从列表视图,列表框, 组合框或下拉列表中获取条目列表.

ListView: 列表视图最常见的例子是资源管理器的文件和文件夹列表 (桌面也是一个列表视图). 从列表视图获取条目列表的语法是:

ControlGet, OutputVar, List, Options, SysListView321, WinTitle, WinText

如果 Options 参数为空或省略, 会获取控件中的所有文本. 除了最后一行外的每行将以一个换行符 (`n) 结束. 在每行内部, 除了最后一个外的每个字段 (列) 将以一个制表符 (`t) 结束.

指定 Options 为 0 或多个下列单词, 彼此间使用一个空格或制表符分隔:

Selected: 仅获取选择 (高亮) 行而不是所有行. 如果没有, OutputVar 被置空.
Focused: 仅获取焦点行.如果没有, OutputVar 被置空.
Col4: 仅获取第四列 (字段) 而不是所有列 (使用你选择的数字替换 4).
Count: 获取控件中总行数 (单个数字表示).
Count Selected: 获取选择 (高亮) 的行数.
Count Focused: 获取焦点行的行号 (位置) (如果没有焦点行则为 0).
Count Col: 获取控件的列数 (如果列的总数无法确定则为 -1).

请注意: 某些应用程序秘密的保存它们的列表视图中的文本, 这样阻止了这些文本被获取. 在这种情况下, ErrorLevel 通常被设置为 0 (表示成功) 但所有获取的字段将是空的. 还要注意的是获取列表视图的文本是不受 #MaxMem 指令限制的.

如果获取成功, ErrorLevel 被设置为 0. 如果失败, 它被设置为 1 同时 OutputVar 被置空. 引起失败的原因有: 1) 目标窗口或控件不存在; 2) 目标控件不是 SysListView32 类型; 3) 拥有列表视图的进程无法打开, 可能由于缺少用户权限或者被锁定了; 4) ColN option 指定了一个不存在的列.

要从列表视图中提取个别行和字段, 请使用 解析循环, 例如:

ControlGet, List, List, Selected, SysListView321, WinTitle
Loop, Parse, List, `n  ; Rows are delimited by linefeeds (`n).
{
    RowNumber := A_Index
    Loop, Parse, A_LoopField, %A_Tab%  ; Fields (columns) in each row are delimited by tabs (A_Tab).
        MsgBox Row #%RowNumber% Col #%A_Index% is %A_LoopField%.
}

相关提示, 列表视图中的列可以通过 SendMessage 命令调整大小, 例如:

SendMessage, 4126, 0, 80, SysListView321, WinTitle  ; 4126 is the message LVM_SETCOLUMNWIDTH.
; In the above, 0 indicates the first column (specify 1 for the second, 2 for the third, etc.)  Also, 80 is the new width.
; Replace 80 with -1 to autosize the column. Replace it with -2 to do the same but also take into account the header text width.

ListBox, ComboBox, DropDownList: 获取控件中的所有文本 (即不支持上面的列表视图选项例如 Count 和 Selected).

除了最后一行外的每行将以一个换行符 (`n) 结束.要使用个别的项目, 请使用 解析循环, 例如:

ControlGet, List, List,, ComboBox1, WinTitle
Loop, Parse, List, `n
    MsgBox Item number %A_Index% is %A_LoopField%.

Checked: 如果复选框或单选框被选中则设置 OutputVar 为 1否则为 0.

Enabled: 如果 Control 是启用的则设置 OutputVar 为 1, 禁用的则为 0.

Visible: 如果 Control 是可见的则设置 OutputVar 为 1, 隐藏的则为 0.

Tab: 设置 OutputVar 为 SysTabControl32 控件的标签页编号. 首个标签页为 1, 第二个为 2, 依此类推. 想要找出标签控件中有多少标签(页), 请参照此例:

SendMessage, 0x1304,,, SysTabControl321, WinTitle  ; 0x1304 is TCM_GETITEMCOUNT.
TabCount = %ErrorLevel%

FindString, String: 设置 OutputVar 为列表框或组合框中精确匹配 String 的条目的编号. 控件中首个条目为 1, 第二个为 2, 依此类推. 如果没有找到匹配, OutputVar 被置空同时 ErrorLevel 被设置为 1.

Choice: 设置 OutputVar 为列表框或组合框中当前选择的条目的名称. 想要获取当前选择项的位置, 请参照此例 (仅使用开始两行的其中一行):

SendMessage, 0x188, 0, 0, ListBox1, WinTitle  ; 0x188 is LB_GETCURSEL (for a ListBox).
SendMessage, 0x147, 0, 0, ComboBox1, WinTitle  ; 0x147 is CB_GETCURSEL (for a DropDownList or ComboBox).
ChoicePos = %ErrorLevel%  ; It will be -1 if there is no item selected.
ChoicePos += 1  ; Convert from 0-based to 1-based, i.e. so that the first item is known as 1, not 0.

LineCount: 设置 OutputVar 为编辑控件中的行数. 所有的编辑控件至少含有一行, 即使控件是空的.

CurrentLine: 设置 OutputVar 为编辑控件中光标处(插入位置)所在的行号. 首行为 1. 如果控件中选择了文本, OutputVar 被设置为选区开始处所在的行号.

CurrentCol: 设置 OutputVar 为编辑控件中光标处(文本插入点)所在的列号. 首列为 1. 如果控件中选择了文本, OutputVar 被设置为选区开始处所在的列号.

Line, N: 设置 OutputVar 为编辑控件中行 N 的文本. 行 1 为首行. 根据控件的性质, OutputVar 可能以一个回车符 (`r) 或一个回车和换行符 (`r`n) 结束. 如果指定的行号其内容是空的或不存在, ErrorLevel 被设置为 1 同时 OutputVar 被置空.

Selected: 设置 OutputVar 为编辑控件中选择的文本. 如果没有选择的文本, OutputVar 将被置空同时 ErrorLevel 被设置为 0 (即没有错误). 某些类型的控件, 如 RichEdit20A, 在某些情况下可能不能从那里得到正确的文本 (例如 Metapad).

Style: 获取一个表示控件样式的 8 位十六进制数. 想了解某些样式请参看 样式表.

ExStyle: 获取一个表示控件扩展样式的 8 位十六进制数.

Hwnd [v1.0.43.06+]: 获取指定控件的句柄 (HWND). 例如: ControlGet, OutputVar, Hwnd,, Edit1, WinTitle. 控件的 HWND 通常使用于 PostMessage, SendMessage, 和 DllCall 命令中. 相关提示, 控件的 HWND 也可以使用 MouseGetPos 命令获取. 最后, 控件的 HWND 可以作为 ahk_id WinTitle 直接使用(即使 DetectHiddenWindows 为 OFF, 这样也适用于隐藏控件).

ErrorLevel

如果获取成功, ErrorLevel 被设置为 0.如果出现错误 -- 例如不存在的窗口或控件 -- ErrorLevel 被设置为 1 同时 OutputVar 被置空.

备注

和改变控件的命令不同, ControlGet 命令后没有一个自动的延迟; 即, SetControlDelay 命令不会影响它.

要获取当前鼠标所指向控件的名称, 请使用 MouseGetPos.要获取窗口中控件的列表, 请使用 WinGet ControlList.

窗口中的标题和文字是大小写敏感的.要检测隐藏窗口, 必须打开 DetectHiddenWindows.

相关

Control, GuiControlGet, ControlMove, ControlGetText, ControlSetText, ControlGetPos, ControlClick, ControlFocus, ControlSend, WinGet

示例

ControlGet, OutputVar, Line, 1, Edit1, Some Window Title

ControlGet, WhichTab, Tab, , SysTabControl321, Some Window Title
if ErrorLevel
    MsgBox There was a problem.
else    MsgBox Tab #%WhichTab% is active.


ControlGetFocus

检索目标窗口的哪个控件有输入焦点，若有的话。

ControlGetFocus, OutputVar [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 存储控件标识符的变量名称，控件标识符在它的父窗口里由它的类名跟序号组成，例如 Button12 。
WinTitle | 目标窗口的标题或副标题 (通过 SetTitleMatchMode 定义匹配行为)。如果此参数和后面的3个参数被省略，最近找到的窗口 将被使用。如果此参数是字母 A 并且后面的3个参数被省略，活动的窗口将被使用。要使用一个窗口类，指定 ahk_class 确切的类名 (通过Window Spy显示)。要使用一个 process 标识符 (PID)，指定 ahk_pid %包含PID的变量% 。要使用一个 窗口组 ，指定 ahk_group 组名。要使用一个窗口的 unique ID 编号 ，指定 ahk_id %包含ID的变量% 。通过指定 多个条件 缩小搜索范围。例如： My File.txt ahk_class Notepad
WinText | 如果出现，此参数必须是目标窗口的一个单独文本对象的子字串(像内置的Window Spy工具显示的一样)。如果 DetectHiddenText 是 ON 的状态，隐藏的文本对象将被探测。
ExcludeTitle | 标题包括此参数值的窗口将不被考虑。
ExcludeText | 文本包括此参数值的窗口将不被考虑。

ErrorLevel

如果带输入焦点的控件被成功地检索到，ErrorLevel 将设为 0 。否则设为 1 (例如目标窗口不存在或者它没有控件带输入焦点) 。

注意

被此命令检索到的控件是带键盘焦点的，也就是说，如果用户去键入任意内容，那控件将收到键击。

目标窗口必须被激活才获得一个焦点控件。如果窗口未激活，OutputVar 将为空。

如果 ControlGetFocus 以一个高频率(例如每 500 ms 一次或更快)重复地执行，它将可能扰乱用户的双击能力。一个应对方案是通过 DllCall 调用操作系统的 GetGUIThreadInfo() 。例如：

; 此脚本检索激活窗口焦点控件的 ahk_id (HWND) 。
; 此脚本需要 Windows 98 或者 NT 4.0 SP3+，或近期其他系统。
GuiThreadInfoSize = 48
VarSetCapacity(GuiThreadInfo, GuiThreadInfoSize)
NumPut(GuiThreadInfoSize, GuiThreadInfo, 0)
if not DllCall("GetGUIThreadInfo", uint, 0, str, GuiThreadInfo)
{
    MsgBox GetGUIThreadInfo() indicated a failure.
    return
}
FocusedHWND := NumGet(GuiThreadInfo, 12)  ; 从结构体检索 hwnd焦点区域。
MsgBox % "The focused control's ahk_id (HWND) is " . FocusedHWND
; 此 ID 能被所有控件命令使用。例如：
; ControlGetText, OutputVar,, ahk_id %FocusedHWND%

窗口标题和文本是区分大小写的。隐藏的窗口将不被探测，除非已打开 DetectHiddenWindows 。

相关命令

ControlFocus, ControlMove, ControlClick, ControlGetText, ControlSetText, ControlSend

示例

ControlGetFocus, OutputVar, 无标题 - 记事本
if ErrorLevel
    MsgBox, 目标窗口不存在或者它没有控件带输入焦点。
else
    MsgBox, 带焦点的控件 = %OutputVar%


ControlGetPos

取得一个 control (控件)的位置和大小。

ControlGetPos [, X, Y, Width, Height, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

X, Y

储存 Control 左上角的 X 和 Y 坐标(以像素表示)的 variables (变量)名称。这些坐标和目标窗口的左上角相关联，因而与被用在 ControlMove 中的坐标是一样的。

如果 X 或 Y 被省略，相应的坐标将不被储存。

Width/Height
储存 Control 的高和宽(以像素表示)的变量名称。如果省略，相应的值将不被储存。
Control

可以是控件的名称/文本或 ClassNN (控件的 classname (类名)和序号)，它们都可以通过 Window Spy 来确定。当使用名称/文本时，matching behavior (匹配模式)通过 SetTitleMatchMode 决定。如果此 parameter (参数)为空，目标窗口的顶端控件将被使用。

要对一个控件的 HWND (窗口 handle (句柄))进行操作，将 Control 参数留空并为 WinTitle 参数指定 ahk_id %ControlHwnd% (这样即使当 DetectHiddenWindows 是 Off 状态，它也能对隐藏的控件起作用)。一个控件的 HWND 往往由 ControlGet Hwnd 、MouseGetPos 或 DllCall 取得。

WinTitle | 目标窗口的标题或副标题(匹配模式由 SetTitleMatchMode 决定)。如果此参数和后面的3个参数被省略， Last Found Window (最近找到的窗口)将被使用。如果此参数是字母 A 并且后面的三个参数被省略，active (激活的)窗口将被使用。要使用一个窗口类，指定 ahk_class 确切的类名(通过 Window Spy 显示)。要使用一个 process identifier (PID) (进程标识符)，指定 ahk_pid %包含PID的变量% 。要使用一个 window group (窗口组)，指定 ahk_group GroupName 。要使用一个窗口的 unique ID number (唯一标识符编号)，指定 ahk_id %包含ID的变量% 。通过指定 multiple criteria (多个条件)缩小搜索范围。例如：My File.txt ahk_class Notepad
WinText | 如果用到，此参数必须是目标窗口的一个单独 text element (文本对象)的 substring (子字串)(像内置的 Window Spy 工具显示的一样)。如果 DetectHiddenText 是 ON 的状态，隐藏的文本对象将被探测。
ExcludeTitle | 标题含有此参数值的窗口将不被考虑。
ExcludeText | 文本含有此参数值的窗口将不被考虑。

注意

如果没有找到匹配的窗口或控件，输出变量将为空。

与改变一个控件的命令不同，ControlGetPos 没有一个自动的延迟( SetControlDelay 不会影响它)。

要找出鼠标当前停留的控件的名称，使用 MouseGetPos 。要获得一个窗口内所有控件的列表，使用 WinGet 。

窗口标题和文本是 case sensitive (区分大小写)的。隐藏的窗口将不被探测，除非 DetectHiddenWindows 已被打开。

相关命令

ControlMove, WinGetPos, Control, ControlGet, ControlGetText, ControlSetText, ControlClick, ControlFocus, ControlSend

示例

; 这个起作用的例子将不断地更新并显示当前鼠标光标下的控件的名称和位置：
Loop
{
    Sleep, 100
    MouseGetPos, , , WhichWindow, WhichControl
    ControlGetPos, x, y, w, h, %WhichControl%, ahk_id %WhichWindow%
    ToolTip, %WhichControl%`nX%X%`tY%Y%`nW%W%`t%H%
}


ControlGetText

从一个控件获取文本。

ControlGetText, OutputVar [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar

储存获得的文本的变量名称

Control

可以是控件的名称/文本或 ClassNN (控件的 classname(类名)和序号)，它们都可以通过 Window Spy 来确定。当使用名称/文本时，matching behavior(匹配模式)通过 SetTitleMatchMode 决定。如果此 parameter(参数)为空或省略，目标窗口的顶端控件将被使用。

要对一个控件的 HWND (窗口 handle(句柄) )进行操作，将 Control 参数留空并为 WinTitle 参数指定 ahk_id %ControlHwnd% (这样即使当 DetectHiddenWindows 是 Off 状态，它也能对隐藏的控件起作用)。一个控件的 HWND 往往由 ControlGet Hwnd 、MouseGetPos 或 DllCall 取得。

WinTitle
目标窗口的标题或副标题(匹配模式由 SetTitleMatchMode 决定)。如果此参数和后面的3个参数被省略，
Last Found Window(最近找到的窗口)将被使用。如果此参数是字母 A 并且后面的三个参数被省略，active(激活的)窗口将被使用。要使用一个窗口类，指定 ahk_class 确切的类名(通过 Window Spy 显示)。要使用一个
process identifier (PID)(进程标识符)，指定 ahk_pid %包含PID的变量% 。要使用一个
window group(窗口组)，指定 ahk_group GroupName 。要使用一个窗口的
unique ID number(唯一标识符编号)，指定 ahk_id %包含ID的变量% 。通过指定
multiple criteria(多个条件) 缩小搜索范围。 例如: My File.txt ahk_class Notepad
WinText
如果用到，此参数必须是目标窗口的一个单独 text element(文本对象)的 substring(子字串) (像内置的 Window Spy 工具显示的一样)。如果 DetectHiddenText 是 ON 的状态，隐藏的文本对象将被探测。
ExcludeTitle
标题含有此参数值的窗口将不被考虑。
ExcludeText
文本含有此参数值的窗口将不被考虑。

ErrorLevel

如果有问题，ErrorLevel 值将被设置为 1 ，否则为 0 。

注意

注意：要从一个 ListView(列表视图)、ListBox(列表框)或者 ComboBox(组合框)获取文本，使用 ControlGet List 来代替此命令。

如果获得的文本显得被缩短过(不完整)，试试在用 ControlGetText 命令之前先用 VarSetCapacity(OutputVar, 55) [用一个与缩短的文本相比而显得非常地长的大小来替换 55 ]。这是很有必要的，因为有些应用程序对于 WM_GETTEXTLENGTH 消息的反馈并不准确，这就导致了 AutoHotkey 的输出变量过小，以至于不能装下整个文本。

返回的文本数量受到一个变量的最大容量的限制(容量可以通过 #MaxMem 指令来改变)。因此，如果目标控件包含大量的文本(例如：用编辑器打开一个很大的文档)，这个命令可能会使用大量的 RAM(随机存取存储器)。不过，一个变量的存储容量能在指定其为空后就可以被释放。例如 OutputVar =

从大部分控件类型取得的文本使用 carriage return(回车)和换行(`r`n)而不是一个单独的换行(`n)来表示每一行的结束。

没有必要执行SetTitleMatchMode Slow ，因为 ControlGetText 总是用缓慢方法来获得文本(由于它工作在一个更大范围的控件类型)。

要获得一个窗口内所有控件的列表，使用 WinGet ControlList 。

窗口标题和文本是 case sensitive (区分大小写)的。隐藏的窗口将不被探测，除非 DetectHiddenWindows 已被打开。

相关命令

ControlSetText, WinGetText, Control, ControlGet, ControlMove, ControlFocus, ControlClick, ControlSend, #MaxMem

示例

ControlGetText, OutputVar, Edit1, 无标题 -


ControlMove

移动或者重新调整一个控件的大小。

ControlMove, Control, X, Y, Width, Height [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

Control

可以是控件的名称/文本或 ClassNN (控件的 classname(类名)和序号)，它们都可以通过 Window Spy 来确定。当使用名称/文本时，matching behavior (匹配模式)通过 SetTitleMatchMode 决定。如果此 parameter(参数)为空，目标窗口的顶端控件将被使用。

要对一个控件的 HWND (窗口 handle (句柄) )进行操作，将 Control 参数留空并为 WinTitle 参数指定 ahk_id %ControlHwnd% (这样即使当 DetectHiddenWindows 是 Off 状态，它也能对隐藏的控件起作用)。一个控件的 HWND 往往由 ControlGet Hwnd 、MouseGetPos& nbsp;或者 DllCall 取得。
X, Y | Control 左上角的 X 和 Y 方向的新坐标(用像素单位)，它们可以是 expressions(表 达式)。如果任何一个坐标参数为空，那么那种尺寸的 Control 的位置就不会改变。坐标是相对于 Control 的父窗口的左上角而言的； ControlGetPos 或者 Window Spy 能被用来确定它们。
Width, Height | Control 新的高度和宽度(用像素单位)，也可以是 expressions(表达 式)。如果任何一个参数为空或省略，那种尺寸的 Control 的大小将不被改变。
WinTitle
目标窗口的标题或副标题(匹配模式由 SetTitleMatchMode 决定)。如果此参数和后面的3个参数被省略，
Last Found Window(最近找到的窗口)将被使用。如果此参数是字母 A 并且后面的三个参数被省略，active(激活的)窗口将被使用。要使用一个窗口类，指定 ahk_class 确切的类名(通过 Window Spy 显示)。要使用一个
process identifier (PID)(进程标识符)，指定 ahk_pid %包含PID的变量% 。要使用一个
window group(窗口组)，指定 ahk_group GroupName 。要使用一个窗口的
unique ID number(唯一标识符编号)，指定 ahk_id %包含ID的变量% 。通过指定
multiple criteria(多个条件)缩小搜索范围。例如: My File.txt ahk_class Notepad
WinText | 如果用到，此参数必须是目标窗口的一个单独文本对象的 substring(子字串)(像内置的 Window Spy 工具显示的一样)。如果 DetectHiddenText 是 ON 的状态，隐藏的文本对象将被探测。
ExcludeTitle | 标题含有此参数值的窗口将不被考虑。
ExcludeText | 文本含有此参数值的窗口将不被考虑。

ErrorLevel

若有错误发生则 ErrorLevel 的值将被设为 1 ，否则为 0 。

注意

为了改善可靠性，每次该命令执行后自动会有一个延迟。这个延迟可以通过 SetControlDelay 来 改变。

窗口标题和文本是 case sensitive(区分大小写)的。隐藏的窗口将不被探测，除非 DetectHiddenWindows 已被打开。

相关命令

ControlGetPos, WinMove, SetControlDelay, Control, ControlGet, ControlGetText, ControlSetText, ControlClick, ControlFocus, ControlSend

示例

SetTimer, ControlMoveTimer
InputBox, OutputVar, My Input Box
return

ControlMoveTimer:
IfWinNotExist, My Input Box
 return
; 否则上面的窗口将为我们设为 the "last found" window(最近找到的窗口):
SetTimer, ControlMoveTimer, off
WinActivate
ControlMove, OK, 10, , 200 ; 将 OK 按钮移至左侧并增加其宽度。
return


ControlSetText

改变控件的文本.

ControlSetText [, Control, NewText, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

Control

可以是 ClassNN (控件的类名和实例号) 或控件的名称/文本, 他们都可以通过 Window Spy 来确定. 当使用名称/文本时, 匹配模式由 SetTitleMatchMode 决定. 如果此参数为空, 将使用目标窗口的顶层控件.

要对一个控件的 HWND (窗口句柄) 进行操作, 请将 Control 参数留空同时在 WinTitle 参数中指定 ahk_id %ControlHwnd% (即使 DetectHiddenWindows 是关闭的, 这样也适用于隐藏的控件) . 获取控件的 HWND 的典型方法是使用 ControlGet Hwnd, MouseGetPos, 或 DllCall 命令.
NewText | 给控件设置的新文本. 如果为空或省略, 控件将被置空
WinTitle | 目标窗口的标题或标题中的部分文字 (匹配模式由 SetTitleMatchMode 决定).如果此参数和后面三个参数都忽略, 默认目标是 上一次匹配窗口. 如果此参数是字母 A, 同时省略后面三个参数, 则以当前的活动窗口为目标. 要用窗口的类名进行匹配, 请指定 ahk_class ExactClassName (Window Spy 中可以显示类名).要用窗口的 进程标识符 (PID) 进行匹配, 请指定 ahk_pid %PID变量%.要使用 窗口组 进行匹配, 请指定 ahk_group GroupName.要使用窗口的 唯一 ID 进行匹配, 请指定 ahk_id %VarContainingID%.要减小检测范围, 请指定 多重条件.例如: My File.txt ahk_class Notepad
WinText | 如果使用这个参数, 则它应该是目标窗口中某个文本元素的子字符串 (在 Window Spy 中会显示窗口中的文本元素).隐藏文本只有当 DetectHiddenText 设置为 ON 的时候才能检测到.
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被排除.
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被排除.

ErrorLevel

如果出现错误, ErrorLevel 被设置为 1, 否则为 0.

备注

大部分控件类型使用回车和换行 (`r`n) 而不是一个单独的换行 (`n) 来表示每一行的结束. 要转换包含 `n 字符的文本块, 请参照这个例子: StringReplace, MyVar, MyVar, `n, `r`n, All

为了提高可靠性, 在每次使用此命令后都自动地有一个延迟.这个延迟可以通过 SetControlDelay 改变.

窗口中的标题和文字是大小写敏感的.要检测隐藏窗口, 必须打开 DetectHiddenWindows.

相关

SetControlDelay, ControlGetText, ControlGet, Control, ControlMove, ControlGetPos, ControlClick, ControlFocus, ControlSend

示例

ControlSetText, Edit1, New Text Here, Untitled -


PostMessage / SendMessage

发送一条消息给一个窗口或一个控件 (SendMessage 还会等待回应)。

PostMessage, Msg [, wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]
SendMessage, Msg [, wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

Msg | 需要发送的消息码，可以是一个 表达式。参看 消息列表 以确定数值。
wParam | 消息的第一个参数，可以是一个 表达式。如果为空或省略，将会发送 0。
lParam | 消息的第二个参数，可以是一个 表达式。如果为空或省略，将会发送 0。
Control

如果此参数为空或省略，消息将被直接发送给目标窗口，而不是它的某个控件。否则，这个参数可以是 ClassNN (控件的类名和实例号) 或者控件的 名字/文本，两者都可通过 Window Spy 来确定。使用 名字/文本 时，匹配模式由 SetTitleMatchMode 决定。

若要通过控件的 HWND (窗口句柄) 来操作，则将 Control 参数留空并为 WinTitle 参数指定 ahk_id %ControlHwnd% (也适用于隐藏控件，即使 DetectHiddenWindows 为 Off)。一个控件的 HWND 通常可以通过 ControlGet Hwnd, MouseGetPos, 或 DllCall 来获取。
WinTitle | 目标窗口的部分或整个标题 (匹配模式由 SetTitleMatchMode 决定)。如果省略这个和另外3个参数，将使用 上一次匹配窗口 。如果这个参数为字母 A 且省略其他3个参数，将使用当前激活的窗口。要使用窗口类，指定 ahk_class 精确的类名 (Window Spy可以显示类名)。要使用 进程标识符 (PID)，指定 ahk_pid %PID变量%。要使用 窗口组，指定 ahk_group 组名。要使用窗口的 唯一ID，指定 ahk_id %ID变量% (也接受 控件的 HWND)。要减小检测范围，使用指定 多重条件。例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题含有此参数值的窗口将不被考虑。
ExcludeText | 文本含有此参数值的窗口将不被考虑。

ErrorLevel

PostMessage: 如果出现问题，例如目标窗口或控件不存在， ErrorLevel 会被设为 1。否则为 0。

SendMessage: 如果出现问题，ErrorLevel 会被设为单词 FAIL。否则，会被设为此消息的数值结果，有时可能是一个根据消息的类型和消息的目标窗口的类型而决定的一个“回覆 (reply) ”。这个结果是一个 0 与 4294967295 之间的整数。如果结果应该是有符号的，下列例子可以将负数结果展现出来：MsgReply := ErrorLevel > 0x7FFFFFFF ? -(~ErrorLevel) - 1 : ErrorLevel

注意

应该小心使用这些命令。因为发送一条消息到错误的窗口（或发送无效的消息）可能导致不可预料的行为，甚至使目标应用程序崩溃。这是因为多数应用程序在设计时并不会考虑对某些从外部来源发来的消息做处理。

PostMessage 将消息放置到与目标窗口相关的消息队列中。它不会等待回应或答覆。相比之下，SendMessage 会用最多5秒钟来等待目标窗口处理此消息。如果消息在这段时间内未处理完，此命令结束并设置 ErrorLevel 为单词 FAIL 。

参数 Msg, wParam, 与 lParam 都应该是 -2147483648 与 4294967295 (0xFFFFFFFF) 之间的整数。AutoHotkey 中所有的整型数值，都可以附加前缀 0x 来代表一个十六进制值。例如， 0xFF 等于 255 。

若要通过 wParam 或 lParam 发送一个字符串，可以指定一个变量的地址。以下例子使用 取地址运算符 (&) 来完成此事：

SendMessage, 0xC, 0, &MyVar, ClassNN, WinTitle  ; 0XC 是 WM_SETTEXT

在 v1.0.43.06 及以后的版本中，消息的接收者放置在 MyVar 中的字符串可以被正确辨认，无需附加步骤。不过这只有在参数的第一个字符是一个 与符号(&) 时才可以。例如， 5+&MyVar 不行但是 &MyVar 或 &MyVar+5 就可以。

一个 带引号/原意(quoted/literal) 的字符串也可以被发送。参照以下的可用范例（此种情况下不应该使用 & 操作符）：

Run Notepad
WinWait 无标题 - 记事本
SendMessage, 0xC, 0, "新的记事本标题"  ; 0XC 是 WM_SETTEXT

要发送一条消息给系统中所有的窗口（包括隐藏或无效的），指定 WinTitle 为 ahk_id 0xFFFF （0xFFFF 是 HWND_BROADCAST）。此技巧应该只在专门用于广播的消息上使用。例如以下的范例：

SendMessage, 0x1A,,,, ahk_id 0xFFFF  ; 0x1A 是 WM_SETTINGCHANGE

若想拥有能够接收消息的脚本，可以使用 OnMessage() 。

参看 消息指南 以获得使用这些命令的说明。

窗口标题与文本都是区分大小写的。隐藏窗口不会被检测，除非开启了 DetectHiddenWindows 。

相关命令

消息列表, 消息指南, OnMessage(), 自动化 Winamp, DllCall, ControlSend, WinMenuSelectItem

示例

#o::  ; Win+O 热键关闭显示器。
Sleep 1000  ; 给用户释放按键的机会（万一它们被释放会再次唤醒显示器）。
; 关闭显示器:
SendMessage, 0x112, 0xF170, 2,, Program Manager  ; 0x112 是 WM_SYSCOMMAND, 0xF170 是 SC_MONITORPOWER。
; 上面的备注: 使用 -1 代替 2 可以打开显示器。
; 使用 1 代替 2 可以开启显示器的节能模式。
return

; 启动用户选择的屏幕保护程序：
SendMessage, 0x112, 0xF140, 0,, Program Manager  ; 0x112 是 WM_SYSCOMMAND, 0xF140 是 SC_SCREENSAVE。

; 向上滚动一行 (用于拥有垂直滚动条的控件)：
ControlGetFocus, control, A
SendMessage, 0x115, 0, 0, %control%, A

; 向下滚动一行：
ControlGetFocus, control, A
SendMessage, 0x115, 1, 0, %control%, A

; 切换活动窗口的 键盘布局/语言 到英语：
PostMessage, 0x50, 0, 0x4090409,, A  ; 0x50 是 WM_INPUTLANGCHANGEREQUEST。

; 本示例询问 Winamp 当前活动的音轨号是哪一个：
SetTitleMatchMode, 2
SendMessage, 1024, 0, 120, - Winamp
if ErrorLevel <> FAIL
{
    ErrorLevel++  ; Winamp 的计数器从 "0" 开始，所以用 1 调整。
    MsgBox, 音轨 #%ErrorLevel% 是活动的或正在播放。.
}
; 参看 自动化 Winamp 获得更多信息。

; 要查找一个 AHK脚本 的进程ID (另一个办法是 "WinGet PID"):
SetTitleMatchMode, 2
DetectHiddenWindows, on
SendMessage, 0x44, 0x405, 0, , SomeOtherScript.ahk - AutoHotkey v
MsgBox %ErrorLevel% 是进程 id。


SetControlDelay

设置两次控件操作类命令之间的延时。

SetControlDelay, Delay

参数

Delay 延时时间，单位毫秒。可以是一个 expression/表达式 。使用 -1 表示无延时，使用 0 表示最小延时。如果没有设置，默认延时 20 。

注意

脚本在执行了每个控件操作类命令之后，会有一个自动的延时（休眠）。这些命令包括：Control ，ControlMove ，ControlClick, ControlFocus 以及 ControlSetText （ControlSend 例外，它的延时使用 SetKeyDelay 命令进行设置）。 这样做的目的是提高脚本的可靠性，因为一个控件一般情况下在两次操作之间都需要一个短暂的“休息”来进行刷新，好对下一个可能的命令进行响应。

虽然允许使用 -1（完全无延时），但是推荐最少只设置到 0 ，这样可以增加脚本正确执行的几率。

设置延时为 0 的话相当于执行了命令 Sleep(0) ，它会将当前脚本的剩余时间片分配给有需要的进程。如果没有进程需要，延时 0 就相当于完全没有延时。

cpu速度比较慢，或者cpu正忙，或者开启了窗口动画的时候，也许需要设置比较大的延时。

内置变量 A_ControlDelay 保存了当前的设置。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将该命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

Control, ControlMove, ControlClick, ControlFocus, ControlSetText, SetWinDelay, SetKeyDelay, SetMouseDelay, SetBatchLines

示例

SetControlDelay, 0


WinMenuSelectItem

调用匹配指定条件的窗口的菜单项。

WinMenuSelectItem, WinTitle, WinText, Menu [, SubMenu1, SubMenu2, SubMenu3, SubMenu4, SubMenu5, SubMenu6, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个窗口参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个窗口参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
Menu | 顶级菜单的名称，例如 File ，Edit ，View 。也可以使用 1& 表示第一个菜单项，2& 表示第二个菜单项，等等。
SubMenu1 | 需要选择的菜单的名称或位置（参见 Menu）。
SubMenu2 | 如果 SubMenu1 本身还有子菜单，那么这个参数就是子菜单项的名称或位置。
SubMenu3 | 同上。
SubMenu4 | 同上。
SubMenu5 | 同上。
SubMenu6 | 同上。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

ErrorLevel

如果出现错误，ErrorLevel/错误等级 设置为 1 ，否则为 0 。

注意

使用这个命令的时候，目标窗口不需要处于激活状态。但是，某些窗口也许要求处于 非最小化 状态。

这个命令对于使用非标准菜单栏的程序 无效 。例如 Microsoft Outlook 和 Outlook Express ，它们使用工具栏来伪装成菜单栏。在这种情况下，推荐使用 ControlSend 或 PostMessage 命令。

菜单的名称是不区分大小写的（例如，File->Save 等同于 file->save ），同时也不需要使用“&”来表示菜单名称中的下划线字母（例如，&File 等同于 File ）。

在菜单名称参数中同样可以指定菜单位置，这样做是为了支持那些没有文本的菜单（例如仅包含图片而没有文字的菜单项）。1& 表示第一个菜单（例如 File），2& 表示第二个菜单（例如 Edit），以此类推。菜单中的分割线也算一个菜单项，在参数中使用菜单位置的时候要注意。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

ControlSend, PostMessage

示例

; 选择记事本中的 “打开”菜单：
WinMenuSelectItem, Untitled - Notepad, , File, Open

; 和上面例子一样，不过使用的是菜单位置：
WinMenuSelectItem, Untitled - Notepad, , 1&, 2&


GroupActivate

激活由 GroupAdd 定义的窗口组中的下一个窗口.

GroupActivate, GroupName [, R]

参数

GroupName | 需激活的组名, 和原来由 GroupAdd 定义的一样.
R | 此参数决定是激活目标组中最老的窗口还是最新的, 每当目标组的成员当前都没有处于活动状态时. 如果省略, 总是激活最老的窗口. 如果它是字母 R, 则激活最新的窗口 (最近激活的那个), 不过仅当命令中的组没有活动的成员时. 当你临时切换工作到一个不相关的任务时 "R" 很有用. 当你使用 GroupActivate, GroupDeactivate 或 GroupClose 返回到目标组时, 您最近工作的窗口被激活而不是最老的窗口.

备注

此命令使得匹配窗口组中任意一条窗口规格的首个窗口被激活. 再次使用此命令将激活系列窗口中的下一个, 依此类推. 通常给它分配一个热键以便使用热键自动遍历窗口.

如果一个窗口紧接着另一个窗口的激活事件之后被激活, 在某些系统中任务栏按钮可能会闪烁 (取决于操作系统和设置). 要避免这种现象, 请使用 #WinActivateForce.

参见 GroupAdd 了解关于窗口组的更多细节.

返回值 [AHK_L 54+]

如果没有找到需激活的窗口 ErrorLevel 被设置为 1 否则为 0.

相关

GroupAdd, GroupDeactivate, GroupClose, #WinActivateForce

示例

GroupActivate, MyGroup, R


GroupAdd

增加一种窗口规格到窗口组, 必要时创建组.

GroupAdd, GroupName [, WinTitle, WinText, Label, ExcludeTitle, ExcludeText]

参数

GroupName | 用来保存这种窗口规格的组名. 若组不存在, 则它将被创建. 组名是大小写不敏感的.
WinTitle

目标窗口(可能多个)的标题或标题中的部分文字. 此参数可以为空. 注意: 尽管 SetTitleMatchMode 和 DetectHiddenWindows 命令不会直接影响此命令的行为, 他们确实会影响其他组命令的行为诸如 GroupActivate 和 GroupClose. 他们还会影响任何其他命令的 WinTitle 参数中 ahk_group 的使用.

要用窗口的类名进行匹配, 请指定 ahk_class ExactClassName (Window Spy 中可以显示类名).要用窗口的 进程标识符 (PID) 进行匹配, 请指定 ahk_pid %PID变量%.

要使用窗口的 唯一 ID 进行匹配, 请指定 ahk_id %VarContainingID%.要使用窗口组进行匹配, 请指定 ahk_group GroupName (例如组可以包含其他的组).

要减小检测范围, 请指定 多重条件.例如: My File.txt ahk_class Notepad
WinText | 如果使用这个参数, 则它应该是目标窗口中某个文本元素的子字符串 (在 Window Spy 中会显示窗口中的文本元素).在使用 GroupActivate, GroupDeactivate, 和 GroupClose 命令时, 隐藏文本只有当 DetectHiddenText 设置为 ON 的时候才能检测到.
Label | 当使用 GroupActivate 命令时, 如果没有找到匹配这种规格的窗口时运行的子程序的标签. 跳到此标签就像使用 Gosub 命令一样. 如果没有, 则省略或留空.
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被排除.
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被排除.

备注

每使用此命令则添加一个新规则到一个组中. 换句话说, 一个组由窗口规格的集合所组成而不是固定的窗口列表. 后面当类似 GroupActivate 的命令使用组时, 会使用这些规则中的每一个检查桌面上的每个窗口. 如果一个窗口匹配组中规则的其中一个, 它被看作一个匹配.

窗口组的典型用法是将相关窗口收集绑定在一起, 这对于包含许多相关窗口的任务或者有许多子窗口的程序是有用的. 例如, 如果您频繁的工作于一个图形程序或文本编辑器的多个实例时, 您可以在一个热键中使用 GroupActivate 命令来切换此程序的每一个实例, 每次一个, 不需要通过 alt-tab 热键或任务栏按钮来找到他们.

由于每组中条目仅需要被添加一次, 此命令通常使用在自动执行段中 (脚本的顶部). 试图添加重复的条目到组中会被忽略.

要在一个组中包含 所有 窗口 (除了特殊的 Program Manager 窗口), 使用这个示例:

GroupAdd, AllWindows

通过在 WinTitle 参数中指定 ahk_group MyGroupName, 所有的窗口命令都可以操作窗口组. WinMinimize, WinMaximize, WinRestore, WinHide, WinShow, WinClose, 和 WinKill 将对一个组中的 所有 窗口起作用. 要仅对顶层的窗口起作用, 参照这个例子:

WinHide % "ahk_id " . WinExist("ahk_group MyGroup")

相反的, 其他的窗口命令例如 WinActivate 和 IfWinExist 将仅对组中的顶层窗口起作用.

相关

GroupActivate, GroupDeactivate, GroupClose

示例

; In the autoexecute section at the top of the script:
GroupAdd, MSIE, ahk_class IEFrame ; Add only Internet Explorer windows to this group.
return ; End of autoexecute section.

; Assign a hotkey to activate this group, which traverses
; through all open MSIE windows, one at a time (i.e. each
; press of the hotkey).
Numpad1::GroupActivate, MSIE, r

; Here's a more complex group for MS Outlook 2002.
; In the autoexecute section at the top of the script:
SetTitleMatchMode, 2
GroupAdd, mail, Message - Microsoft Word ; This is for mails currently being composed
GroupAdd, mail, - Message ( ; This is for already opened items
; Need extra text to avoid activation of a phantom window:
GroupAdd, mail, Advanced Find, Sear&ch for the word(s)
GroupAdd, mail, , Recurrence:
GroupAdd, mail, Reminder
GroupAdd, mail, - Microsoft Outlook
return  ; End of autoexecute section.

Numpad5::GroupActivate, mail ; Assign a hotkey to visit each Outlook window, one at a time.


GroupClose

关闭刚刚由 GroupActivate 或 GroupDeactivate 命令激活的活动窗口. 接着激活系列中的下一个窗口. 它也可以关闭一组中的所有窗口.

GroupClose, GroupName [, A|R]

参数

GroupName | 组名, 如同原来由 GroupAdd 命令定义的.
A|R | 如果此参数是字母 A, 目标组的所有成员将被关闭. 与使用 WinClose ahk_group GroupName 的效果一样. 否则: 如果此命令关闭了活动窗口, 接着它将激活系列中的下一个窗口. 此参数决定是激活最老的窗口还是最新的. 如果省略, 总是激活最老的窗口.如果它是字母 R, 则激活最新的窗口 (最近激活的那个), 不过仅当给出的命令中的组的成员当前都没有处于活动状态.当你临时切换工作到一个不相关的任务时, "R" 是有用的.当你使用 GroupActivate, GroupDeactivate, 或 GroupClose 命令返回组时, 你最近工作的窗口被激活, 而不是最老的窗口.

备注

如果 A|R 参数不是字母 "A", 此命令的行为由前面对 GroupName 进行的操作命令是 GroupActivate 还是 GroupDeactivate 决定的. 如果它是 GroupDeactivate, 仅当活动窗口 不是 目标组的成员时此命令将关闭活动窗口 (否则它什么都不做). 如果它是 GroupActivate 或者没有, 仅当活动窗口 是 目标组的成员时此命令将关闭活动窗口 (否则它什么都不做). 这种特性允许分配一个热键到 GroupClose 作为 GroupName 的 GroupActivate 或 GroupDeactivate 热键的搭配.

想了解关于窗口组的更多详情, 请参看 GroupAdd 命令.

相关

GroupAdd, GroupActivate, GroupDeactivate

示例

GroupClose, MyGroup, R


GroupDeactivate

类似于 GroupActivate, 只是它激活 不 在目标组中的下一个窗口.

GroupDeactivate, GroupName [, R]

参数

GroupName | 目标组的名称, 如同原来由 GroupAdd 命令定义的.
R | 此参数决定是激活最老的非成员窗口还是最新的, 只要目标组的其中一个成员当前处于活动状态. 如果省略, 总是激活最老的非成员窗口.如果它是字母 R, 则激活最新的非成员窗口 (最近激活的那个), 不过仅当命令中的组有一个成员活动时. 当你临时切换工作到一个不相关的任务时, "R" 是有用的.当你使用 GroupActivate, GroupDeactivate, 或 GroupClose 命令返回组时, 你最近工作的窗口被激活, 而不是最老的窗口.

备注

GroupDeactivate 使得 不 匹配组中任意一条窗口规格的首个窗口被激活. 再次使用 GroupDeactivate 将激活系列窗口中的下一个, 以此类推. 通常给 GroupDeactivate 分配一个热键以便通过使用热键让窗口遍历自动进行.

当你将几乎总是在运行的最爱窗口收集在一起时, 此命令很有用. 通过将这些窗口添加到一个组中, 你可以使用 GroupDeactivate 命令访问不是自己最爱的每一个窗口并决定是否关闭它. 此命令可以让你快速清理桌面, 比手动快的多.

想了解关于窗口组的更多详情, 请参看 GroupAdd 命令.

相关

GroupAdd, GroupActivate, GroupClose

示例

GroupDeactivate, MyFavoriteWindows  ; Visit non-favorite windows to clean up desktop.


#Warn

#Warn [v1.0.95.00+]

启用或禁用为选择的在加载时或运行时提示开发者错误的警告, 例如书写错误或缺少全局声明.

#Warn [, WarningType, WarningMode]

打算把此指令作为开发者工具, 通过让这些错误简单的显露出来以便加快脚本开发.

这个特征概念上与 Visual Basic 的 "Option Explicit" 设置和 Perl 的 "Strict" 编译指示有关, 尽管它只提供额外的警告, 而不需要对脚本进行任何预先的改变 (例如对所有变量进行显式声明).

参数

WarningType

下面列表中值的其中一个.如果省略, 默认为 All.

All:对指定的 WarningMode 适用的所有支持的警告类型.

UseUnsetLocal 或 UseUnsetGlobal:在明确对变量进行赋值前使用变量 (例如读取它的值) 时警告.此选项根据局部或全局变量划分为独立的警告类型, 因为使用未赋值的局部变量可能能是开发者错误, 许多 AutoHotkey 脚本在编写时会特意检查未赋值的全局变量, 所以可能需要为局部变量启用此类型的警告而禁用全局变量的.这些是运行时错误, 它们可能在脚本运行的任意时刻产生.

UseEnv:在自动使用环境变量代替空的脚本变量时警告.当脚本中使用的某个变量名意外地与一个环境变量名相同时会发生这种情况, 但如果脚本使用了 #NoEnv (推荐使用) 则不会发生.这是运行时警告; 它可能在脚本运行的任意时刻产生.

LocalSameAsGlobal:当一个局部变量和脚本中任意位置的全局变量名称相同时警告.请注意这种警告仅适用于隐式引入的局部变量 - 而不适用于明确声明的变量例如 local x 或 static y, 或函数参数).这是加载时警告; 它仅可能在脚本首次加载时产生.
WarningMode

下面列表中值的其中一个.如果省略, 默认为 MsgBox.

MsgBox:将显示描述警告的消息框 (请注意当消息框解除后, 脚本将照常继续).

OutputDebug:警告的描述将被发送到调试器 (如果有的话) 显示出来.想了解更多详情, 参见 OutputDebug.

Off:禁用指定的警告类型.

备注

默认情况下, 所有的警告都是关闭的.

无法在运行时启用或禁用警告; 这个设置是在脚本加载时确定的.因此它在脚本中的位置是不重要的 (并且与其他 # 指令一样, #Warn 不能根据条件执行).

然而, 多个 #Warn 指令的顺序是有意义的: 最近一次设置指定警告的指令决定了这种警告的模式.所以, 例如下面的两个语句具有启用除了 UseEnv 外的所有警告的组合效果:

#Warn All
#Warn UseEnv, Off

EnvSet EnvVar, 1
x := EnvVar       ; 由于没有使用 #NoEnv 这句是正确的.
x := NotAnEnvVar  ; 这句会产生警告.

相关

局部和全局变量

示例

#Warn All, Off                    ; 禁用所有警告.这是默认设置.
#Warn                             ; 启用各种警告并把它们显示到消息框中.
#Warn UseUnsetLocal, OutputDebug  ; 在赋值前使用局部变量时发送警告到 OutputDebug.


#WinActivateForce

跳过温和的方法激活窗口而直接使用强硬的方法。

#WinActivateForce

在脚本的任意位置指定此指令将促使激活窗口的命令 -- 例如 WinActivate, WinActivateBottom, 和 GroupActivate -- 跳过 "温和的" 方法激活窗口而直接使用更强硬的方法。

虽然这个指令通常不会改善如何快速地或可靠地激活窗口，但它可以防止任务栏按钮在不同窗口接连快速地激活时的闪烁。

Windows 95 和 NT 将可能永不需要此设置，因为它们在准许窗口被激活方面更自由。

相关命令

WinActivate, WinActivateBottom, GroupActivate

示例

#WinActivateForce


DetectHiddenText

决定窗口中隐藏的文本是否在探测窗口时“可见”。这会影响像 IfWinExist 和 WinActivate 这样的命令。

DetectHiddenText, On|Off

参数

On|Off

On: 非 AutoIt v2 脚本中的默认值 (例如 .ahk, .ini)。将探测隐藏的文本。

Off: AutoIt v2 脚本中的默认值。不探测隐藏的文本。

注意

"Hidden text"是一个术语，和窗口中那些不可见的控件有关。它们的文本因而被认为是“隐藏的”。当你要探测多标签对话框或多窗格窗口不同的窗格之间的差异的时候，将 DetectHiddenText 设为 Off 是很有用的。用 Window Spy 来测定当前活动窗口中哪些文本是隐藏的。所有接受 WinText 参数的命令都受到该设置影响，包括 WinActivate, IfWinActive, WinWait 和 IfWinExist。

内置变量 A_DetectHiddenText 包含当前的设置 (On 或 Off)。

每一个新运行的 线程 (例如一个 热键, 自定义菜单项, 或者 定时的 子程序) 都会以本命令的默认设置开始。这一默认值可以通过将本命令放置于自动运行区段(位于脚本的顶部)来改变。

相关命令

DetectHiddenWindows

示例

DetectHiddenText, off


DetectHiddenWindows

决定不可见的窗口是否被脚本“看见”。

DetectHiddenWindows, On|Off

参数

On|Off

On: 探测隐藏的窗口。

Off: 这参数是默认的。不探测隐藏的窗口，除了通过 WinShow 命令。

注意

在一些情况下开启 DetectHiddenWindows 能使脚本运行更艰难，因为有些隐藏的系统窗口可能偶然地匹配你正在试着去一同工作的另一个窗口的标题或文本。因此大多数脚本应该让这个设置关闭。不过假如你希望直接地和隐藏窗口一同工作而不是先使用 WinShow 命令来反隐藏它们，那么开启它也许会很有用。

所有窗口命令除了 WinShow 都被此设置影响，包括 WinActivate 、IfWinActive 、WinWait 、IfWinExist 。相比之下，WinShow 将总是能反隐藏一个隐藏的窗口，即使隐藏的窗口没有被探测到。

当通过 ahk_id 方法 或像 last-found-window(最后找到的窗口)来访问一个子窗口或控件时，没有必要开启 DetectHiddenWindows 。当通过 Gui +LastFound 来访问 GUI 窗口时它也是没必要的。

内置变量 A_DetectHiddenWindows 包含当前的设置(On 或者 Off)。

对于此命令来说，每个最近启动的 thread (例如一个 hotkey 、custom menu item 或 timed 子程序) 以新的默认设置开始。这个默认设置可以通过在自动执行部分(脚本的顶部)使用此命令来改变。

相关命令

DetectHiddenText

示例

DetectHiddenWindows, on


IfWinActive / IfWinNotActive

检查指定的窗口是否存在且当前是否活动 (在最前面).

IfWinActive [, WinTitle, WinText,  ExcludeTitle, ExcludeText]
IfWinNotActive [, WinTitle, WinText, ExcludeTitle, ExcludeText]
UniqueID := WinActive("WinTitle", "WinText", "ExcludeTitle", "ExcludeText")

参数

WinTitle | 目标窗口的标题或部分标题 (匹配行为由 SetTitleMatchMode 决定). 如果省略此参数和其他 3 个参数, 那么将使用 上次找到的窗口. 要使用窗口类, 请在此参数中指定 ahk_class ExactClassName (在 Window Spy 中所显示的). 要使用 进程标识符 (PID), 请指定 ahk_pid %VarContainingPID%. 要使用 窗口组, 请指定 ahk_group GroupName. 要使用窗口的 唯一 ID 号, 请指定 ahk_id %VarContainingID%. 通过指定 多个条件 可以缩小搜索范围. 例如: My File.txt ahk_class Notepad
WinText | 如果使用此参数, 那么它必须是目标窗口中单个文本元素的子字符串 (和内置的 Window Spy 工具显示的一样). 当 DetectHiddenText 的设置为 ON 时, 那么会检测到隐藏文本元素.
ExcludeTitle | 标题中含有此参数值的窗口将被排除. 注意: 由于向后兼容 .aut 脚本, 所以如果此参数准确匹配某个命令名, 那么它将被解释为命令. 要变通解决此问题, 请使用 WinActive() 函数 代替此命令.
ExcludeText | 文本中含有此参数值的窗口将被排除.

备注

如果省略所有参数, 那么将使用 上次找到的窗口.

如果这些命令的其中一个确定了某个活动窗口为符合的匹配, 那么 上次找到的窗口 将更新为这个活动窗口. 换句话说, 如果 IfWinActive 匹配结果为 "true" 或 IfWinNotActive 匹配结果为 "false", 那么将更新 上次找到的窗口.

WinActive() 函数返回匹配指定条件的活动窗口的 唯一 ID (HWND). 如果不匹配, 则函数返回 0. 由于所有的非零数字被视为 "true", 所以每当 WinTitle 为活动时, if WinActive("WinTitle") 语句为 true.

SetWinDelay 不适用于 IfWinExist/IfWinActive.

窗口标题和文本是区分大小写的. 只有在打开 DetectHiddenWindows 设置时, 才会检测到隐藏窗口.

相关

IfWinExist, SetTitleMatchMode, DetectHiddenWindows, 上次找到的窗口, WinActivate, WinWaitActive, WinWait, WinWaitClose, #IfWinActive/Exist

示例

IfWinActive, Untitled - Notepad
{
    WinMaximize  ; 最大化前面 IfWinActive 找到的记事本窗口.
    Send, Some text.{Enter}
    return
}

if WinActive("ahk_class Notepad") or WinActive("ahk_class" . ClassName)  ; "ahk_class" 后不需要空格.
    WinClose  ; 这里使用 上次找到的窗口.


IfWinExist / IfWinNotExist

检查指定的窗口是否存在.

IfWinExist [, WinTitle, WinText,  ExcludeTitle, ExcludeText]
IfWinNotExist [, WinTitle, WinText, ExcludeTitle, ExcludeText]
UniqueID := WinExist("WinTitle", "WinText", "ExcludeTitle", "ExcludeText")

参数

WinTitle | 目标窗口的标题或部分标题 (匹配行为由 SetTitleMatchMode 决定). 如果省略此参数和其他 3 个参数, 那么将使用 上次找到的窗口 (即检查指定的窗口看它是否仍然存在). 如果此参数为字母 A 且省略其他 3 个参数, 那么将使用活动窗口. 要使用窗口类, 请在此参数中指定 ahk_class ExactClassName (在 Window Spy 中所显示的). 要使用 进程标识符 (PID), 请指定 ahk_pid %VarContainingPID%. 要使用 窗口组, 请指定 ahk_group GroupName. 要使用窗口的 唯一 ID 号, 请指定 ahk_id %VarContainingID%. 通过指定 多个条件 可以缩小搜索范围. 例如: My File.txt ahk_class Notepad
WinText | 如果使用此参数, 那么它必须是目标窗口中单个文本元素的子字符串 (和内置的 Window Spy 工具显示的一样). 当 DetectHiddenText 的设置为 ON 时, 那么会检测到隐藏文本元素.
ExcludeTitle | 标题中含有此参数值的窗口将被排除. 注意: 由于向后兼容 .aut 脚本, 所以如果此参数准确匹配某个命令名, 那么它将被解释为命令. 要变通解决此问题, 请使用 WinExist() 函数 代替此命令.
ExcludeText | 文本中含有此参数值的窗口将被排除.

备注

如果省略所有参数, 那么将检查 上次找到的窗口 看它是否仍然存在 (如果是 IfWinNotExist 则检查其是否不存在).

如果这些命令的其中一个确定了某个符合的窗口存在, 那么 上次找到的窗口 将更新为此窗口. 换句话说, 如果 IfWinExist 匹配结果为 true 或 IfWinNotExist 匹配结果为 false, 那么将更新上次找到的窗口.

WinExist() 返回首个匹配窗口的 唯一 ID (HWND) (没有找到匹配时则为 0). 由于所有的非零数字都被视为 "true", 所以每当 WinTitle 存在时, if WinExist("WinTitle") 语句为 true.

要获取控件的 HWND (用于 Post/SendMessage 或 DllCall 中), 请使用 ControlGet Hwnd 或 MouseGetPos.

SetWinDelay 不适用于 IfWinExist/IfWinActive.

窗口标题和文本是区分大小写的. 只有在打开 DetectHiddenWindows 设置时, 才会检测到隐藏窗口.

相关

IfWinActive, SetTitleMatchMode, DetectHiddenWindows, 上次找到的窗口, Process, WinActivate, WinWaitActive, WinWait, WinWaitClose, #IfWinActive/Exist

示例

IfWinExist, Untitled - Notepad
{
    WinActivate  ; 自动使用前面找到的窗口.
    WinMaximize  ; 同上
    Send, Some text.{Enter}
    return
}

IfWinNotExist, Calculator
    return
else
{
    WinActivate  ; 前面的 "IfWinNotExist" 也为我们设置了 "上次找到的" 窗口.
    WinMove, 40, 40  ; 把它移动到新的位置.
    return
}

if WinExist("ahk_class Notepad") or WinExist("ahk_class" . ClassName)
    WinActivate  ; 这里使用 上次找到的窗口.

MsgBox % "The active window's ID is " . WinExist("A")


SetTitleMatchMode

设置在例如 WinWait 这样的命令中，参数 WinTitle 的匹配模式。

SetTitleMatchMode, MatchMode
SetTitleMatchMode, Fast|Slow

参数

MatchMode | 使用下面所示的一个数字或单词 RegEx ： 1 ：匹配由指定的 WinTitle 开始的窗口标题。 2 ：匹配包含指定的 WinTitle 的窗口标题。 3 ：精确匹配。窗口的标题必须完全和 WinTitle 一样。 RegEx（v1.0.45+）：切换参数 WinTitle ，WinText，ExcludeTitle 以及 ExcludeText 为 正则表达式 匹配模式。当使用正则表达式的时候，不用在正则表达式的外面加引号。例如：WinActivate Untitled.*Notepad 。RegEx 同样适用于 ahk_group 和 ahk_class 。例如 ahk_class IEFrame 匹配一个类名中任意位置包含 IEFrame 的窗口（这是因为默认情况下，正则表达式会在目标字符串中的 任意位置 搜索匹配值）。注意：对 WinText 参数来说，正则表达式会独立的匹配每个文本元素（例如每个控件的文本），因此，正则表达式的匹配范围不能横跨多个文本元素。 上面的模式设置同样影响 ExcludeTitle 参数。例如，模式 3 要求被排除的窗口的标题精确匹配 ExcludeTitle 中指定的名称。
Fast|Slow | Fast：快速模式，这个是默认值。使用 Fast 的性能比使用 Slow 要好得多，但是对于窗口操作类命令中的 WinText 参数，某些类型的窗口中的文本元素可能不能被检测到。 Slow：慢速模式，速度会比较慢，但是 WinText 可以匹配到窗口中所有可能的文本元素。Window Spy 中显示在“slow Hidden Text”部分的文本都要求使用慢速模式来匹配。

注意

这个命令影响所有的窗口操作类命令，例如 IfWinExist 和 WinActivate 。

如果未指定，默认使用 1 和 fast 。

一般来说，只有在用窗口标题或者快速模式的 WinText 参数搜索不到窗口的时候才使用慢速模式。因为当任一个窗口正忙或者无响应的时候慢速模式会变得相当的慢。

AutoHotkey 自带的 Window Spy 将需要使用慢速模式检测的文本元素放在一个独立的区域中显示，这样就可以很容易的决定是否使用慢速模式。

如果你要同时修改两个参数，可以使用这个命令两次：
SetTitleMatchMode, 2
SetTitleMatchMode, slow

内置变量 A_TitleMatchMode 和 A_TitleMatchModeSpeed 存储了当前的设置。

与当前的 TitleMatchMode 设置无关，WinTitle ，WinText ，ExcludeTitle 以及 ExcludeText 都是大小写敏感的。但是有一个例外，就是正则表达式中 大小写敏感设置 ，例如：i)untitled - notepad

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

SetWinDelay, IfWinExist, WinActivate, RegExMatch()

示例

SetTitleMatchMode 2
; 或者：
SetTitleMatchMode RegEx

SetTitleMatchMode Slow  ; Slow/Fast 可以在其它的模式之外单独进行设置。


SetWinDelay

设置两个窗口操作类命令间的延时，例如 WinActivate 。

SetWinDelay, Delay

参数

Delay 延时时间，单位毫秒。可以是一个 expression/表达式 。使用 -1 表示无延时，使用 0 表示最小延时。如果没有设置，默认延时 100 。

注意

脚本在执行了每个窗口操作类命令之后，会有一个自动的延时（休眠），除了 IfWinActive 和 IfWinExist 。这样做的目的是提高脚本的可靠性，因为一个窗口在创建、激活、最小化或其它操作之后有时候需要一个简短的“休息”来进行刷新，好对下一个可能的命令进行响应。

虽然允许使用 －1 （完全无延时），但是推荐最少只设置到 0 ，这样可以增加脚本正确执行的几率。

设置延时为 0 的话相当于执行了命令 Sleep(0) ，它会将当前脚本的剩余时间片分配给有需要的进程。如果没有进程需要，延时 0 就相当于完全没有延时。

cpu速度比较慢，或者cpu正忙，或者开启了窗口动画的时候，也许需要设置比较大的延时。

内置变量 A_WinDelay 保存了当前的设置。

每一个新运行的 Thread/线程（例如一个 hotkey/热键，custom menu item/自定义菜单，或 timed/定时器 事件）会将该命令的设置重置为默认值。要更改该命令的默认值，可以将该命令放在脚本的自动执行区域（脚本的顶部）。

相关命令

SetControlDelay, SetKeyDelay, SetMouseDelay, SetBatchLines, SendMode

示例

SetWinDelay, 10


StatusBarGetText

获取标准的状态栏控件中的文本.

StatusBarGetText, OutputVar [, Part#, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 用于保存获取的文本的变量名称.
Part# | 希望获取文本的状态栏那一部分的数字, 可以是一个 表达式. 默认值为 1, 这部分通常包含了我们感兴趣的文本.
WinTitle | 目标窗口的标题或标题中的部分文字 (匹配模式由 SetTitleMatchMode 决定). 如果省略所有的参数, 默认目标是 上一次匹配窗口. 如果此参数是字母 A 同时省略其他三个窗口参数, 则以当前的活动窗口为目标. 要用窗口的类名进行匹配, 请指定 ahk_class ExactClassName (Window Spy 中可以显示类名). 要用窗口的 进程标识符 (PID) 进行匹配, 请指定 ahk_pid %PID变量%. 要使用 窗口组 进行匹配, 请指定 ahk_group GroupName. 要使用窗口的 唯一 ID进行匹配, 请指定 ahk_id %VarContainingID%. 要减小检测范围, 请指定 多重条件. 例如: My File.txt ahk_class Notepad
WinText | 如果使用这个参数, 则它应该是目标窗口中某个文本元素的子字符串 (在 Window Spy 中会显示窗口中的文本元素). 隐藏文本只有当 DetectHiddenText 设置为 ON 的时候才能检测到.
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被排除.
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被排除.

ErrorLevel

如果出现错误, ErrorLevel 被设置为 1, 否则为 0. 如果出现了错误, OutputVar 会被置空.

备注

该命令尝试读取一个窗口中第一个 标准 状态栏 (Microsoft 通用控件: msctls_statusbar32).? 某些程序使用它们自己的状态栏控件或者 MS 通用控件的特殊版本, 这样的情况下无法获取它的文本.

通常情况下使用 StatusBarWait 命令比在一个循环中使用该命令更有效率, 因为它包含了避免重复调用 StatusBarGetText 形成的高开销的优化.

窗口中的标题和文字是大小写敏感的.要检测隐藏窗口, 必须打开 DetectHiddenWindows.

相关

StatusBarWait, WinGetTitle, WinGetText, ControlGetText

示例

StatusBarGetText, RetrievedText, 1, Search Results
IfInString, RetrievedText, found, MsgBox, Search results have been found.


StatusBarWait

等待一个窗口的状态栏包含指定的字符串.

StatusBarWait [, BarText, Seconds, Part#, WinTitle, WinText, Interval, ExcludeTitle, ExcludeText]

参数

BarText | 命令所等待出现的文本或部分文本. 默认值是空的, 这意味着等待目标状态栏变成空的. 该文本是大小写敏感的同时匹配行为由 SetTitleMatchMode 决定, 和下面的 WinTitle 类似. 代替等待状态栏的文本 改变 的方法, 在循环中使用 StatusBarGetText, 或者像页面底部的例子那样使用 RegEx.
Seconds | 在超时前等待的秒数 (可以包含小数点或者是一个 表达式), 超时后 ErrorLevel 将被设置为 1. 默认值为空, 这意味着无限期等待. 指定为 0 则等同于 0.5.
Part# | 希望获取文本的状态栏那一部分的数字, 可以是一个 表达式.默认值为 1, 这部分通常包含了我们感兴趣的文本.
WinTitle | 目标窗口的标题或标题中的部分文字 (匹配模式由 SetTitleMatchMode 决定).如果省略所有的参数, 默认目标是 上一次匹配窗口.如果此参数是字母 A, 同时省略其他三个窗口参数, 则以当前的活动窗口为目标.要用窗口的类名进行匹配, 请指定 ahk_class ExactClassName (Window Spy 中可以显示类名).要用窗口的 进程标识符 (PID) 进行匹配, 请指定 ahk_pid %PID变量%.要使用 窗口组 进行匹配, 请指定 ahk_group GroupName.要使用窗口的 唯一 ID 进行匹配, 请指定 ahk_id %VarContainingID%.要减小检测范围, 请指定 多重条件.例如: My File.txt ahk_class Notepad
WinText | 如果使用这个参数, 则它应该是目标窗口中某个文本元素的子字符串 (在 Window Spy 中会显示窗口中的文本元素).隐藏文本只有当 DetectHiddenText 设置为 ON 的时候才能检测到.
Interval | 命令等待时对状态栏进行检查的时间间隔 (单位为毫秒), 可以是一个 表达式. 默认值是 50.
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被排除.
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被排除.

ErrorLevel

如果在目标状态栏出现匹配的字符串之前命令超时了, ErrorLevel 被设置为 1. 状态栏无法访问时, 它被设置为 2. 成功找到匹配, 它被设置为 0.

备注

StatusBarWait 尝试读取一个窗口中第一个 标准 状态栏 (类名为 msctls_statusbar32).? 某些程序使用它们自己的状态栏控件或者 MS 通用控件的特殊版本. 此命令不支持这样的状态栏.

通常情况下使用 StatusBarWait 命令比在一个循环中使用 StatusBarGetText 命令更有效率, 因为它包含了避免重复调用 StatusBarGetText 形成的高开销的优化.

StatusBarWait 在开始匹配的等待之前会确定它的目标窗口. 如果目标窗口关闭了, 即使存在另一个满足指定的 WinTitle 和 WinText 的窗口命令也将停止等待.

当该命令处于等待状态时, 新的 线程 可以通过 热键, 自定义菜单项, 或 计时器 启动.

窗口中的标题和文字是大小写敏感的.要检测隐藏窗口, 必须打开 DetectHiddenWindows.

相关

StatusBarGetText, WinGetTitle, WinGetText, ControlGetText

示例

; The following example enters a new search pattern into an existing Explorer/Search window.
IfWinExist, Search Results ; Sets the Last Found window to simplify the below.
{
    WinActivate
    Send, {tab 2}!o*.txt{enter}  ; In the Search window, enter the pattern to search for.
    Sleep, 400  ; Give the status bar time to change to "Searching".
    StatusBarWait, found, 30
    if ErrorLevel
        MsgBox, The command timed out or there was a problem.
    else
        MsgBox, The search successfully completed.
}

?

; The following example waits for the status bar of the active window to change. This example requires v1.0.46.06+.
SetTitleMatchMode RegEx
IfWinExist A  ; Set the last-found window to be the active window (for use below).
{
   StatusBarGetText, OrigText
   StatusBarWait, ^(?!^\Q%OrigText%\E$)  ; This regular expression waits for any change to the text.
}


WinActivate

激活匹配指定条件的窗口（将它置于最前端）。

WinActivate [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略所有的参数，默认目标是 上一次匹配窗口 。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

如果窗口处于最小化状态，它首先会还原到原来的状态，再被激活。

在 60ms 中，脚本会对目标窗口的激活进行 6 次尝试。因此，一般情况下在 WinActivate 命令之后不需要使用 WinWaitActive 命令。

如果匹配的窗口已经处于激活状态，那么它会继续保持激活状态，脚本不会再去激活其它的匹配窗口。一般情况下，如果匹配的窗口不止一个，处于最前端（最近使用）的窗口将被激活。也可以使用 WinActivateBottom 激活最底端（最久一次使用）的窗口。

如果一个窗口紧接着另一个窗口的激活事件之后被激活，任务栏可能会闪烁（取决于系统和设置）。要防止这种现象，使用 #WinActivateForce 。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinActivateBottom, #WinActivateForce, SetTitleMatchMode, DetectHiddenWindows, Last Found Window, IfWinExist, IfWinActive, WinWaitActive, WinWait, WinWaitClose, WinClose, GroupActivate, WinSet

示例

IfWinExist, Untitled - Notepad
    WinActivate ; 使用上一句找到的窗口
else
    WinActivate, Calculator


WinActivateBottom

功能和 WinActivate 一样，只是这个是激活最底端的（至少最近激活的）窗口，而不是最顶端的。

WinActivateBottom [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

如果只有一个匹配窗口，WinActivateBottom 完全和 WinActivate 一样。

Window groups 更加高级和方便，为了提高脚本的功能性和适应性，应该尽量使用它。

如果窗口处于最小化状态，它首先会还原，再被激活。

在 60ms 中，脚本会对目标窗口的激活进行 6 次尝试。因此，一般情况下在 WinActivate 命令之后不需要使用 WinWaitActive 命令。

和 WinActivate 不同，这个命令中不能使用 上一次匹配窗口 ，因为它可能不是最底端的窗口。因此，至少要有一个参数不为空。

如果一个窗口紧接着另一个窗口的激活事件之后被激活，任务栏可能会闪烁（取决于系统和设置）。要防止这种现象，使用 #WinActivateForce 。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinActivate, #WinActivateForce, SetTitleMatchMode, DetectHiddenWindows, IfWinExist, IfWinActive, WinWaitActive, WinWait, WinWaitClose, GroupActivate

示例

; 这个快捷键让你以从最老到最新的顺序访问所有打开的浏览器窗口
#i::
SetTitleMatchMode, 2
WinActivateBottom, - Microsoft Internet Explorer
return


WinClose

关闭匹配指定条件的窗口。

WinClose [, WinTitle, WinText, SecondsToWait, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个窗口参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个窗口参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个变量要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
SecondsToWait | 如果省略或留空，命令完全不会等待。如果使用 0 ，会等待 500ms 。否则，它会等待指定的时间（可以包含小数点或者是一个 表达式 ）来让窗口彻底关闭。如果窗口在指定的时间内并未关闭，脚本会继续执行，但是该命令 不会 设置 ErrorLevel/错误等级 。所以当需要检测一个窗口是否已被关闭的时候，使用 IfWinExist 或 WinWaitClose 。当该命令处于等待状态的时候，仍然可以通过 快捷键 ，自定义菜单 ，或 定时器 来启动新的 线程 。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

这个命令传送一个关闭信息给窗口，结果取决于窗口（可能会询问是否保存数据，或其它）。

如果匹配的窗口中有一个处于激活状态，那么它会被关闭，脚本不会再去关闭其它的匹配窗口。一般情况下，如果匹配的窗口不止一个，处于最前端（最近使用）的窗口将被关闭。

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

WinClose 通过发送一个 WM_CLOSE 消息给目标窗口来关闭窗口。这个关闭的方法稍微有一点强迫性。另外一个关闭窗口的方法是发送下面那样的消息给窗口。这个方法和 WinClose 有点不同，它更接近按 Alt + F4 或者点击标题栏上关闭按钮的效果：

PostMessage, 0x112, 0xF060,,, WinTitle, WinText  ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE

用 WinClose 不能关闭的窗口，可以使用 WinKill 强制关闭。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinKill, WinWaitClose, Process, WinActivate, SetTitleMatchMode, DetectHiddenWindows, Last Found Window, IfWinExist, IfWinActive, WinWaitActive, WinWait, GroupActivate

示例

IfWinExist, Untitled - Notepad
    WinClose ; 使用上面找到的窗口
else
    WinClose, Calculator


WinGet

返回符合指定条件的窗口的 uID，进程ID，进程名称，或控件列表。它也可以返回一个列表，包含所有符合指定条件的窗口。

WinGet, OutputVar [, Cmd, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 输出变量，存储由 Cmd 指定的结果。
Cmd | 查看下面的说明。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略下面 3 个参数，默认目标是 上一次匹配的窗口 。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_pid %ID变量%
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

Cmd 指定了返回值的内容，如果留空，默认是 ID 。它可以是下面单词的其中之一：

ID：返回窗口的 uID（HWND/句柄）。如果没有匹配窗口，OutputVar 为空。函数 WinExist() 和 WinActive() 也可以用来获取窗口的 uID ，例如，WinExist("A") 能快速获取当前激活窗口的 uID 。要获取一个控件的 HWND（供 Post/SendMessage 或 DllCall 使用），使用 ControlGet Hwnd 或 MouseGetPos 。

IDLast：和上面的功能一样，不过当匹配的窗口超过一个的时候，它返回的是 最底端/最后使用 的窗口的 ID。如果只有一个匹配窗口，它和 ID 的效果一样。类似的概念也适用于 WinActivateBottom 。

PID：返回窗口的 进程ID（PID）。

ProcessName：返回窗口所属进程的进程名称（例如 notepad.exe）。如果没有匹配窗口，OutputVar 为空。

Count：返回符合 WinTitle ，WinText ，ExcludeTitle 以及 ExcludeText 所指定的条件的窗口数量（如果没有匹配窗口则返回 0 ）。要统计当前总窗口数，省略所有和 标题/文本 有关的参数。默认不统计隐藏窗口，除非打开了 DetectHiddenWindows 。

List：返回所有符合 WinTitle ，WinText ，ExcludeTitle 以及 ExcludeText 所指定的条件的窗口的 uID （要返回当前所有窗口的 uID ，省略所有和 标题/文本 有关的参数）。每个 ID 由一个 数组元素 存储，数组元素名从 OutputVar 开始，而 OutputVar 本身则存储了数组的长度（如果没有匹配窗口则为 0 ）。例如，OutputVar 使用 MyArray ，有 2 个匹配窗口，则变量 MyArray1 存储了第一个窗口的 ID ，变量 MyArray2 存储了第二个窗口的 ID ，而变量 MyArray 存储了数组长度 2 。窗口 ID 的返回顺序是从最顶端的窗口到最底端的窗口（取决于它们在桌面上的堆放方式）。默认不返回隐藏窗口的 ID ，除非打开了 DetectHiddenWindows 。在一个 函数 中，要创建一个全局数组，在使用这个命令之前 声明 MyArray 为全局变量（在使用了 assume-global 的函数中则是相反的情况）。

MinMax：返回窗口的 最小化/最大化 状态。如果没有匹配窗口，OuputVar 为空，否则，返回下列数值之一：
-1：窗口处于最小化状态（ WinRestore 可以还原它）。
1：窗口处于最大化状态（ WinRestore 可以还原它）。
0：窗口既不处于最大化也不处于最小化状态。

ControlList：返回一个列表，包含窗口中所有控件的名称。如果没有匹配窗口或窗口中没有控件，OutputVar 为空。否则，每个控件的名称由它的 class 名和序号（ClassNN）组成，同 Window Spy 中显示的一样。

除了最后一个控件的名称之外，每个名称后都跟着一个换行符（`n）。要单独遍历所有的控件名称，使用 parsing loop ，可以参考最下面示例区中的例子。

控件名称的存储顺序取决于它们的 Z 轴顺序，如果窗口支持 Tab 导航，这个顺序一般和 Tab 顺序一样。

要返回鼠标当前所指控件的信息，使用 MouseGetPos 。

ControlListHwnd [v1.0.43.06+]：功能同上，不同的是它返回的是控件的 窗口句柄（HWND）。

Transparent：返回窗口的透明度（用 WinSet 设置窗口透明）。OutputVar 在以下情况时为空：1、系统比 Windows XP 老；2、没有匹配窗口；3、窗口没有设置透明；4、其它情况（由系统行为引起），例如窗口透明后被最小化，还原，以及/或者调整大小。否则，OutputVar 存储一个 0 到 255 之间的值，0 表示完全透明，255 表示不透明。例如：

MouseGetPos,,, MouseWin
WinGet, Transparent, Transparent, ahk_id %MouseWin%  ; 获取鼠标当前所指窗口的透明度。

TransColor：返回窗口的透明色（用 WinSet 设置透明色）。OutputVar 在以下情况时为空：1、系统比 Windows XP 老；2、没有匹配窗口；3、窗口没有设置透明色；4、其它情况（由系统行为引起），例如窗口透明后被最小化，还原，以及/或者调整大小。否则，OutputVar 存储一个 6 位的十六进制数，表示 RGB 颜色，比如 0x00CC99 。例如：

MouseGetPos,,, MouseWin
WinGet, TransColor, TransColor, ahk_id %MouseWin%  ; 获取鼠标当前所指窗口的透明色。

Style 或 ExStyle：返回一个 8 位的十六进制数，表示窗口的样式或扩展样式。如果没有匹配窗口，OutputVar 为空。下面这个例子检测一个窗口是否具有 WS_DISABLED 样式：

WinGet, Style, Style, My Window Title
if (Style & 0x8000000)  ; 0x8000000 表示 WS_DISABLED 。
  ... 检测到窗口为不可用状态，进行适当的操作。

下面的例子检测一个窗口是否具有 WS_EX_TOPMOST 样式（置顶）：

WinGet, ExStyle, ExStyle, My Window Title
if (ExStyle & 0x8)  ; 0x8 表示 WS_EX_TOPMOST.
  ... 检测到窗口处于置顶状态，进行适当的操作。

更多样式，查看 样式列表 。

注意

窗口的 ID 只在窗口的生命周期中有效。也就是说，一个程序重启之后，它所有的窗口都将使用新的 ID 。

这个命令获取的 ID 仅是一个数字（不包括前缀“ahk_id”），并且以十六进制存储，与 SetFormat 的设置无关。

要获取鼠标当前所指窗口的 ID ，使用 MouseGetPos 。

虽然目前获取的 ID 是 32 位的无符号整数，但是将来的版本中可能会变成 64 位的。因此，对这些值进行数学操作，例如相加，是不安全的。因为这些操作要求操作数是有正负号的整数而不是无符号的整数。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinGetClass, Process, WinGetTitle, MouseGetPos, ControlGet, ControlFocus, GroupAdd

示例

; 示例 #1：最大化当前激活窗口并且显示它的 uID 。
WinGet, active_id, ID, A
WinMaximize, ahk_id %active_id%
MsgBox, The active window's ID is "%active_id%".

; 示例 #2：访问当前所有窗口并且分别显示它们的信息。
WinGet, id, list,,, Program Manager
Loop, %id%
{
    this_id := id%A_Index%
    WinActivate, ahk_id %this_id%
    WinGetClass, this_class, ahk_id %this_id%
    WinGetTitle, this_title, ahk_id %this_id%
    MsgBox, 4, , Visiting All Windows`n%a_index% of %id%`nahk_id %this_id%`nahk_class %this_class%`n%this_title%`n`nContinue?
    IfMsgBox, NO, break
}

; 示例 #3：从控件列表中分离出每个单独的控件名称。
WinGet, ActiveControlList, ControlList, A
Loop, Parse, ActiveControlList, `n
{
    MsgBox, 4,, Control #%a_index% is "%A_LoopField%". Continue?
    IfMsgBox, No
        break
}

; 示例 #4：实时显示当前激活窗口的控件列表。
#Persistent
SetTimer, WatchActiveWindow, 200
return
WatchActiveWindow:
WinGet, ControlList, ControlList, A
ToolTip, %ControlList%
return


WinGetActiveStats

将 WinGetActiveTitle 和 WinGetPos 合并为一条命令。

WinGetActiveStats, Title, Width, Height, X, Y

参数

Title | 存储当前激活窗口的标题的变量。
Width/Height | 存储当前激活窗口的宽或高的变量。
X, Y | 存储当前激活窗口左上角的横坐标和纵坐标的变量。

注意

如果没有找到匹配的窗口，输出变量为空。

这个命令等同于顺序执行下面两个命令：
WinGetTitle, Title, A
WinGetPos, X, Y, Width, Height, A

如果当前激活的窗口是一个隐藏窗口并且 DetectHiddenWindows 是关闭的（默认），则所有的命令，除了 WinShow ，都不能检测到该窗口。如果因为这个原因或者其它的原因不能检测到当前激活的窗口，则该命令所有的输出变量都为空。

相关命令

WinGetPos, WinGetActiveTitle, WinGetTitle, WinGetClass, WinGetText, ControlGetText

示例

WinGetActiveStats, Title, Width, Height, X, Y
MsgBox, The active window "%Title%" is %Width% wide`, %Height% tall`, and positioned at %X%`,%Y%.


WinGetActiveTitle

获取当前激活窗口的标题。

WinGetActiveTitle, OutputVar

参数

OutputVar 输出变量，存储当前激活窗口的标题。

注意

这个命令等同于：WinGetTitle, OutputVar, A

相关命令

WinGetPos, WinGetActiveStats, WinGetTitle, WinGetClass, WinGetText, ControlGetText

示例

WinGetActiveTitle, Title
MsgBox, The active window is "%Title%".


WinGetClass

返回匹配指定条件的窗口的 class 名。

WinGetClass, OutputVar [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 输出变量，存储 class 名。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略所有的参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

只返回 class 名（前缀 “ahk_class” 不会存入 OutputVar 中）。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinGet, WinGetTitle

示例

WinGetClass, class, A
MsgBox, The active window's class is "%class%".


WinGetPos

返回匹配指定条件的窗口的位置和大小。

WinGetPos [, X, Y, Width, Height, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

X, Y | 存储目标窗口左上角的横坐标和纵坐标的变量。如果省略，则不能获取到相应的数据。
Width/Height | 存储目标窗口的宽或高的变量。如果省略，则不能获取到相应的数据。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略后面的 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略后面的 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

如果没有匹配窗口，输出变量为空。

如果参数 WinTitle 使用“Program Manager”，该命令会返回桌面的大小，一般和当前屏幕分辨率相同。

最小化的窗口同样有位置和大小，具体取决于操作系统以及系统设置。

要获取当前鼠标所指窗口和控件的名称，使用 MouseGetPos 。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinMove, ControlGetPos, WinGetActiveStats, WinGetActiveTitle, WinGetTitle, WinGetText, ControlGetText

示例

WinGetPos, X, Y, Width, Height, Calculator
MsgBox, Calculator is at %X%`,%Y%

WinGetPos, X, Y, , , A  ; “A”表示使用当前激活窗口为目标窗口
MsgBox, The active window is at %X%`,%Y%

IfWinExist, Untitled - Notepad
{
    WinGetPos, Xpos, Ypos  ; 使用上面找到的窗口
    MsgBox, Notepad is at %Xpos%`,%Ypos%
}


WinGetText

返回匹配指定条件的窗口中的文本。

WinGetText, OutputVar [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 输出变量，存储获取的文本。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

ErrorLevel

如果出现错误，ErrorLevel/错误级别 设置为 1 ，否则为 0 。

注意

一般情况下，返回的文本和 Window Spy 中显示的一样。但是，如果 DetectHiddenText 为关闭状态，则不能获取隐藏文本。

每个获取的文本元素之后都跟着一个回车和一个换行符（CR+LF），在脚本中用 `r`n 表示。要将返回值分解为单行文本或从中提取子字符串，使用 StringGetPos 和 StringMid 这样的命令。也可以使用 parsing loop 来单独检查每行文本或每个单词。

如果获取的文本不完整，尝试一下在 WinGetText 之前使用 VarSetCapacity(OutputVar, 55) （将 55 替换为大于窗口文本的大小）。有时候这是很有必要的，因为有些应用程序的窗口不会正确响应 WM_GETTEXTLENGTH 消息，导致 AutoHotkey 将输出变量设置过小，无法存储所有的窗口文本。

能够获取的文本数量取决于变量的最大容量（可以使用 #MaxMem 设置）。因此，当一个窗口包含大量文本（例如打开了一个大文档的记事本）的时候，这个命令可能会消耗大量的内存。要避免这种情况，使用 ControlGetText 来获取窗口的部分文本。在任何时候，一个变量可以通过指向空值来释放它所占用的内存，例如 OutputVar =

Windows 95/98/ME 中可能会限制窗口中的每个文本元素大小不超过 64 KB 。

要获取窗口中的控件列表，使用：WinGet, OutputVar, ControlList, WinTitle

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

ControlGetText, WinGetActiveStats, WinGetActiveTitle, WinGetTitle, WinGetPos, #MaxMem

示例

Run, Calc.exe
WinWait, Calculator
WinGetText, text  ; 使用上面找到的窗口
MsgBox, The text is:`n%text%


WinGetTitle

返回匹配指定条件的窗口的标题。

WinGetTitle, OutputVar [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

OutputVar | 输出变量，存储标题。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

要获取当前鼠标所指的窗口标题，使用 MouseGetPos 。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinGetActiveStats, WinGetActiveTitle, WinGetClass, WinGet, WinGetText, ControlGetText, WinGetPos

示例

WinGetTitle, Title, A
MsgBox, The active window is "%Title%".


WinHide

隐藏匹配指定条件的窗口。

WinHide [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略所有的参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个变量要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

使用 WinShow 显示一个隐藏的窗口（不受 DetectHiddenWindows 设置的影响）。

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

可以使用下面的脚本隐藏/显示任务栏：
WinHide ahk_class Shell_TrayWnd
WinShow ahk_class Shell_TrayWnd

相关命令

WinShow, SetTitleMatchMode, DetectHiddenWindows, Last Found Window, WinSet

示例

Run, notepad.exe
WinWait, Untitled - Notepad
Sleep, 500
WinHide ; 使用上面匹配到的窗口
Sleep, 1000
WinShow


WinKill

强制关闭匹配指定条件的窗口。

WinKill [, WinTitle, WinText, SecondsToWait, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个窗口参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个窗口参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个参数要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
SecondsToWait | 如果省略或留空，命令完全不会等待。如果使用 0 ，会等待 500ms 。否则，它会等待指定的时间（可以包含小数点或者是一个 表达式 ）来让窗口彻底关闭。如果窗口在指定的时间内并未关闭，脚本会继续执行，但是该命令 不会 设置 ErrorLevel/错误等级 。所以当需要检测一个窗口是否已被关闭的时候，使用 IfWinExist 或 WinWaitClose 。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

这个命令首先会短暂的尝试正常关闭窗口，如果失败了，就通过结束窗口进程的方式来强制关闭它。

如果匹配的窗口中有一个处于激活状态，那么它会被关闭，脚本不会再去关闭其它的匹配窗口。一般情况下，如果匹配的窗口不止一个，处于最前端（最近使用）的窗口将被关闭。

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinClose, WinWaitClose, Process, WinActivate, SetTitleMatchMode, DetectHiddenWindows, Last Found Window, IfWinExist, IfWinActive, WinWaitActive, WinWait, GroupActivate

示例

IfWinExist, Untitled - Notepad
    WinKill ; 使用上面找到的窗口
else
    WinKill, Calculator


WinMaximize

最大化匹配指定条件的窗口。

WinMaximize [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个参数要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

使用 WinRestore 还原窗口，使用 WinMinimize 将窗口最小化。

如果某些窗口不能正确响应 WinMaximize ，尝试使用下面的脚本：

PostMessage, 0x112, 0xF030,,, WinTitle, WinText  ; 0x112 = WM_SYSCOMMAND ，0xF030 = SC_MAXIMIZE

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinRestore, WinMinimize

示例

Run, notepad.exe
WinWait, Untitled - Notepad
WinMaximize ; 使用上面找到的窗口

^Up::WinMaximize, A  ; 设置一个快捷键来最大化当前窗口


WinMinimize

最小化匹配指定条件的窗口到任务栏。

WinMinimize [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个参数要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

使用 WinRestore 或者 WinMaximize 还原窗口。

如果某些窗口不能正确响应 WinMinimize ，尝试使用下面的脚本：
PostMessage, 0x112, 0xF020,,, WinTitle, WinText ; 0x112 = WM_SYSCOMMAND ，0xF020 = SC_MINIMIZE

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinRestore, WinMaximize, WinMinimizeAll

示例

Run, notepad.exe
WinWait, Untitled - Notepad
WinMinimize ; 使用上面找到的窗口

^Down::WinMinimize, A  ;设置一个快捷键来最小化当前窗口


WinMinimizeAll / WinMinimizeAllUndo

最小化或还原所有窗口

WinMinimizeAll
WinMinimizeAllUndo

在大多数系统中，这个命令等同于 Explore 的 Win-M 和 Win-D 快捷键。

相关命令

WinMinimize, GroupAdd

示例

WinMinimizeAll
WinMinimizeAllUndo


WinMove

对匹配指定条件的窗口进行移动或更改大小的操作。

WinMove, X, Y
WinMove, WinTitle, WinText, X, Y [, Width, Height, ExcludeTitle, ExcludeText]

参数

X, Y | 目标窗口新位置的 X轴 和 Y轴 坐标（单位是像素），以窗口左上角为基准点，可以是 表达式 。屏幕左上角坐标为 0, 0 。 如果只指定了这 2 个参数，其它参数留空，默认目标是 上一次匹配窗口 。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个窗口参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个窗口参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
Width, Height | 目标窗口新大小的宽度和高度（单位是像素），可以是 表达式 。如果其中一个或两个一起留空或省略或使用单词 DEFAULT ，则默认等于原始宽度/高度。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

如果 Width 和 Height 参数太小（或负数），大多数带标题栏的窗口最小不会小于 112 x 27 像素（有些类型的窗口可能大小有出入）。如果 Width 和 Height 参数太大，大多数窗口最大不会大于 (桌面分辨率 + 12) 像素。

坐标轴参数可以使用负数，这是为了支持多显示器系统，以及可以让窗口完全移出桌面。

虽然 WinMove 不能移动最小化的窗口，但是在 DetectHiddenWindows 打开的情况下它可以移动隐藏窗口。

窗口移动的速度受 SetWinDelay 影响.

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

ControlMove, WinGetPos, WinHide, WinMinimize, WinMaximize, WinSet

示例

Run, calc.exe
WinWait, Calculator
WinMove, 0, 0 ; 将 WinWait 找到的窗口移动到屏幕左上角。

SplashTextOn, 400, 300, Clipboard, The clipboard contains:`n%clipboard%
WinMove, Clipboard, , 0, 0 ; 将窗口移动到左上角
Msgbox, Press OK to dismiss the SplashText
SplashTextOff

; 下面的 函数 将指定的窗口居中。
CenterWindow(WinTitle)
{
    WinGetPos,,, Width, Height, %WinTitle%
    WinMove, %WinTitle%,, (A_ScreenWidth/2)-(Width/2), (A_ScreenHeight/2)-(Height/2)
}


WinRestore

还原匹配指定条件的处于最大化或最小化状态中的窗口。

WinRestore [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个参数要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

如果某些窗口不能正确响应 WinRestore ，尝试使用下面的脚本：

PostMessage, 0x112, 0xF120,,, WinTitle, WinText  ; 0x112 = WM_SYSCOMMAND ，0xF120 = SC_RESTORE

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinMinimize, WinMaximize

示例

WinRestore, Untitled - Notepad


WinSet

对匹配指定条件的窗口进行一系列的设置，例如设置“总在最前”，以及透明度等。

WinSet, Attribute, Value [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

Attribute, Value | 查看下面的列表。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略后面 3 个参数，默认目标是 上一次匹配的窗口 。如果这个参数使用字母 A ，同时省略后面 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

Attribute, Value

AlwaysOnTop, [On|Off|Toggle]：让一个窗口处于置顶状态。使用 ON 开启设置，使用 OFF 关闭设置，使用 TOOGLE 切换设置。如果省略，默认是 TOOGLE。也可以使用单词 Topmost 替换 AlwaysOnTop。

Bottom：将一个窗口放到最底端，也就是所有窗口的下面。这个效果类似使用 Alt－Escape 快捷键。例如：WinSet, Bottom,, WinTitle

Top：将一个窗口放到最前端而不进行 激活 。但是，大多数情况下系统都会自动激活它。另外，当系统禁止切换窗口焦点的时候该命令可能没有效果（这取决于当前窗口类型以及用户当前的操作）。要应付这种情况，可以让窗口暂时 置顶 ，再取消置顶。

Disable 或 Enable：停用或启用一个窗口。当一个窗口处于停用状态的时候，用户不能移动它或利用它的控件进行交互。另外，停用的窗口也不会出现在 alt-tab 列表中。

Redraw：通过通知系统某个窗口区域需要重绘，来刷新一个窗口的界面和内容。如果对某个窗口不起作用，尝试 WinMove 。如果还不起作用，尝试：
WinHide, WinTitle
WinShow, WinTitle

Style,N 或 ExStyle,N：分别设置窗口的样式或扩展样式。如果 N 中的第一个字符是加号或减号，则窗口会增加或移除 N 中指定的样式（可同时指定多个样式，下同）；如果第一个字符是符号“`”，窗口将对 N 中指定的样式进行切换操作；如果第一个字符是数字，窗口原来的所有样式将被覆盖，彻底变成 N 中指定的样式。

如果样式设置失败，ErrorLevel/错误等级 设置为 1 ，成功为 0 。当没有匹配窗口或窗口不能应用指定的样式的时候（一般发生在 Windows 9x 中）会设置失败。

更改了一个窗口的样式之后，可能需要对窗口进行重绘，使用命令 WinSet Redraw （具体见下面）。最后，一些常用的样式代码可以参看 样式列表 。一些例子：

WinSet, Style, -0xC00000, A  ; 移除当前激活窗口的标题栏（WS_CAPTION）。
WinSet, ExStyle, ^0x80, WinTitle  ; 切换窗口的 WS_EX_TOOLWINDOW 属性，可以将窗口添加到/移除于 alt-tab 列表中。

WinSet, Region [, Options, WinTitle, ...]

更改一个窗口的形状为指定的方形，椭圆形，或多边形。如果 Options 参数留空，窗口将恢复到原来的形状。否则，可以指定下面的一个或多个参数，用空格分隔：

Wn：方形或椭圆形的宽度。例如：w200
Hn：方形或椭圆形的高度。例如：h300
X-Y：X轴 和 Y轴 坐标。例如，200-0 中的 200 表示 X轴 坐标，0 表示 Y轴 坐标。
E：将窗口形状设置为椭圆形，而不是方形。这个参数只有在同时指定了 W 和 H 参数的时候才有效。
R[w-h]：设置方形窗口的圆角。例如，R30-30 表示圆角大小为 30x30 。如果省略 w-h ，默认使用 30-30 。R 参数只有在同时指定了 W 和 H 参数的时候才有效。

方形或椭圆形：如果同时指定了 W 和 H 参数，窗口的形状将变成方形，方形区域左上角的位置坐标为 X-Y 参数指定的坐标（以窗口左上角为原点）。但是，如果同时使用了 E 参数的话，窗口的形状将变成椭圆形。例如：WinSet, Region, 50-0 W200 H250 E, WinTitle

多边形：如果同时指定了 W 和 H 参数，并且在 X-Y 参数中指定了多组坐标，窗口的形状将变成多边形（每组坐标以窗口左上角为原点）。例如，如果指定了 3 组坐标，大多数情况下窗口的形状会变成三角形，具体的形状取决于 3 组坐标的顺序。此外，在 Options 参数中也可以加上单词 Wind ，这将会使用一种弯曲的方式来决定多边形的形状。

如果形状设置失败，ErrorLevel/错误等级 设置为 1 ，成功为 0 。失败的原因有：1）没有匹配窗口；2）Options 中有一个或多个参数无效；3）指定了超过 2000 组坐标；4）指定的形状无效或不适用与目标窗口。

更多示例请查看本页最下方的示例代码。

WinSet, Transparent, N, WinTitle

设置窗口为半透明状态。指定 N 为一个 0 到 255 的数字来表示透明度：0 表示完全透明，255 表示完全不透明。使用单词 OFF 彻底关闭窗口的透明效果。和设置透明度为 255 不同，使用 OFF 会提升系统性能并降低系统资源的占用。

已知的关于透明度和 TransColor/透明色 的限制：

  • 在 Windows 9x 和 NT4 上无效。
  • 对于没有标题栏并且没有 总在最前 属性的窗口无效。对于 图形界面窗口，可以在设置了窗口透明之后再移除标题栏。另外，下面的属性设置也可以让窗口设置透明度：Gui -Caption +ToolWindow.
  • 设置透明度为 OFF 之前最好先设置透明度为 255 ，这样可以避免窗口的重绘问题，例如背景变黑。如果窗口仍然不能正确的重绘，参看下面有关 Redraw/重绘 的说明。
  • 要更改窗口当前的 TransColor/透明色 ，最好先关闭窗口透明。

小贴士：要设置任务栏的透明度，使用 WinSet, Transparent, 150, ahk_class Shell_TrayWnd 。类似的，要设置开始菜单的透明度，参照这个例子：

DetectHiddenWindows, on
WinSet, Transparent, 150, ahk_class BaseBar  ; 要让开始菜单的子菜单也透明，继续加入下面的代码。

要让当前选择的菜单或系统所有的菜单透明，运行下面这个脚本。注意虽然这个脚本不能让它自己的菜单透明，但是可以让其它脚本的菜单透明：

#Persistent
SetTimer, WatchForMenu, 5
return  ; 结束自动运行区域。

WatchForMenu:
DetectHiddenWindows, on  ; 以立即检测到菜单。
IfWinExist, ahk_class #32768
    WinSet, Transparent, 150  ; 使用上一行找到的窗口。
return

WinSet, TransColor, Color [N], WinTitle

让目标窗口中所有符合指定颜色的区域完全透明（在 Windows 9x 和 NT4 中无效）。如果用户点击窗口中的透明部分，点击事件会“穿透”该窗口传递给下面的窗口。Color 参数可以是一个颜色名称或一个 RGB 值（关于颜色详细请参看 颜色图表 ，或者使用 PixelGetColor 的 RGB 模式）。要让目标窗口中符合指定颜色的区域半透明，在颜色参数之后添加一个表示透明度的数字（0 - 255）。例如：WinSet, TransColor, EEAA99 150, WinTitle

TransColor/透明色 常被用来制作屏幕菜单（OSD）或窗口特效。有一个关于屏幕菜单的例子在 Gui 命令帮助页的最下面 。

单词 OFF 用来完全关闭窗口的透明设置。下面两个脚本的功能是一样的：
WinSet, Transparent, Off, WinTitle
WinSet, TransColor, Off, WinTitle

已知的限制：参看 上面的列表 。

注意

除了上面明确说明的地方外，ErrorLevel/错误等级 不会被该命令修改。

虽然 Windows 2000/XP 及之后的系统都支持设置透明，但是只有 XP 之后的系统才能获取到窗口的透明度设置（通过 WinGet 命令）。

可以用下面的脚本取消一个脚本的 SplashText 窗口的置顶状态：
WinSet, AlwaysOnTop, Off, My Splash Window Title

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinGet, WinHide, WinSetTitle, WinMove, WinActivate, Control

示例

WinSet, Transparent, 200, Untitled - Notepad ; 让窗口稍微有点透明效果
WinSet, TransColor, White, Untitled - Notepad ; 让窗口中白色的部分透明
WinSet, AlwaysOnTop, toggle, Calculator ; 切换计算器的“总在最前”状态

; 长一点的例子：
; 这里有一些快捷键用来演示“Transparent/透明度”和“TransColor/透明色”的效果
; 注意：如果你按下快捷键的时候鼠标正指在 TransColor/透明色
; 设置的窗口透明部分上，则快捷键影响的就是透明窗口下方的窗口。
; 同样，快捷键 Win + G 只有在 Windows XP 上才有效果，
; 因为 Windows 2000 不能获取窗口的透明设置

#t::  ; 快捷键 Win+T 让窗口中符合鼠标所指颜色的部分透明
MouseGetPos, MouseX, MouseY, MouseWin
PixelGetColor, MouseRGB, %MouseX%, %MouseY%, RGB
; 设置新的透明效果之前需要关闭窗口当前的透明效果
WinSet, TransColor, Off, ahk_id %MouseWin%
WinSet, TransColor, %MouseRGB% 220, ahk_id %MouseWin%
return

#o::  ; 快捷键 Win+O 关闭鼠标所指窗口的透明效果
MouseGetPos,,, MouseWin
WinSet, TransColor, Off, ahk_id %MouseWin%
return

#g::  ; 快捷键  Win+G 显示鼠标所指窗口当前的透明效果设置
MouseGetPos,,, MouseWin
WinGet, Transparent, Transparent, ahk_id %MouseWin%
WinGet, TransColor, TransColor, ahk_id %MouseWin%
ToolTip Translucency:`t%Transparent%`nTransColor:`t%TransColor%
return

; “WinSet Region”的例子
WinSet, Region, 50-0 W200 H250, WinTitle  ; 让窗口只显示指定的方形部分
WinSet, Region, 50-0 W200 H250 R40-40, WinTitle  ; 和上面的一样，不过有 40 x 40 的圆角。
WinSet, Region, 50-0 W200 H250 E, WinTitle  ; 椭圆形窗口
WinSet, Region, 50-0 250-0 150-250, WinTitle  ; 倒三角形窗口
WinSet, Region,, WinTitle ; 将窗口恢复原状

; 更加复杂的 Region 例子，在窗口中创建了一个方形的“洞”。
; 这里指定了 2 个方形，一个内部的一个外部的。每个方形使用 5 组坐标
WinSet, Region, 0-0 300-0 300-300 0-300 0-0   100-100 200-100 200-200 100-200 100-100, WinTitle


WinSetTitle

改变匹配指定条件的窗口的标题。

WinSetTitle, NewTitle
WinSetTitle, WinTitle, WinText, NewTitle [, ExcludeTitle, ExcludeText]

参数

NewTitle | 目标窗口的新标题。如果只指定这一个参数，其它参数省略，默认目标是 上一次匹配窗口 。
WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个参数，默认目标是 上一次匹配窗口 。如果这个参数使用字母 A ，同时省略其它 3 个参数，则以当前激活的窗口作为目标。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

如果窗口所在的程序本身经常修改窗口的标题，那么该命令对窗口标题的修改就只能是暂时的。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinMove, WinGetActiveStats, WinGetActiveTitle, WinGetText, ControlGetText, WinGetPos, WinSet

示例

WinSetTitle, Untitled - Notepad, , This is a new title

; 另一个修改记事本标题的例子：
Run, notepad.exe
WinWaitActive, Untitled - Notepad
WinSetTitle, This is a new title  ; 使用上面 WinWaitActive 找到的窗口


WinShow

显示匹配指定条件的窗口。

WinShow [, WinTitle, WinText, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略所有的参数，默认目标是 上一次匹配窗口 。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 （此时 WinText ，ExcludeTitle ，以及 ExcludeText 三个变量要省略）。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

注意

默认情况下，WinShow 是唯一一个在任何时候都能检测到隐藏窗口的命令。其它的命令只有在开启 DetectHiddenWindows 的时候才能检测到隐藏窗口。

这个命令只对匹配窗口中处于最前端的进行操作，除了在 WinTitle 参数中使用 ahk_group 组名 的时候，这时候会影响窗口组中的所有窗口。

相关命令

WinHide, SetTitleMatchMode, DetectHiddenWindows, Last Found Window

示例

Run, notepad.exe
WinWait, Untitled - Notepad
Sleep, 500
WinHide  ; 因为它省略了所有参数，它使用上面找到的窗口。.
Sleep, 1000
WinShow


WinWait

等待，直到匹配指定条件的窗口出现。

WinWait [, WinTitle, WinText, Seconds, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad WinTitle 只有在 WinText ，ExcludeTitle ，以及 ExcludeText 不都为空的时候才能留空。
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
Seconds | 超时时间。超时后将不再等待并且设置 ErrorLevel/错误等级 为 1 。留空表示无限等待。指定 0 等同于 0.5 。这个参数可以一个 表达式 。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

ErrorLevel/错误等级

超时的话 ErrorLevel/错误等级 为 1 ，否则为 0 。

注意

匹配的窗口出现后，命令会立即设置 ErrorLevel/错误等级 为 0 ，更新 上一次匹配窗口 ，然后让脚本继续执行，而不必再等待 Seconds 参数中指定的时间。

当该命令处于等待状态的时候，仍然可以通过 快捷键 ，自定义菜单 ，或 定时器 来启动新的 线程 。

如果其它的 线程 在该命令等待的时候改变了参数中所使用到的变量的值，该命令会无视这些改变 —— 它仍然会使用这些变量在开始等待的时候的值。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinWaitActive, WinWaitClose, IfWinExist, IfWinActive, Process, SetTitleMatchMode, DetectHiddenWindows

示例

Run, notepad.exe
WinWait, Untitled - Notepad, , 3
if ErrorLevel
{
    MsgBox, WinWait timed out.
    return
}
else
    WinMinimize  ; 最小化上面找到窗口。


WinWaitActive / WinWaitNotActive

等待匹配指定条件的窗口处于激活或未激活状态。

WinWaitActive [, WinTitle, WinText, Seconds, ExcludeTitle, ExcludeText]
WinWaitNotActive [, WinTitle, WinText, Seconds, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个窗口参数，默认目标是 上一次匹配窗口 。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
Seconds | 超时时间。超时后将不再等待并且设置 ErrorLevel/错误等级 为 1 。留空表示无限等待。指定 0 等同于 0.5 。这个参数可以一个 表达式 。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

ErrorLevel

超时以后 ErrorLevel/错误等级 为 1 ，否则为 0 。

注意

如果一个匹配窗口的状态符合命令要求，命令会立即设置 ErrorLevel/错误等级 为 0 ，然后让脚本继续执行，而不必再等待 Seconds 参数中指定的时间。

如果命令开始执行的时候匹配窗口处于激活状态，WinWaitActive 和 WinWaitNotActive 都会更新 上一次匹配的窗口 。另外，匹配窗口在超时时间以内激活，WinWaitActive 也会更新上一次匹配窗口。

当该命令处于等待状态的时候，仍然可以通过 快捷键 ，自定义菜单 ，或 定时器 来启动新的 线程 。

如果其它的 线程 在该命令等待的时候改变了参数中所使用到的变量的值，该命令会无视这些改变 —— 它仍然会使用这些变量在开始等待的时候的值。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinWait, WinWaitClose, IfWinExist, IfWinActive, SetTitleMatchMode, DetectHiddenWindows

示例

Run, notepad.exe
WinWaitActive, Untitled - Notepad, , 2
if ErrorLevel
{
    MsgBox, WinWait timed out.
    return
}
else
    WinMinimize  ; 最小化 WinWaitActive 找到的窗口。


WinWaitClose

等待匹配指定条件的窗口被关闭。

WinWaitClose [, WinTitle, WinText, Seconds, ExcludeTitle, ExcludeText]

参数

WinTitle | 目标窗口的标题或标题中的部分文字（匹配模式由 SetTitleMatchMode 决定）。如果省略其它 3 个窗口参数，默认目标是 上一次匹配窗口 。要用窗口的 class 名进行匹配，使用 ahk_class 精确 class 名（Window Spy 中可以显示 class 名）。要用窗口的 进程标识符（PID）进行匹配，使用 ahk_pid %PID变量% 。要用 窗口组 ，使用 ahk_group 组名 。要用窗口的 唯一 ID 进行匹配，使用 ahk_id %ID变量% 。要减小检测范围，使用 多重条件 ，例如：My File.txt ahk_class Notepad
WinText | 如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 DetectHiddenText 设置为 ON 的时候才能检测到。
Seconds | 超时时间。超时后将不再等待并且设置 ErrorLevel/错误等级 为 1 。留空表示无限等待。指定 0 等同于 0.5 。这个参数可以一个 表达式 。
ExcludeTitle | 标题中包含该参数指定的文字的窗口将被除外。
ExcludeText | 文本元素中包含该参数指定的文字的窗口将被除外。

ErrorLevel

超时以后 ErrorLevel/错误等级 为 1 ，否则为 0 。

注意

没有匹配窗口的时候，命令会立即设置 ErrorLevel/错误等级 为 0 ，然后让脚本继续执行，而不必再等待 Seconds 参数中指定的时间。

当该命令处于等待状态的时候，仍然可以通过 快捷键 ，自定义菜单 ，或 定时器 来启动新的 线程 。

如果其它的 线程 在该命令等待的时候改变了参数中所使用到的变量的值，该命令会无视这些改变 —— 它仍然会使用这些变量在开始等待的时候的值。

窗口的标题和窗口中的文字是大小写敏感的。要检测隐藏窗口，必须打开 DetectHiddenWindows 。

相关命令

WinClose, WinWait, WinWaitActive, IfWinExist, IfWinActive, Process, SetTitleMatchMode, DetectHiddenWindows

示例

Run, notepad.exe
WinWait, Untitled - Notepad
WinWaitClose  ; 等待 WinWait 找到的窗口被关闭。
MsgBox, Notepad is now closed.


#AllowSameLineComments

仅适用于 AutoIt v2 (.aut) 脚本: 允许注释和命令在同一行.

#AllowSameLineComments

在任何 AutoIt v2 (.aut) 脚本的 顶部 指定此指令会启用同行注释, 出于兼容性的考虑正常情况下这个功能是禁用的. 如果在脚本顶部外的其他地方使用, 那么在使用此指令后才支持同行注释.

示例

#AllowSameLineComments
Sleep, 1  ; 此注释是同行注释.


#ClipboardTimeout

更改首次尝试访问剪贴板失败后需要间隔的时间。

#ClipboardTimeout Milliseconds

参数

Milliseconds 以毫秒为单位的间歇时间。指定为 -1 使其保持不停地访问剪贴板。指定为 0 使其只尝试一次。不包含该指令的脚本将在 1000 ms 后超时。

注意

一些应用程序使剪贴板长时间打开，可能是要读写大量的数据。这种情况下，增加此设置的值会使脚本在放弃并显示出错信息前长时间处于等待状态。

该设置应用于所有的剪贴板操作，最简单的比如下面这个例子:
Var = %Clipboard%
Clipboard = 新文本

每当脚本处于等待剪贴板的内容成为变量时，新的线程 不能被启动并且定时器也不会运行。不过，如果用户按了热键，选择了一个自定义菜单项或者执行了 GUI 操作比如点击按钮，那么这些事件会先被缓存起来留到之后处理；换句话说，子进程被推迟到剪贴板内容成为变量后才执行。

该指令也会导致首次访问失败后重新尝试读取剪贴板数据 (在先前的版本中，只有打开的剪贴板才会重新尝试访问)。

相关命令

Clipboard, Thread

示例

#ClipboardTimeout 2000


#CommentFlag

把脚本的注解符号从分号改为其他字符串。

#CommentFlag NewString

参数

NewString 一个或多个字符可以被用作新的注解标识。最多可指定 15 个字符。

注意

默认的注解标识是分号 (;) 。

注解标识用来表示紧随其后的文本不应该被脚本执行 (当脚本启动时注解不被加载，因此它们不影响执行)。

注解标识出现在命令的同一行上不被视为表示注解，除非它的左边至少有一个空格或 tab 。例如：

MsgBox, Test1 ; 这是一个注解。
MsgBox, Test2; 这不是一个注解并且将被 MsgBox 命令显示。

相关命令

#EscapeChar

示例

#CommentFlag //  ; 改为 C++ 注解样式。


#ErrorStdOut

让脚本启动时将任何语法错误发送到标准输出而不是显示错误对话框。

#ErrorStdOut

它允许像 Textpad, SciTE, Crimson 和 EditPlus 这样的优秀编辑器在遇上语法错误时跳转到出错行。由于 #ErrorStdOut 指令必须加进每个脚本，通常设置你的编辑器从而在启动任何 AutoHotkey 脚本时使用命令行选项 /ErrorStdOut 会更好(详见更下面的设置说明)。

虽然语法错误被发送到标准输出(stdout)，但不会直接显示在命令提示符中。然而，这些输出可以通过管道或者重定向来获得。例如:

"C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "My Script.ahk" |more
"C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "My Script.ahk" >"Syntax-Error Log.txt"

你也可以直接传送输出信息到剪切板，通过下载 cb.zip (4 KB)，然后按照下例操作:

"C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "My Script.ahk" |cb.exe

特定编辑器的设置:

EditPlus:
从菜单栏中选择 Tools > Configure User Tools。
点击按钮: Add Tool > Program
Menu Text: 你自己定
Command: C:\Program Files\AutoHotkey\AutoHotkey.exe
Argument: /ErrorStdOut "$(FilePath)"
Initial directory: $(FileDir)
Capture output: Yes

TextPad:
从菜单栏中选择 Configure > Preferences。
展开 Tools 选项。
点击 Add 按钮并选择 "Program"。
复制然后粘贴 (调整为你的路径): C:\Windows\System32\cmd.exe -- 然后点击 OK。
在列表框中快速点击三次新添加的项目 (cmd.exe)，重命名为你定的名称(例如 Launch Script)。
点击应用。
在左边的目录树选择新项目并键入如下信息:
Command (应该已经填过): cmd.exe (或者它的完整路径)
Parameters (如果有必要的话调整为你的路径): /c ""C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "$File""
Initial folder: $FileDir
勾上如下选框: 1) Run minimized; 2) Capture output。
点击 OK。新添加的项目现在应该已经在 Tools 菜单中了。

相关命令

FileAppend (同样可以发送文本到标准输出)

示例

#ErrorStdOut


#EscapeChar (and explanation of escape sequences)

#EscapeChar (以及转义顺序的解释)

改变脚本的转义符号 (例如重音符与反斜线)。

#EscapeChar NewChar

参数

NewChar 指定单个字符。

注意

转义字符用来表明其后紧跟的字符应该被解释地与它通常的含义不同。

AutoIt v2 (.aut) 脚本默认的转义符号是反斜线 (\)。对所有其它的文件扩展名，包括所有编译的脚本，默认的转义符号是重音符/反引号 (`)。当一个 .aut 脚本 自动转换 为一个 .ahk 脚本时，反斜线转义符号将被全部替换为重音符。

转义顺序 (当重音符是转义符号时)

输入这些 | 来得到这些
`, | , (原义的逗号)。注意: 在命令最后一个参数里出现的逗号不需要被转义，因为程序知道将它们视作原义。同样也适用于 MsgBox 命令的所有参数，因为它有智能的逗号处理功能。
`% | % (原义的百分号)
`` | ` (原义的重音符；也就是两个连续的转义字符结果为单个原义的字符)
`; | ; (原义的分号)。注意: 这只有在分号的左边有一个空格或 tab 时才有必要。如果没有，它会被正确地识别而不用转义。
`:: | :: (一对原义的冒号)。在 v1.0.40+ 版本之后，它不再需要被转义。
`n | 新起一行 (换行/LF)
`r | 回车 (CR)
`b | 退格
`t | tab (很典型的水平的移位)
`v | 垂直的 tab -- 相当于 Ascii 编码的值 11。它也可以在一些应用程序中通过键入 Control+K 来显示。
`a | alert (警告/bell) -- 相当于 Ascii 编码的值 7。它也可以在一些应用程序中通过键入 Control+G 来显示。
`f | formfeed(进纸) -- 相当于 Ascii 编码的值 12。它也可以在一些应用程序中通过键入 Control+L 来显示。
Send | 当 Send 命令或热字符串以它们默认的 (非 raw) 模式使用时，像 {}^!+# 这样的字符有特殊的含义。因此，在这些情况下要使用它们的原义就得将它们围在大括号内。例如：Send {^}{!}{{}
"" | 在表达式内，一个原义的字符串内的两个连续的引号解析为单个原义的引号。例如：Var := "The color ""red"" was found."

相关命令

同样存在下面这些极其少用的指令；它们的用法在这些例子里表明：

#DerefChar #  ; 将引用符号一般默认的 % 改为 # 。
#Delimiter /  ; 将分隔符号一般默认的逗号改为 / 。

示例

#EscapeChar \  ;将其改变为反斜杠来代替默认的重音符 (`)。


#MaxMem

设置每个变量可使用的最大内存兆数。

#MaxMem Megabytes

参数

Megabytes 每个变量可用的内存兆数。大于 4095 的值将视为 4095。小于 1 的值将视为 1。

注意

如果脚本中没有指定这个指令，它将设为 64。

限制每个变量的大小是为了防止错误的脚本耗光系统所有的可用内存。提高或降低该限制值不会影响脚本的性能，也不会改变脚本实际使用的内存量(WinGetText 和 ControlGetText 命令的情况除外，增加 #MaxMem 的值将使其能获取更多的文本)。

此设置是全局性的，也就是说它只需要指定一次(在脚本的任何地方)就会影响整个脚本。

此设置仅仅限制了变量的自动扩充行为。它不影响 VarSetCapacity。

相关命令

VarSetCapacity, Variables, Sort, WinGetText, ControlGetText, #MaxThreads

示例

#MaxMem 256  ;允许每个变量最多使用 256 MB 内存。


#NoEnv

#NoEnv [v1.0.43.08+]

避免检查空变量是否为环境变量(推荐所有新建脚本使用)。

#NoEnv

指定 #NoEnv 这行在脚本的任意位置，防止空变量被作为潜在的环境变量来查找。例如：

#NoEnv
MsgBox %WinDir%

上面的不检索 "WinDir" 环境变量(尽管通过在脚本顶部附近加入 WinDir := A_WinDir 能解决)。

指定 #NoEnv 是推荐所有新建脚本使用的，因为：

  1. 当空变量被用在一个表达式或命令里的时候，它显著地改善性能。其同样改善 DllCall 的性能，当未引用的变量类型被使用的时候(例如 int 对 "int")。
  2. 它防止由于那些环境变量的名称意外地被脚本使用的变量名匹配而造成的错误。
  3. 将来的AutoHotkey版本可能让此行为模式作为默认。

为了有助于改善切换到 #NoEnv 的情况，内置的 Comspec 和 ProgramFiles 变量被添加进来。它们与相应的环境变量包含同样的字串。

当 #NoEnv 起作用时，脚本应该使用 EnvGet 来找回环境变量，或使用内置的像 A_WinDir 这类变量。

相关命令

EnvGet, Comspec, ProgramFiles, A_WinDir


#Persistent

让脚本持久地运行(就是说，直到用户关闭它或者遇到了 ExitApp 命令)。

#Persistent

如果这个指令出现在脚本的任意位置，那么脚本在自动执行部分(脚本顶部)完成后会保持运行。当一个脚本包含 定时器 和/或 自定义菜单项，但没有 热键 、热字符串 或者没有使用任何的 OnMessage() 或 Gui 时，它将非常有用处。

如果这个指令被添加到一个已经存在的脚本，你可能需要把一些或全部出现的 Exit 修改成 ExitApp。这是因为 Exit 不能终止一个持续的脚本；它只能终止 当前的线程。

在 v1.0.16 及之后版本，此指令也让一个脚本成为了 single-instance(单独实例)。要取代它或改变单独实例的运作方式，请看 #SingleInstance。

相关命令

#SingleInstance, SetTimer, Menu, Exit, ExitApp

示例

#Persistent


AutoHotkey

中文帮助的翻译和更新

这里仅涉及中文帮助的相关情况, 想了解对 AutoHotkey 有贡献的人员名单, 请参见 致谢页面.

关于中文帮助

AutoHotkey_L 是主要由 Lexikos 维护的一个 AutoHotkey 定制版本. Chris Mallett 于 2010年10月认可了 AutoHotkey_L 的继承地位, 并改称原版本为 AutoHotkey Basic.

此中文帮助基于 AutoHotkey_L 1.1.0.0 的英文帮助, 使用提示:

  • 中文帮助总是滞后于英文帮助, 所以最新的帮助请以英文帮助为准.
  • 这里的在线帮助将持续进行更新, 所以通常都比离线手册要新.
  • 由于一般只在大量更新时才集成离线手册供下载, 若您需要离线帮助, 请至 中文论坛 下载.
  • 学习使用 AutoHotkey 时帮助是不错的参考手册, 希望大家用好.
  • 欢迎在 中文论坛 提出对帮助的意见和建议, 我将对其中的错误积极进行修正, 让我们一起努力把帮助做的越来越好!

翻译人员列表

从中文论坛组织帮助的翻译开始, 经历了坎坷曲折, 并曾一度停滞, 直至今日中文帮助基本成形, 期间离不开许多人的默默支持和付出, 这里列出参与帮助翻译的人员名单 (不分先后):

  • helfee
  • wanghom.lee
  • wz520
  • xiaohuilucky
  • 第八单元
  • lskxt
  • wsbd008
  • handt
  • 甲壳虫
  • wanggang999
  • bu45gande
  • 单菜子
  • whynotwxg
  • 8thunit
  • tcgbp
  • Kookee
  • lastmore
  • yugi
  • xbeta
  • okey3m
  • BLooM2
  • baggio1987
  • Xiangee
  • 天堂之门
  • hsudatalks
  • 惊幻
  • lwjiee

还包括我, 如果其中有遗漏, 请联系我: amnesiac10@hotmail.com.

特别感谢

  • Yoken, 翻译了 AutoHotkey 1.0.36.06 部分帮助.
  • 彪悍的小玄和卢世杰, 在我翻译过程中给予我极大帮助.

最后, 感谢所有使用中文帮助的人, 并感谢对我提出批评和建议的人, 我将做得更好!


高级快捷键功能- 鼠标和键盘快捷键

高级快捷键功能

注意：下述功能中，多数需要 Windows NT/2000/XP 或更高版本操作系统。

让最容易按的键变得更有用：有些键占了好位置，易于按下，但却不常用。为什么不改造它们呢？比如，如果你的右 ALT 键很不常用，则不妨为它指定一个常用的操作：

RAlt::
MsgBox 你按下了右 ALT 键。
return

另外，也可以把右 Alt 作为一个“引导键”，再加上一个其他键组成快捷键。这样的好处是不会占用右Alt的本来功能。在下面的例子中，右Alt 就成为了引导键，和j一起，实现了切换窗口的功能。作为引导键，它可以和任何其他键一起按下发挥作用。而没有其他键按下时，它仍然能发挥自己的作用（如上面的例子）：

RAlt & j::AltTab

修饰键不再局限于 CTRL、ALT、SHIFT 和 WIN：你可以使用任意两个按键或鼠标按键组成自定义快捷键。例如，按住小键盘数字0，再按下数字1 就形成了一个快捷键（写为：Numpad0 & Numpad1::）；按住 CapsLock，再按下另一个键或用鼠标点击右键（写为：CapsLock & RButton::）。这种情况下，CapsLock 键的状态（大写/小写）不会发生改变。详见 自定义组合键。

用鼠标滚轮（或其他键）代替 Alt-Tab：点击鼠标滚轮，就可以显示窗口选择菜单；上下滚动，就在各窗口图标进行选择；选中之后再次按下滚轮，则切换到选中的窗口。并且，在Alt-Tab菜单不出现时，鼠标滚轮的正常功能仍然可以使用。脚本：

MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab

让按键变成鼠标键，或者在按住某个键或鼠标键时，让计算机重复某个动作。示例见 remapping page。

让快捷键区分情境：可以让最易使用的快捷键在不同的程序中，调用不同的最常用功能。下面的脚本可以让右Ctrl键在记事本和计算器中，分别实现不同功能：

#IfWinActive ahk_class Notepad
RControl::WinMenuSelectItem, , , 文件, 保存  ; 在记事本中保存当前文件

#IfWinActive ahk_class SciCalc
RControl::Send, ^c!{tab}^v  ; 在计算器中，把计算结果复制到原来的活动窗口

详见 #IfWinActive。

热字符串：实现缩写功能。无须经过任何培训，就可以写出这样的脚本。例如，下述脚本将自动把 ceo, cfo, 和 btw 替换成完整拼写：（注：暂不支持汉字）

::ceo::Chief Executive Officer
::cfo::Chief Financial Officer
::btw::by the way

（更详内容）

如果你对游戏感兴趣：

  • 别人拼血流汗时，你只需动一下手指，就能发出一系列复杂操作。因为常用操作可以定义到几乎任意键上，包括单一的字母键、方向键、数字键，甚至是特殊键（CTRL/ALT/WIN/SHIFT）。
  • 为鼠标键，包括滚轮（MButton）、上下左右滚动（WheelUp、WheelDown、WheelLeft 和 WheelRight）进行快捷键定义。还可以将鼠标键盘结合起来。如，按住ctrl点击右键可写为 ^RButton::
  • 创建“穿越型”快捷键。例如，点击鼠标左键，一方面触发快捷键动作，另一方面，仍和往常一样，游戏也接收到了左键单击（写为：~LButton::）。
  • 使用诸如 PixelSearch（像素搜索）、PixelGetColor（取得像素颜色）、ImageSearch（搜索图像）这样的命令来实现自动操作。
  • 可以选择使用 keyboard hook来实现快捷键。在游戏占用较多CPU资源时，此方法比其他方法的响应性更好。它还能覆盖游戏软件本身对哪些键可以映射的限制。

更多信息，请见 Hotkeys 章节。


Last Found Window

“最近找到”的窗口

这是被 IfWin[Not]Exist, IfWin[Not]Active, WinWait[Not]Active 或 WinWait 命令最近找到的窗口。由于不需要在各种窗口命令里再重复目标窗口的 WinTitle 和 WinText 参数，所以它可以使脚本更易于创建和维护。此外，因为在首次找到目标窗口后不需要再将其搜寻一遍，所以脚本执行得更好。

所有窗口命令都可以使用“最近找到”的窗口，除了 WinWait, WinActivateBottom 和 GroupAdd。要使用它的话，只需省略掉全部的四个窗口参数(WinTitle, WinText, ExcludeTitle 和 ExcludeText)。

每个线程都保留了它自有的“最近找到”窗口的值，就是说如果当前线程被另一个线程打断，那么在原来的线程恢复时，它仍将保持它原本的“最近找到”窗口的值，而不是那个中断它的线程的值。

如果最近找到的窗口是一个隐藏的 Gui 窗口，那么即使在 DetectHiddenWindows 处于 Off 状态时，它也能被使用。这常与"Gui +LastFound"一起使用。

示例

Run Notepad
WinWait 无标题 - 记事本
WinActivate  ;使用最近找到的窗口。

IfWinExist, 无标题 - 记事本
{
    WinActivate  ;自动地使用上面找到的窗口。
    WinMaximize  ;同上
    Send, Some text.{Enter}
    return
}

IfWinNotExist, 计算器
    return
else
{
    WinActivate  ;上面的 "IfWinNotExist" 也为我们设置了“最近找到”的窗口。
    WinMove, 40, 40  ;将它移动到一个新的位置。
    return
}

WinTitle 参数的其他用法

如果有多种窗口符合一个窗口命令比如 WinMove 的 WinTitle/Text 条件，那么在窗口堆层次中位于其它窗口上面的那个窗口将被使用。例如，如果激活的/最前面的窗口匹配条件，就会用它，即使它下面还有其它匹配的窗口。

激活的窗口 (A): 几乎所有的窗口命令都能被告知对激活的窗口进行操作，只要指定它们的 WinTitle 参数为字母 A 并且省略掉 WinText, ExcludeTitle 和 ExcludeText。在下例中，Win+上箭头 变成一个最大化当前激活窗口的热键: #Up::WinMaximize A

窗口类 (ahk_class): 通过 Window Spy 显示的或者由 WinGetClass 获得的类名都能使所有的窗口命令对一个窗口类进行操作。在下例中，一个分割视图的资源管理器窗口（译注：即左侧为文件夹树）将被激活: WinActivate ahk_class ExploreWClass

唯一 ID/HWND (ahk_id): 通过唯一 ID 编号，所有的窗口命令都能对特定的窗口或者控件进行操作。例如：WinActivate ahk_id %VarContainingID%。一个窗口的 ID 一般通过 WinExist() 或者 WinGet 来取得。一个控件的 ID 一般通过 ControlGet Hwnd, MouseGetPos 或 DllCall 来取得。而且，即使控件是隐藏的，ahk_id 也将对它们进行操作；就是说，DetectHiddenWindows 的设置无关紧要。

进程 ID (ahk_pid): 所有的窗口命令都能对属于一个进程标识符(PID)的窗口进行操作。例如，WinClose ahk_pid %VarContainingPID% 会关闭那个进程的最上层窗口。PID 能通过 WinGet 或 Run 或 Process 来获得。

窗口组 (ahk_group): 通过给 WinTitle 参数指定 ahk_group MyGroupName，所有的窗口命令都能对属于一个窗口组的窗口进行操作。WinMinimize, WinMaximize, WinRestore, WinHide, WinShow, WinClose 和 WinKill 命令会对组内所有的窗口起作用。相比之下，其它窗口命令例如 WinActivate 和 IfWinExist 将只对组内最上层的窗口进行操作。

多重条件: 和上面段落中的 ahk_group (其扩大了搜索)相比，只要在 WinTitle 参数中指定多个条件就能缩小搜索范围。在下例中，脚本等待标题包含 My File.txt 以及类是 Notepad 的窗口出现:

WinWait My File.txt ahk_class Notepad
WinActivate  ;激活它找到的窗口。

当使用这方法时，应该首先列出标题的文字(如果有的话就需要)，后跟一个或多个附加的条件。超出首个的条件必须精确地用一个空格或者 tab 来与前一个分开(任何其他的空格或 tab 将被看作前一个条件的一部分)。


License

Software License

GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.

We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and
modification follow.

GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.

c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS


AutoHotkey Tutorial - Launch a program or document (continued)

指南 - 启动一个程序或文档 (续)

要使一个程序或文档最大化、最小化或隐藏地启动，考虑下面的 hotkey (热键) 它指定 Win+Z 热键来启动两个记事本实例，第一个是最大化的，而第二个是最小化的：

#z::
Run, Notepad, , max
Run, Notepad, , min
return

要使一个程序使用一个指定的文件夹作为它的工作目录，考虑 这个创建一个命令提示符窗口到指定目录的 Win+C 热键：

#c::Run, %comspec% /k, C:\My Documents

在上面的例子中，comspec 是一个在一个典型的系统中指向 C:\Windows\system32\cmd.exe 的内置 variable (变量)。

想要传递参数，直接把它们添加到程序或文档的名字后面——正如这些例子：

Run, %comspec% /c dir >"Output File.txt", C:\My Documents
Run, Notepad.exe "C:\My Documents\Address List.txt"
Run, "%A_AhkPath%" "C:\Scripts\Test Script.ahk" param1 "param2 with spaces" param3

在上面的第二个和第三个例子中， 带有空格的参数被放在引号里，这是一般来说最可靠的做法。相比之下，即使工作目录包含空格，也不需要被放在引号里，正如上面的第一个例子。

某些特定的被称为 system verbs (系统保留字) 的词语也是被支持。下面的第一个例子为指定的文件打开资源管理器的属性对话框 。第二个例子打印指定的文档。

Run, properties "C:\Address List.txt"
Run, print "C:\Address List.txt"

最后，RunWait设定内置的 ErrorLevel 变量为它打开的那个程序的退出代码(它还会等侯程序终止并关闭)。例如，由于 cmd.exe 在表明有问题发生了，故下面的例子会显示一个非零的ErrorLevel ：

RunWait, %comspec% /c dir c:\NonExistent.txt, , hide
MsgBox, %ErrorLevel%

更多关于启动程序和文档的内容，请看 Run/RunWait。

返回到指南目录


ObjAddRef() / ObjRelease()

ObjAddRef() / ObjRelease() [AHK_L 53+]

增加或减少对象的引用数.

ObjAddRef(Ptr)
ObjRelease(Ptr)

参数

Ptr 一种非托管的对象指针或 COM 接口指针.

返回值

这两个函数返回新的引用计数. 此值应该 仅 用于调试目的.

相关

尽管后面的文章讨论了适用于 COM 的引用计算, 但其中掩饰了通常也适用于 AutoHotkey 对象的重要概念和规则: IUnknown::AddRef, IUnknown::Release, 引用计数规则.

示例

参见 ComObjConnect.

obj := Object()

; The following two lines are equivalent:
ptr1 := Object(obj) ptr2 := ObjectToPointer(obj) ObjectToPointer(obj) { if !IsObject(obj) return "" ptr := &obj ObjAddRef(ptr) return ptr }

; Each pointer retrieved via Object() or ObjectToPointer() must be manually released ; to allow the object to be eventually freed and any memory used by it reclaimed.
ObjRelease(ptr2) ObjRelease(ptr1)


AutoHotkey Acknowledgements

鸣谢

除了已经 提到的 AutoIt 作者，此外还有：

Robert Yaklin: 不知疲倦地测试大量孤立 bug ，一个伟大的第一版安装者，以及对命令应该如何工作提出过极好的建议 :)

Jason Payam Ahdoot: 提供浮点数运算支持的建议和描述。

Jay D. Novak: 发现很多 Send 命令、Capslock 和 热键修饰符 在 Win9x 下的问题；并慷慨地分享了他大量的代码以及在热键、热字符串、钩子应用和输入加速方面的学问。

Rajat: 为原 AHK 图标制作了时尚的替换物；一个伟大的产品标志；制作了 TextPad 的自定义语法；发现注册表命令和 AutoIt v2 的兼容性的一些 bug ；制作了 SmartGUI Creator ；以及很多其它事情。

Beardboy: 为修补 GetKeyState 和 Send 命令做了 NT4 的测试工作；在论坛上提供了大量的帮助；以及很多建议和 bug 报告。

Gregory F. Hogg of Hogg's Software: 编写了 SysGet 命令中多显示器支持的源代码。

Aurelian Maga: 编写了 ImageSearch 和更快的 PixelSearch 的源代码。

Joost Mulders: 他的源代码为 表达式 提供了基础。

Laszlo Hars: 提供了关于数据结构和算法方面的建议，有利于极大地加速数组和动态变量。

Marcus Sonntag (Ultra): 研究、设计、编码并且测试了 DllCall 。

Gena Shimanovich: 协助编码和调试；并提供了一些在未来的特性上可能作为基础的高级脚本原型。

Eric Morin (numEric): 提出了数学方面的建议；在 OnMessage 、浮点数运算以及鼠标移动方面，做了坚定的调试工作；以及对整体品质的改善。

Philip Hazel: 提供 Perl-Compatible Regular Expressions (PCRE) (兼容Perl的正则表达式)。

Titan: 提供了在 autohotkey.net 的社区托管，创造了很多有用的脚本和类库，在论坛上彩色显示代码注解的 JavaScript 以及许多其它事情。

Philippe Lhoste (PhiLho): 在论坛上不知疲劳的 moderation(温和) 和支持，测试并建议 RegEx ，语法和设计理念，以及其它很多事情。

John Biederman: 显著地改善了文档的演示和人类工程学。

Jonathan Rennison (JGR): 发展了 RegisterCallback() ，并提供了有益的建议。

Steve Gray (Lexikos): 发展了动态函数调用及其它新的功能；分析并修补 bug ；对论坛上成百上千单独的游客提供宝贵的支持和意见。

同样对其他所有提交 bug 报告或建议的人：谢谢！


Arrays

关联数组 [AHK_L 31+]

自包含关联数组可以调用 Object() 创建. 例如:

; 创建数组后, 初始为空:
Array := Object()

; 写入数据到数组:
Loop, Read, C:\Guest List.txt ; 此循环获取文件中的每行, 一次一行.
{
    Array.Insert(A_LoopReadLine) ; 添加此行到数组中.
}

; 从数组中读取:
; Loop % Array.MaxIndex()   ; 较传统的方式.
for index, element in Array ; 在大多数情况下建议使用的方式.
{
    ; 使用 "Loop", 索引必须是连续的数字, 从 1 到
    ; 数组中元素的个数 (或者必须在循环中进行计算).
    ; MsgBox % "Element number " . A_Index . " is " . Array[A_Index]

    ; 使用 "for", 索引 (或 "键") 和其关联值都
    ; 提供了, 并且所以可以是 *任意* 您选择的值.
    MsgBox % "Element number " . index . " is " . element
}

此例仅演示了 对象 提供的 功能 的一个小子集. 可以设置, 获取, 插入, 移除和枚举项目. 除了数字, 还可以把字符串和对象作为键使用. 对象可以作为值存储到其他对象中并且可以作为函数参数或返回值传递. 对象还可以用新功能进行 扩展.

尽管 Insert() 和枚举数有它们的用途, 不过一些用户可能会发现使用它们比用更传统的方式容易些:

  ; 每个数组在使用前必须进行初始化:
  Array := Object()

; Array%j% := A_LoopField
  Array[j] := A_LoopField

; Array%j%_%k% := A_LoopReadLine
  Array[j, k] := A_LoopReadLine

  ArrayCount := 0
  Loop, Read, C:\Guest List.txt
  {
      ArrayCount += 1
    ; Array%ArrayCount% := A_LoopReadLine
      Array[ArrayCount] := A_LoopReadLine
  }

  Loop %ArrayCount%
  {
    ; element := Array%A_Index%
      element := Array[A_Index]
    ; MsgBox % "Element number " . A_Index . " is " . Array%A_Index%
      MsgBox % "Element number " . A_Index . " is " . Array[A_Index]
  }

为了方便而使用 ArrayCount 变量保存数组元素个数, 但可以通过 Array.Count := n 保存到数组自身中, 或使用 Array._MaxIndex() 代替它. 如果希望使用 1 之外的其他值作为起始索引, 还可以使用 Array._MinIndex().

伪数组

伪数组主要是概念上的: 每个数组实际上只是一系列连续编号的 变量 或 函数 的集合, 它们每个被视为数组的 元素. AutoHotkey 不会以任何方式把这些元素链接在一起.

除了如 StringSplit 和 "WinGet List" 这样的数组创建命令外, 任何接受 OutputVar 或把值赋给变量的命令都可以用来创建数组. 最简单的例子是 赋值运算符 (:=), 如下所示:

Array%j% := A_LoopField

通过在索引间使用您选择的分隔符可以创建多维数组. 例如:

Array%j%_%k% := A_LoopReadLine

下面的例子演示了如何创建和访问数组, 这里是从文本文件获取一系列的名称:

; 写入数组到数组:
ArrayCount = 0
Loop, Read, C:\Guest List.txt   ; 此循环获取文件中的每行, 一次一行.
{
    ArrayCount += 1  ; 记录数组中的项目数.
    Array%ArrayCount% := A_LoopReadLine  ; 把此行保存到数组中的下一个元素.
}

; 从数组中读取:
Loop %ArrayCount%
{
    ; 下一行使用 := 运算符获取数组元素:
    element := Array%A_Index%  ; A_Index 是内置变量.
    ; 可选地, 您可以使用 "% " 前缀让 MsgBox 或其他一些命令的参数中 可以使用表达式:
    MsgBox % "Element number " . A_Index . " is " . Array%A_Index%
}

一个和数组有关的概念是使用 NumPut() 和 NumGet() 储存/获取一批二进制格式的数字. 这在对性能和/或内存占用有要求时比较有用.


Clipboard, ClipboardAll, 以及 OnClipboardChange

Clipboard 是一个内置变量，存储了当前 Windows 剪贴板中可以以文本形式表现的内容。相应的，ClipboardAll 存储了剪贴板中的所有内容，例如图片以及带格式的文本。

Clipboard 中的每行文本通常都以回车和换行(CR+LF)结尾，在脚本中可表示为 `r`n。文件(例如那些用 Control-C 从资源管理器中复制的文件)是用文本形式表现的：每当在脚本中引用 Clipboard 变量时，它们都会被自动转换为它们的文件名称(带完整路径)。要逐个提取文件的话，参照下例：

Loop, parse, clipboard, `n, `r
{
 MsgBox, 4, , 第 %A_Index% 个文件是 %A_LoopField%。`n`n是否继续?
 IfMsgBox, No, break
}

要将文件名按字母顺序排列，使用 Sort 命令。要将剪贴板上的文件名写入文件，可用 FileAppend, %clipboard%`r`n, C:\My File.txt。要改变让脚本试着保持打开剪贴板的这个时间 -- 例如在另一个程序使用剪贴板时 -- 请用 #ClipboardTimeOut 命令。

基础示例：
clipboard = my text ;给予剪贴板全新的内容。
clipboard = ;清空剪贴板。
clipboard = %clipboard% ;将任何复制的文件、HTML 或者其它带格式的文本转换为纯文本。
clipboard = %clipboard% 添加的文本。 ;在剪贴板中追加些文本。
StringReplace, clipboard, clipboard, ABC, DEF, All ;将剪贴板中所有的 ABC 替换为 DEF (同时也将剪贴板中的内容转换为纯文本)。

使用 ClipWait 命令改善脚本的可靠性：

clipboard = ;首先清空剪贴板，使 ClipWait 命令能检测到文本何时被复制到了剪贴板中。
Send ^c
ClipWait ;等待文本被复制到剪贴板中。
MsgBox Control-C 复制了下列内容到剪贴板中：`n`n%clipboard%

ClipboardAll (存储以及恢复剪贴板的所有内容)

ClipboardAll 存储了剪贴板中的所有内容(例如图片以及带格式的文本)。它最常用来存储剪贴板的内容以便脚本为了某个操作能临时使用剪贴板。当这个操作结束时，脚本再像下面这样将剪贴板原本的内容恢复：

ClipSaved := ClipboardAll ;将剪贴板的所有内容存储到你选的一个变量里。
;... 这里放临时使用剪贴板的脚本，例如用转换 Unicode 命令粘贴 Unicode 编码的文本...
Clipboard := ClipSaved ;恢复剪贴板原本的内容。注意使用的是 Clipboard (不是 ClipboardAll)。
ClipSaved = ;释放内存以防原来剪贴板里是巨大的内容。

ClipboardAll 中的内容也可以存成一个文件(在这种模式下，FileAppend 命令会覆盖已存在的文件)：
FileAppend, %ClipboardAll%, C:\Company Logo.clip ; 文件扩展名无关紧要。

要在之后将文件重新读取回剪贴板(或读取到一个变量中)，参照下例：
FileRead, Clipboard, *c C:\Company Logo.clip ;注意必须在文件名之前使用 *c。

注意

在上面所描述的情况之外调用 ClipboardAll 都会返回空值。另外，ClipboardAll 不能写在逗号分隔的表达式中；也就是说，它必须独占一行，例如 ClipSaved := ClipboardAll。

赋值了 ClipboardAll 的变量将用二进制格式来存储数据，因此使用 MsgBox 或类似命令查看其内容时会显示乱码。并且，修改二进制变量的内容(例如使用 StringReplace 命令)会将其还原为普通变量，结果会丢失其存储的剪贴板数据。在 v1.0.46 及之后的版本中，二进制变量可以通过数值传递给函数(之前它们只能使用引用传递的方式)。

如果 ClipboardAll 不能获取剪贴板中的一个或多个对象(格式化的)，那么它们将被省略，而所有剩余的对象仍然会被存储。获取行为会根据 #ClipboardTimeOut 命令的设定再次尝试(而不是只尝试一次)。

一个包含了剪贴板数据的变量可以被复制到另一个变量中，例如：ClipSaved2 := ClipSaved

ClipWait 命令可以用来检测剪贴板何时有内容(包括非文本数据也可选)。

StringLen 命令可以用来显示赋值了 ClipboardAll 的变量的总大小。

赋值了 ClipboardAll 的变量可以使用 <> 和 = 运算符来相互比较(但不能直接与 ClipboardAll 进行比较)。在下例中，首先检查每个变量的大小。如果根据大小不能进行判断，就将两个变量的内容进行比较：

if ClipSaved1 <> %ClipSaved2% ;这里必须使用老式的 IF 语句，不能使用表达式。
MsgBox 两个变量中存储的剪贴板的内容不相同。

将 ClipboardAll 的内容存储到一个变量时，变量大小不受 #MaxMem 命令设置的最大内存限制。

一个存储了剪贴板内容的文件由四个字节的格式类型，接着四个字节的数据块大小，接着那个格式的数据块而组成。如果剪贴板包含多种格式的内容(大部分时候都是这样)，前面所述的三个组成部分会重复下去，直到存储了所有的格式。文件最后以一个四个字节的 0 格式类型结束。

已知局限：当剪贴板中有 Microsoft Excel 单元格的内容时，获取 ClipboardAll 会导致 Excel 弹出 "找不到打印机" 的对话框。

OnClipboardChange

如果存在名称为 OnClipboardChange 的标签，那么当任何程序(甚至是脚本自身)更改了剪贴板的内容的时候，该标签下的脚本都会自动执行。在脚本加载的时候该标签同样会执行一次。

内置变量 A_EventInfo 包含：
0 如果剪贴板当前为空；
1 如果剪贴板中的内容能够以文本形式表达(包括从资源管理器中复制的文件)；
2 如果整个剪贴板里是非文本内容，例如一幅图片。

下面的例子就是一个可用的脚本。它会在剪贴板内容每次改变的时候短暂地显示一个提示。

#Persistent
return

OnClipboardChange:
ToolTip 剪贴板中的数据类型为：%A_EventInfo%
Sleep 1000
ToolTip ;关闭提示。
return

如果正在执行 OnClipboardChange 标签下的脚本时剪贴板中的内容发生了变化，那么那个提示事件将会丢失。如果需要避免这种情况，在 OnClipboardChange 标签下的首行使用 Critical。不过，在 OnClipboardChange 线程运行这个时段产生的其它线程(例如按了个热键)也会被缓冲或延迟。

如果脚本本身更改了剪贴板的内容，则脚本中的 OnClipboardChange 标签往往不会立即执行；就是说，更改剪贴板的命令的下一行命令很可能会提前执行。要强制让 OnClipboardChange 标签立即执行的话，可以在更改了剪贴板之后添加一个短暂的延时例如 Sleep 20。

相关内容：OnExit, OnMessage(), RegisterCallback()


CLSID List (Windows Class Identifiers)

CLSID 列表 (Windows 类标识符)

操作系统内某些特殊的文件夹是通过唯一的字符串来识别的。这些字符串中的一些字串可以被 FileSelectFile, FileSelectFolder 和 Run 使用。例如:

FileSelectFile, OutputVar,, ::{645ff040-5081-101b-9f08-00aa002f954e}  ; 在回收站里选择一个文件。
FileSelectFolder, OutputVar, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}  ; 在“我的电脑”中选择一个文件夹。

CLSID(类标识符) | 含义/位置 | 被 Run 支持?
::{d20ea4e1-3957-11d2-a40b-0c5020524153} | Administrative Tools(管理工具) |
::{85bbd92o-42a0-1o69-a2e4-08002b30309d} | Briefcase(公文包) |
::{21ec2o2o-3aea-1o69-a2dd-08002b30309d} | Control Panel(控制面板) |
::{d20ea4e1-3957-11d2-a40b-0c5020524152} | Fonts(字体) |
::{ff393560-c2a7-11cf-bff4-444553540000} | History(历史) |
::{00020d75-0000-0000-c000-000000000046} | Inbox(收件箱) |
::{00028b00-0000-0000-c000-000000000046} | Microsoft Network(微软网络) |
::{20d04fe0-3aea-1069-a2d8-08002b30309d} | 我的电脑 | 是
::{450d8fba-ad25-11d0-98a8-0800361b1103} | 我的文档 | 是
::{208d2c60-3aea-1069-a2d7-08002b30309d} | 网上邻居 | 是
::{1f4de370-d627-11d1-ba4f-00a0c91eedba} | 搜索结果 - 计算机 | 是
::{7007acc7-3202-11d1-aad2-00805fc1270e} | 网络连接 | 是
::{2227a280-3aea-1069-a2de-08002b30309d} | 打印机和传真 | 是
::{7be9d83c-a729-4d97-b5a7-1b7313c39e0a} | Programs Folder(应用程序文件夹) |
::{645ff040-5081-101b-9f08-00aa002f954e} | 回收站 | 是
::{e211b736-43fd-11d1-9efb-0000f8757fcd} | Scanners and Cameras(扫描仪和照相机) |
::{d6277990-4c6a-11cf-8d87-00aa0060f5bf} | 任务计划 | 是
::{48e7caab-b918-4e58-a94d-505519c795dc} | Start Menu Folder(启动菜单文件夹) |
::{7bd29e00-76c1-11cf-9dd0-00a0c9034933} | Temporary Internet Files(Internet 临时文件) |
::{bdeadf00-c265-11d0-bced-00a0c90ab50f} | Web Folders(网络文件夹) |

最后一列有“是”的项目并不是权威的: Run 命令根据系统配置可能支持不同的 CLSIDs 。要用 Run 命令打开一个 CLSID 文件夹，只需将 CLSID 指定为首个参数。例如:

Run ::{20d04fe0-3aea-1069-a2d8-08002b30309d}  ; 打开“我的电脑”。
Run ::{645ff040-5081-101b-9f08-00aa002f954e}  ; 打开回收站。
Run ::{450d8fba-ad25-11d0-98a8-0800361b1103}\My Folder  ; 打开“我的文档”里的一个文件夹。
Run %A_MyDocuments%\My Folder  ; 在大部分操作系统上等同于上行命令。


ErrorLevel

ErrorLevel是为了判断命令运行成功与否而内置的一个变量（不过，并不是所有的命令都会改变ErrorLevel的值）。当值为0时通常代表成功，而其他的时意味着失败。你也可以自己定义ErrorLevel的值。

要特别注意的就是 RunWait 命令在它所运行的程序中将ErrorLevel设置成了退出代码。大部分程序在他们成功完成之后都会产生一个退出代码 0。

每个 线程 都保留了它自己的ErrorLevel值，意味着如果 当前线程 被其他的线程中断后，当原线程恢复时它还保持原有的ErrorLevel值，而不会被中断线程修改原有的ErrorLevel值。

备注：由于一些命令将ErrorLevel的值设置成大于1，所以最好不要检查ErrorLevel是否为1，而是检查它是否为0来代替。

例子：

WinWait, MyWindow, , 1
if ErrorLevel   ; 也就是说它既不是空值，也不是0.
    MsgBox, The window does not exist.
else
    MsgBox, The window exists.


Standard Windows Fonts

标准 Windows 字体

供 Progress, GUI, 和 SplashImage 命令使用。

推荐的字体被黄色高亮。

字体名称 | Win95 | WinNT | Win98 | Win2000 | WinMe | WinXP
Abadi MT Condensed Light |  |  | x |  |  |
Arial | x | x | x | x | x | x
Arial Alternative Regular |  |  |  |  | x |
Arial Alternative Symbol |  |  |  |  | x |
Arial Black |  |  | x | x | x | x
Arial Bold | x | x | x | x | x | x
Arial Bold Italic | x | x | x | x | x | x
Arial Italic | x | x | x | x | x | x
Book Antiqua |  |  | x |  |  |
Calisto MT |  |  | x |  |  |
Century Gothic |  |  | x |  |  |
Century Gothic Bold |  |  | x |  |  |
Century Gothic Bold Italic |  |  | x |  |  |
Century Gothic Italic |  |  | x |  |  |
Comic Sans MS |  |  | x | x | x |
Comic Sans MS Bold |  |  | x | x | x | x
Copperplate Gothic Bold |  |  | x |  |  |
Copperplate Gothic Light |  |  | x |  |  |
Courier | x | x | x | x | x | x
Courier New | x | x | x | x | x | x
Courier New Bold | x | x | x | x | x | x
Courier New Bold Italic | x | x | x | x | x | x
Courier New Italic | x | x | x | x | x | x
Estrangelo Edessa |  |  |  |  |  | x
Franklin Gothic Medium |  |  |  |  |  | x
Franklin Gothic Medium Italic |  |  |  |  | x |
Gautami |  |  |  |  |  | x
Georgia |  |  |  | x |  | x
Georgia Bold |  |  |  | x |  | x
Georgia Bold Italic |  |  |  | x |  | x
Georgia Italic |  |  |  | x |  | x
Georgia Italic Impact |  |  |  |  |  | x
Impact |  |  | x | x | x |
Latha |  |  |  |  |  | x
Lucida Console |  | x | x | x | x | x
Lucida Handwriting Italic |  |  | x |  |  |
Lucida Sans Italic |  |  | x |  |  |
Lucida Sans Unicode |  |  | x | x |  | x
Marlett |  |  | x |  | x |
Matisse ITC |  |  | x |  |  |
Modern | x | x | x | x |  |
Modern MS Sans Serif |  |  |  |  |  | x
MS Sans Serif | x | x | x | x | x | x
MS Serif | x | x | x | x | x |
Mv Boli |  |  |  |  |  | x
News Gothic MT |  |  | x |  |  |
News Gothic MT Bold |  |  | x |  |  |
News Gothic MT Italic |  |  | x |  |  |
OCR A Extended |  |  | x |  |  |
Palatino Linotype |  |  |  | x |  | x
Palatino Linotype Bold |  |  |  | x |  | x
Palatino Linotype Bold Italic |  |  | x |  | x |
Palatino Linotype Italic |  |  |  | x |  | x
Roman |  | x |  | x |  | x
Script |  | x |  | x |  | x
Small Fonts |  | x |  | x |  | x
Smallfonts | x |  | x |  | x |
Symbol | x | x | x | x | x | x
Tahoma |  |  | x | x | x | x
Tahoma Bold |  |  | x | x | x | x
Tempus Sans ITC |  |  | x | x |  |
Times New Roman | x | x | x | x | x | x
Times New Roman Bold | x | x | x | x | x | x
Times New Roman Bold Italic | x | x | x | x | x | x
Times New Roman Italic | x | x | x | x | x | x
Trebuchet |  |  |  |  | x |
Trebuchet Bold |  |  |  |  | x |
Trebuchet Bold Italic |  |  |  |  | x |
Trebuchet Italic |  |  |  |  | x |
Trebuchet MS |  |  |  | x |  | x
Trebuchet MS Bold |  |  |  | x |  | x
Trebuchet MS Bold Italic |  |  |  | x |  | x
Trebuchet MS Italic |  |  |  | x |  | x
Tunga |  |  |  |  |  | x
Verdana (包含于 MSIE 3+ 中) |  |  | x | x | x | x
Verdana Bold |  |  | x | x | x | x
Verdana Bold Italic |  |  | x | x | x | x
Verdana Italic |  |  | x | x | x | x
Webdings |  |  | x | x | x | x
Westminster |  |  | x |  | x | x
Wingdings | x | x |  | x |  | x
WST_Czech |  |  |  |  |  | x
WST_Engl |  |  |  |  |  | x
WST_Fren |  |  |  |  |  | x
WST_Germ |  |  |  |  |  | x
WST_Ital |  |  |  |  |  | x
WST_Span |  |  |  |  |  | x
WST_Swed |  |  |  |  |  | x

列表由 KaysKreations 和 AutoIt 团队整理。


Language Codes

语言编码

下面的列表包含了对应每种语言编码的语言名称，它能被包含在 A_Language 变量里。语言编码本身是下面等号左边的末尾的 4 位数字。例如，如果 A_Language 包含了 0436，那么系统的默认语言就是 Afrikaans。备注：包含字母的编码可以使用大写或小写。

你可以直接把 A_Language 和下面的一个或多个 4 位编码进行比较。例如:if (A_Language = "0436")。或者，你可以把整个列表粘贴进一个脚本，然后像列表底部的那个演示一样存取当前语言的名称。

languageCode_0436 = Afrikaans
languageCode_041c = Albanian
languageCode_0401 = Arabic_Saudi_Arabia
languageCode_0801 = Arabic_Iraq
languageCode_0c01 = Arabic_Egypt
languageCode_0401 = Arabic_Saudi_Arabia
languageCode_0801 = Arabic_Iraq
languageCode_0c01 = Arabic_Egypt
languageCode_1001 = Arabic_Libya
languageCode_1401 = Arabic_Algeria
languageCode_1801 = Arabic_Morocco
languageCode_1c01 = Arabic_Tunisia
languageCode_2001 = Arabic_Oman
languageCode_2401 = Arabic_Yemen
languageCode_2801 = Arabic_Syria
languageCode_2c01 = Arabic_Jordan
languageCode_3001 = Arabic_Lebanon
languageCode_3401 = Arabic_Kuwait
languageCode_3801 = Arabic_UAE
languageCode_3c01 = Arabic_Bahrain
languageCode_4001 = Arabic_Qatar
languageCode_042b = Armenian
languageCode_042c = Azeri_Latin
languageCode_082c = Azeri_Cyrillic
languageCode_042d = Basque
languageCode_0423 = Belarusian
languageCode_0402 = Bulgarian
languageCode_0403 = Catalan
languageCode_0404 = Chinese_Taiwan
languageCode_0804 = Chinese_PRC
languageCode_0c04 = Chinese_Hong_Kong
languageCode_1004 = Chinese_Singapore
languageCode_1404 = Chinese_Macau
languageCode_041a = Croatian
languageCode_0405 = Czech
languageCode_0406 = Danish
languageCode_0413 = Dutch_Standard
languageCode_0813 = Dutch_Belgian
languageCode_0409 = English_United_States
languageCode_0809 = English_United_Kingdom
languageCode_0c09 = English_Australian
languageCode_1009 = English_Canadian
languageCode_1409 = English_New_Zealand
languageCode_1809 = English_Irish
languageCode_1c09 = English_South_Africa
languageCode_2009 = English_Jamaica
languageCode_2409 = English_Caribbean
languageCode_2809 = English_Belize
languageCode_2c09 = English_Trinidad
languageCode_3009 = English_Zimbabwe
languageCode_3409 = English_Philippines
languageCode_0425 = Estonian
languageCode_0438 = Faeroese
languageCode_0429 = Farsi
languageCode_040b = Finnish
languageCode_040c = French_Standard
languageCode_080c = French_Belgian
languageCode_0c0c = French_Canadian
languageCode_100c = French_Swiss
languageCode_140c = French_Luxembourg
languageCode_180c = French_Monaco
languageCode_0437 = Georgian
languageCode_0407 = German_Standard
languageCode_0807 = German_Swiss
languageCode_0c07 = German_Austrian
languageCode_1007 = German_Luxembourg
languageCode_1407 = German_Liechtenstein
languageCode_0408 = Greek
languageCode_040d = Hebrew
languageCode_0439 = Hindi
languageCode_040e = Hungarian
languageCode_040f = Icelandic
languageCode_0421 = Indonesian
languageCode_0410 = Italian_Standard
languageCode_0810 = Italian_Swiss
languageCode_0411 = Japanese
languageCode_043f = Kazakh
languageCode_0457 = Konkani
languageCode_0412 = Korean
languageCode_0426 = Latvian
languageCode_0427 = Lithuanian
languageCode_042f = Macedonian
languageCode_043e = Malay_Malaysia
languageCode_083e = Malay_Brunei_Darussalam
languageCode_044e = Marathi
languageCode_0414 = Norwegian_Bokmal
languageCode_0814 = Norwegian_Nynorsk
languageCode_0415 = Polish
languageCode_0416 = Portuguese_Brazilian
languageCode_0816 = Portuguese_Standard
languageCode_0418 = Romanian
languageCode_0419 = Russian
languageCode_044f = Sanskrit
languageCode_081a = Serbian_Latin
languageCode_0c1a = Serbian_Cyrillic
languageCode_041b = Slovak
languageCode_0424 = Slovenian
languageCode_040a = Spanish_Traditional_Sort
languageCode_080a = Spanish_Mexican
languageCode_0c0a = Spanish_Modern_Sort
languageCode_100a = Spanish_Guatemala
languageCode_140a = Spanish_Costa_Rica
languageCode_180a = Spanish_Panama
languageCode_1c0a = Spanish_Dominican_Republic
languageCode_200a = Spanish_Venezuela
languageCode_240a = Spanish_Colombia
languageCode_280a = Spanish_Peru
languageCode_2c0a = Spanish_Argentina
languageCode_300a = Spanish_Ecuador
languageCode_340a = Spanish_Chile
languageCode_380a = Spanish_Uruguay
languageCode_3c0a = Spanish_Paraguay
languageCode_400a = Spanish_Bolivia
languageCode_440a = Spanish_El_Salvador
languageCode_480a = Spanish_Honduras
languageCode_4c0a = Spanish_Nicaragua
languageCode_500a = Spanish_Puerto_Rico
languageCode_0441 = Swahili
languageCode_041d = Swedish
languageCode_081d = Swedish_Finland
languageCode_0449 = Tamil
languageCode_0444 = Tatar
languageCode_041e = Thai
languageCode_041f = Turkish
languageCode_0422 = Ukrainian
languageCode_0420 = Urdu
languageCode_0443 = Uzbek_Latin
languageCode_0843 = Uzbek_Cyrillic
languageCode_042a = Vietnamese

the_language := languageCode_%A_Language%  ; 获取系统的默认语言名称。
MsgBox %the_language%  ; 显示语言名称。


Creating a Keyboard Macro or Mouse Macro

创建一个键盘宏或者鼠标宏

宏是按需要“播放”的一系列事先编好的动作。宏最常见的用法是向一个或多个窗口发送 模拟的键击 和 鼠标点击。这些窗口对每个键击和鼠标点击做出响应，就好像你手动操作一样，这就使得重复性的工作得以高速可靠地自动化。

虽然宏可以手工编辑，但借助于 AutoScriptWriter，你在编写较长的宏时会感觉更轻松。它是一个附在 AutoHotkey 里的宏录制器。其监视你在何处点击并输入了什么，而且一直记录 激活的 窗口。它将这些动作转录成一个之后能以更快速度“回放”的可用的宏。

宏回放最便捷的方式之一就是为其指定一个 热键 或者 热字符串。例如，下面的热键将为特定类型的收件人创建一个空白电子邮件，在发送之前允许你进行个性化编写：

^!s::  ; Control+Alt+S 热键。
IfWinNotExist Inbox - Microsoft Outlook
    return  ; Outlook 未开启正确的部分，所以什么都不做。
WinActivate  ; 激活由上面命令找到的窗口。
Send ^n  ;通过 Control+N 创建一个新的/空白的电子邮件。
WinWaitActive Untitled Message
Send {Tab 2}Product Recall for ACME Rocket Skates  ; 设定标题行。
Send {Tab}Dear Sir or Madam,{Enter 2}We have recently discovered a minor defect ...  ; 等等
return  ; 这行用来结束热键。

上面这样的热键宏对你每天都要多次执行的工作非常有帮助。相比之下，不经常使用的宏可以存放在独立的脚本中，通过把它加到开始菜单或者放在桌面来运行。

想马上创建你自己的宏和热键，请阅读 迅速开始指南。

-- 主页 --


Overriding Hotkeys

覆写或禁用热键

对注册表做如下更改，你可以禁用内置的 Windows 热键除了 Win+L 和 Win+U (这适用于所有的微软操作系统，不过可能需要重启生效):

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
NoWinKeys REG_DWORD 0x00000001 (1)

但是如果你想进一步设置而非仅仅将它们全部禁用，那么请往下看。注意下面的大部分示例在 Windows Me/98/95 中不支持。

其他程序定义的热键可以在脚本中将它们指定为一个动作来简单地覆写或禁用。此特性常用来改变 Windows 内置的热键。例如，如果你希望 Win+E (启动资源管理器的热键) 执行其他的动作，可以这样:

#e::
MsgBox 现在脚本支配此热键。
return

在下面的示例中，用来打开运行对话框的 Win+R 热键被完全禁用了:

#r::return

类似地，要禁用两个 Windows 键，可以这样:

Lwin::return
Rwin::return

要禁用或改变一个程序的非全局热键(即只有在应用程序窗口处于激活时才起作用的热键)，可参考下面这个仅在记事本中禁用 Control+P(打印)，而让它对所有其它类型的窗口有效的示例:

$^p::
IfWinActive ahk_class Notepad
 return ;即什么也不做，它使 Control-P 在记事本中失效。
Send ^p
return

在上例中前缀 $ 是必需的，以便热键可以“发送自身”而不触发它自己(否则会不停地出现警告框)。同样可见：上下文相关的热键。

你可以复制上述示例到一个新的文本文件例如 "Override.ahk"，然后运行文件来试用。


Performance

脚本性能

每个脚本在它被载入以及语法检查时都是半编译的。这样做除了会减少脚本消耗的内存外，也会极大地提高运行时的性能。

除了 SetBatchLines,根据脚本的内容，下列命令同样会影响到性能: SendMode, SetKeyDelay, SetMouseDelay, SetWinDelay, SetControlDelay 和 SetDefaultMouseSpeed。

下面是优化过程的技术细节(半编译):

  • 输入输出变量(当不含其它变量的引用时)以及 group 名称被解析为内存地址。
  • Loops, blocks, IFs 和 ELSEs 会给出它们在脚本内相关的跳转点的内存地址。
  • 每个 Hotkey, Gosub 和 Goto 的终点被解析为一个内存地址，除非它是个变量。
  • 在一个跳转列表里，每个命令名称都被替换成一个地址。
  • 每一行都被预解析成一个参数列表。
  • 每个参数和 表达式 都被预解析为一个 变量 和 函数 的列表(如果有的话)。
  • 每个变量或函数的引用都被解析为一个内存地址。


正则表达式 - 快速参考

基础知识

不论你在哪: 通常，正则表达式可以在被搜索字符串中的任意位置找到匹配文本。比如，正则表达式 abc 可以匹配 abc123, 123abc, 和 123abcxyz 。您也可以使用脱字符号"^"和美元符号"$"把匹配文本锚定(anchor)在这一行的开头和结尾。

神奇的转义: (Hsuda:如果需要匹配的某个字符本身就是元字符(如：\.*?+[{|()^$ )，正则表达式会如何处理呢？)例如搜索www.xiaonei.com，而需要搜索的文本里的点号在正则表达式里是代表所有字符的元字符。这时我最终使用的正则表达式是www\.xiaonei\.com。通过使用反斜线，让元字符失去特殊含义而成为普通字符。反斜线(\)便是转义符。不过值得注意的是，在字符组内，转义字符无效。

忽略大小写: 通常，正则表达式不会忽略大小写。但是这会给我们带来一些困扰，比如我们在处理HTML文档的时候，H1和h1是一个意思，但正则表达式却无法知道。这个时候我们可以使用选项"i"让正则表达式忽略大小写。比如i)abc可以忽略大小写去搜索abc。参照 options 来获取更多选项信息。

通用的元字符及使用方法：

. 点号 匹配单个任意字符(除了新行：换行符('r)和回车符('n))。比如，ab. 匹配 abc和abz及ab_。
*

星号 可以匹配任意多次(字符，字符组(class)，单元(subpattern))，也可能不匹配。比如 a* 可以匹配ab 也可以匹配aaaab 。它还可以匹配甚至不包含a的字符串。

通配符: AHK里自由的组合莫过于 点号-星号 的组合。它可以匹配任意多的任意字符，也可以匹配0个字符(当然，除了新行：换行符('r)和回车符('n))。比如： abc.*123 匹配 abcAnything123 或者 abc123。
?

问号 容许匹配一次(字符，字符组(class)，单元(subpattern))，但非必须。您可以理解为“之前的那项是可选的”。比如， colou?r 可以

匹配 color和colour 因为"u"是可选的。
+ 加号 至少需要匹配一次(字符，字符组(class)，单元(subpattern))，至多可能任意多次。比如 a+ 匹配 ab 和 aaab。但是在开头必须至少有一个a，这就是他与星号有区别的地方。
{min,max}

区间量词 至少需要min次(字符，字符组(class)，单元(subpattern))，至多容许max次。比如，a{1,2}可以匹配ab 但仅仅只能匹配aaab中的前两个a。

另外，{3}意味着准确地匹配3次，{3,}意味着3次或者更多。注意：您所指定的数字必须小于65536，并且第一个数字要小于第二个数字。（地球人都知道为什么~）
[...]

字符组: (Hsuda:如果我们要搜索的是单词"grey"而又不确定它是否写作"gray"，便应当使用字符组。)在方括号中列出期望匹配的字符。[abc]可以匹配a或b或c。我们也可以使用连字符"-"来表示一个范围；比如[a-z]就意味着可以匹配所有的小写字母，很有趣，不是么？

Hsuda:下面所介绍的\d \w ……都是一种特殊的字符组。

与单个字符一样，您可以使用 *, ?, +, or {min,max}这些量化符号跟在字符组的后面。效果同上面的介绍。 比如[0-9]+匹配一个或者更多的数字，所以能够匹配xyz123而不能匹配abcxyz。

在字符组你既可以罗列你期望匹配的字符也可以使用字符序列，或者将二者组合使用。比如 [a-zA-Z0-9_] 可以匹配数字字母下划线。

Hsuda:我们通常所说的字符组在POSIX标准中被称为方括号表达式(bracket expression)。POSIX中术语"字符组"指的是在方括号表达式内部使用的一种特殊的功能(special feature)，而我们可以认为它们是Unicode的字符属性的原型。

POSIX标准中规定的形式是 [[:xxx:]] ，xxx可以上下面的单词来代替：

alnum 字母字符和数字字符

alpha 字母

ascii 0-127

blank 空格和制表符

cntrl 控制字符

digit 数字0-9

xdigit 16进制数字

print 类似graph但包含空白字符

graph 非空白字符(即空白字符，控制字符之外的字符)

punct 标点符号

lower 小写字母

upper 大写字母

space 所有的空白字符

word 单词字符，参考\w

Within a character class, characters do not need to be escaped except when they have special meaning inside a class; e.g. [\^a], [a\-b], [a\]], and [\\a].
[^...] 排除型字符组 匹配任何未列出的字符。比如[^1-6]匹配除了1到6以外的任何字符。其他特性与字符组相同。
\d | 匹配单个数字 等价于 [0-9]。相反的 \D 匹配非数字字符 等价于 [^0-9]。这个和下面介绍的那两个都可以用在字符组里。比如[\d.-]可以匹配所有数字，点号，和连字符。
\s | 匹配空白字符 通常等价于[ \f\n\r\t\v]即匹配空白符，空格，制表，换行。相反的 \S匹配非空白字符。
\w | 匹配单词中的字符，等价于[0-9a-zA-Z_]。相反的\W匹配非单词字符 等价于[^0-9a-zA-Z]。
^
$

脱字符号"^"和美元符号"$"被称为锚点是因为他们并不会匹配实际的文本，而是寻找文本中的位置。(Hsuda:我把锚点归类为“零长度断言”)

^(脱字符)匹配需要搜索的文本的起始位置。比如： ^abc 匹配 abc123 而不能 123abc。

$ 美元符号 匹配目标字符串的末尾。比如abc$ 匹配 123abc 而不是 abc123。

两个锚点可以组合使用，比如^abc$ 只能匹配abc(在abc的前面和后面不能有任何字符)。

对于有很多行的被搜索文本，我们可以使用 "m" 选项 使得锚点可以用作搜索每一行而不是把所有行当作整体来搜索。比如m)^abc$ 可以匹配 123`r`nabc`r`n789 。但是如果缺少 "m" 选项，这是不可以匹配的。
\b | \b 代表"单词分界符(word boundary)"，单词分界符的作用与行锚点一样，也是匹配字符串中的某些位置。它要求当前字符的状态是一个单词字符(\w)而它之前的与它相反。我们使用\b能有效地避免在匹配过程中遇到一个单词属于另一个单词时造成的麻烦。比如： \bcat\b不能匹配catfish而仅仅只能匹配cat。\B则起到的是完全相反的作用。
| 竖线将两个或者更多的选项分隔开来。选项中的任意一项满足条件便可以完成匹配。比如gray|grey 可以匹配 gray和grey。相似的，表达式 gr(a|e)y 所产生的作用与上面这个例子一样。
(...)

将表达式放入括号里通常应用于：

  • 确定赋值的类型。比如(Sun|Mon|Tues|Wednes|Thurs|Fri|Satur)day可以匹配任何一天的名字。
  • 应用 *, ?, +, 或 {min,max} 来量化多于一个的字符。比如(abc)+ 可以匹配一连串的“abc”，他可以匹配abcabc而不能匹配ab123或 bc123。
  • 捕获子表达式的值就像捕获abc(.*)xyz 中点号所匹配的部分。比如RegExMatch()在他的输出数组(output array)中存储子表达式所匹配的值。相似的，在RegExReplace() 中，允许我们使用类似$1这样的回溯(backreferences)将匹配每个子表达式的文本重新插入到结果中。不过捕获并不总是好事，为了避免捕获带来的烦恼，正则表达式提供了非捕获型括号，在左边的括号的后面写上?: 作为前两个字符，比如(?:.*) (?:abc)。
  • 在工作状态下改变选项(options)。比如 (?im) 能够让表达式的剩余部分忽略大小写选项和多行选项(如果它在一个子表达式中，则改变这个子表达式的)。相反的， (?-im) 将把这两个参数全部关闭。除了 DPS`r`n`a 外支持所有的选项。
\t
\r
etc.

这些转义字符代表特殊字符。最常见的是\t代表制表符，\r代表回车，\n代表换行。在AutoHotkey里，这里例子里的反斜线可以用重音符号" ` "来代替(当然是为了方便群众)。像\xhh这种形式的转义字符也是支持的，hh则是代表ANSI字符的十六进制数(00-FF)。

在 v1.0.46.06以上的版本中， \R 代表"任何形式的单个换行符"，与之功能相同的是 `a option(然而，\R在字符组(character class)内仅仅是字母"R")。在In v1.0.47.05以上的版本中，在表达式的前面指定(*BSR_ANYCRLF)可以让 \R 匹配CR LF 和 CRLF。比如：im)(*BSR_ANYCRLF)abc\Rxyz。

匹配优先模式:通常， *, ?, +, 和 {min,max}是匹配优先量词因为他们都是尽可能多地去匹配字符。

Hsuda:这里插播一个例子，对于匹配优先模式，我们将遇到一个很常见的陷阱。比如，我们要搜索的句子是

They call me "Hsudatalks" or "Freedom".

我希望搜索第一对引号里的内容，可能会产生这样的表达式".+"，可是由于*是匹配优先的量词，我们得到的结果是

"Hsudatalks" or "Freedom"

这明显不是我们所期望的结果。那该怎么办呢？请看下面的帮助：

在他们后面使用问号则可以让他们尽可能少的匹配字符。那上面的例子我们采用".+?"，所得到的便是"Hsudatalks"。

例：表达式<.+>所表示的意思是先搜索<，在匹配一个或者更多的任意字符，后面跟着一个>。在匹配时会出现 <em>text</em>，为了避免这种情况，我们使用<.+?> 使得表达式仅仅只会匹配标记<em>。

顺序环视和逆序环视: (?=...)，(?!...)，(?<=...) 和 (?<!...) 被成为环视，因为他们都是形容一个匹配条件而不消耗任何字符。比如：abc(?=.*xyz) 匹配右边的某个地方存在字符xyz的字符abc(如果不存在，便不能匹配)。 (?=...)被称为肯定顺序环视，因为他需要指定的字符在后面存在才能够完成匹配过程。相反的，(?!...)是否定顺序环视，因为他是在不存在指定字符的条件下的条件下完成匹配。相似的，(?<=...) 和(?<!...) 被称为肯定和否定的逆序环视，因为他们是在当前位置的左边寻找指定的字符存在或者不存在。逆序要比顺序更加局限，因为他不支持*,?和+这样的量词。

相关： 正则表达式由 RegExMatch(), RegExReplace()和SetTitleMatchMode支持。

最后：尽管这个页面介绍了正则表达式中最常用的元字符和一些特性，但是还有比如条件子表达式等相当一部分的其他特性您期望了解的。完整的PCRE手册请访问 www.pcre.org/pcre.txt 。(Hsuda:写到这里，发现AHK里的正则表达式原来用的是PCRE的库，关于PCRE，大家需要了解的是这是个地地道道的传统NFA引擎的正则库，所以，在编写正则表达式的时候是很考验您的优化功力的)


Regular Expression Callouts

正则表达式全程调用 [AHK_L 14+]

全程调用提供在正则表达式模式匹配当中临时传递控制到脚本的方法. 关于 PCRE 标准全程调用特性的详细信息, 参见 pcre.txt.

全程调用当前仅由 RegExMatch 和 RegExReplace 支持.

语法

在 AutoHotkey_L 中全程调用的语法为 (?CNumber:Function), 此处 Number 和 Function 都是可选的. 只有在指定了 Function 时才需要冒号, 如果省略了 Number 那么冒号是可选的. 如果指定的 Function 不是用户定义的函数名称, 则会出现编译错误并且不会开始模式匹配.

如果省略了 Function, 那么函数名称必须在名为 pcre_callout 的变量中指定. 如果同时存在此名称的全局变量和局部变量, 局部变量优先. 如果 pcre_callout 不包含用户定义函数的名称, 那么省略函数的全程调用被忽略.

全程调用函数

Function(Match, CalloutNumber, FoundPos, Haystack, NeedleRegEx)
{
    ...
}

全程调用函数最多可以定义 5 个参数:

  • Match: 相当于 RegExMatch 函数中的 UnquotedOutputVar 参数, 包含需创建的数组变量.
  • CalloutNumber: 接收全程调用的 Number.
  • FoundPos: 接收当前可能匹配的位置.
  • Haystack: 接收传递到 RegExMatch 或 RegExReplace 函数的 Haystack 参数.
  • NeedleRegEx: 接收传递到 RegExMatch 或 RegExReplace 函数的 NeedleRegEx 参数.

这些名称只是暗示性的. 实际的名称可以改变.

模式匹配可能继续进行或失败, 取决于全程调用函数的返回值:

  • 如果函数返回 0 或不返回一个数值, 匹配操作如常进行.
  • 如果函数返回 1 或更大的数字, 则在当前位置匹配失败, 但其他匹配的可能性测试继续进行.
  • 如果函数返回 -1, 匹配中止.
  • 如果函数返回小于 -1 的值, 它被当成 PCRE 错误码并且匹配中止. RegExMatch 返回空字符串, 而 RegExReplace 返回原始的 Haystack. 在两种情况中, ErrorLevel 包含了错误码.

例如:

Haystack = The quick brown fox jumps over the lazy dog.
RegExMatch(Haystack, "i)(The) (\w+)\b(?CFunc)")
Func(m) {
    MsgBox m=%m%`nm1=%m1%`nm2=%m2%
    return 1
}

在上面的例子中, 为匹配全程调用之前模式的那部分的每个子字符串调用一次 Func. 使用 \b 排除匹配中不完全的单词例如 The quic, The qui, The qu 等.

EventInfo

通过 A_EventInfo 可以使用 pcre_callout_block 结构的附加信息.

version           := NumGet(A_EventInfo,  0, "Int")
callout_number    := NumGet(A_EventInfo,  4, "Int")
offset_vector     := NumGet(A_EventInfo,  8)
subject           := NumGet(A_EventInfo,  8 + A_PtrSize)
subject_length    := NumGet(A_EventInfo,  8 + A_PtrSize*2, "Int")
start_match       := NumGet(A_EventInfo, 12 + A_PtrSize*2, "Int")
current_position  := NumGet(A_EventInfo, 16 + A_PtrSize*2, "Int")
capture_top       := NumGet(A_EventInfo, 20 + A_PtrSize*2, "Int")
capture_last      := NumGet(A_EventInfo, 24 + A_PtrSize*2, "Int")
pad := A_PtrSize=8 ? 4 : 0  ; Compensate for 64-bit data alignment.
callout_data      := NumGet(A_EventInfo, 28 + pad + A_PtrSize*2)
pattern_position  := NumGet(A_EventInfo, 28 + pad + A_PtrSize*3, "Int")
next_item_length  := NumGet(A_EventInfo, 32 + pad + A_PtrSize*3, "Int")

更多信息, 参见 pcre.txt, NumGet 和 A_PtrSize.

自动全程调用

在模式选项中包含 C 启用自动全程调用模式. 在此模式中, 在匹配模式的每个项目前插入等于 (?C255) 的全程调用. 例如, 可以使用下面的模板来调试正则表达式:

; Set the default callout function.
pcre_callout = DebugRegEx

; Call RegExMatch with auto-callout option C.
RegExMatch("xxxabc123xyz", "C)abc.*xyz")

DebugRegEx(Match, CalloutNumber, FoundPos, Haystack, NeedleRegEx)
{
    ; See pcre.txt for descriptions of these fields.
    start_match       := NumGet(A_EventInfo, 12 + A_PtrSize*2, "Int")
    current_position  := NumGet(A_EventInfo, 16 + A_PtrSize*2, "Int")
    pad := A_PtrSize=8 ? 4 : 0
    pattern_position  := NumGet(A_EventInfo, 28 + pad + A_PtrSize*3, "Int")
    next_item_length  := NumGet(A_EventInfo, 32 + pad + A_PtrSize*3, "Int")

    ; Point out >>current match<<.
    _HAYSTACK:=SubStr(Haystack, 1, start_match)
        . ">>" SubStr(Haystack, start_match + 1, current_position - start_match)
        . "<<" SubStr(Haystack, current_position + 1)

    ; Point out >>next item to be evaluated<<.
    _NEEDLE:=  SubStr(NeedleRegEx, 1, pattern_position)
        . ">>" SubStr(NeedleRegEx, pattern_position + 1, next_item_length)
        . "<<" SubStr(NeedleRegEx, pattern_position + 1 + next_item_length)

    ListVars
    ; Press Pause to continue.
    Pause
}

备注

全程调用在当前的半线程中执行, 但在全程调用函数返回后将恢复 A_EventInfo 原来的值. 在 RegExMatch 或 RegExReplace 返回时才会设置 ErrorLevel 的值.


Remapping a Joystick to Keyboard or Mouse

重映射游戏杆为键盘或鼠标

目录

  • 重要事项
  • 让游戏杆按钮发送键击或者鼠标点击
  • 让游戏杆轴向(Joystick Axis)或者视点帽(POV Hat)发送键击或者鼠标点击
  • 备注

重要事项

  • 虽然可以把游戏杆按钮或轴向重映射为按键或者鼠标按钮，但是不能把它映射为另一个游戏杆按钮或轴向。只能用游戏杆模拟器例如 PPJoy 来实现。
  • AutoHotkey 用 1 至 32 之间一个唯一的数字来定义游戏杆上的每个按钮。要确定这些数字，请用游戏杆测试脚本。

让游戏杆按钮发送键击或者鼠标点击

以下是三种由易到难的方式。最复杂的方法适用于更广泛的情况（例如需要将按键或者鼠标按钮按住不放的游戏）。

方法 #1: 此方法发送简单的键击和鼠标点击。例如:

Joy1::Send {Left} ;让按钮 #1 发送一个左箭头键击。
Joy2::Click ;让按钮 #2 发送一个鼠标左键点击。
Joy3::Send a{Esc}{Space}{Enter} ;让按钮 #3 发送字母"a"后紧跟 Escape, Space 和 Enter。
Joy4::Send Sincerely,{Enter}John Smith ;让按钮 #4 发送一个两行的签名。

要让一个按钮执行多个命令，只要将第一个命令放在按钮名称之下并且使最后一个命令为 return。例如:

Joy5::
Run Notepad
WinWait 无标题 - 记事本
WinActivate
Send This is the text that will appear in Notepad.{Enter}
return

请看按键列表以获得完整的按键和鼠标/游戏杆按钮列表。

方法 #2: 此方法是在你按住一个游戏杆按钮的全程，键盘按键或者鼠标按钮也必须一直按住的情况下才使用的。下面的例子使游戏杆的第二个按钮成为左箭头按键：

Joy2::
Send {Left down} ;按住左箭头按键。
KeyWait Joy2 ;等待用户松开游戏杆按钮。
Send {Left up} ;释放左箭头按键。
return

方法 #3: 此方法是你有多个在方法 #2 中所描述的游戏杆热键，并且有时会同时按下或释放这些热键的情况下才使用。下面的例子使游戏杆的第三个按钮成为鼠标左键：

Joy3::
Send {LButton down} ;按住鼠标左键。
SetTimer, WaitForButtonUp3, 10
return

WaitForButtonUp3:
if GetKeyState("Joy3") ;按钮仍处于按下状态的话就继续等待。
return
;否则，按键已松开。
Send {LButton up} ;松开鼠标左键。
SetTimer, WaitForButtonUp3, off
return

自动重复某个键击：有些程序或者游戏可能需要你重复地发送某个按键（就像你在键盘上按着它不放）。下面的例子在你按住游戏杆的第二个按钮时通过重复地发送空格键键击来达到此目的。

Joy2::
Send {Space down} ;按下空格键。
SetTimer, WaitForJoy2, 30 ;将数字 30 减为 20 或 10 可以更快地发送按键。增加它会发送地更慢。
return

WaitForJoy2:
if not GetKeyState("Joy2") ;按钮已经释放。
{
Send {Space up} ;释放空格键。
SetTimer, WaitForJoy2, off ;停止监视按钮。
return
}
;因为上面没有“return”，所以按钮依然处于按住状态。
Send {Space down} ;发送另一个空格键键击。
return

环境敏感的游戏杆按钮：#IfWinActive/Exist 指令使选择的游戏杆按钮根据激活或存在的窗口类型而执行不同的动作(或者根本不执行)。

把游戏杆当鼠标来用：Joystick-To-Mouse 脚本通过重映射游戏杆的按钮和控制轴向把它变成鼠标。

让游戏杆轴向或视点帽发送键击或者鼠标点击

要让脚本对游戏杆轴向或者视点帽的移动做出响应，请用 SetTimer 和 GetKeyState。下面的例子将使游戏杆的 X 和 Y 轴表现得和键盘上的箭头按键群（左、右、上、下）一样。

#Persistent ;保持脚本运行，直到用户明确地退出。
SetTimer, WatchAxis, 5
return

WatchAxis:
GetKeyState, JoyX, JoyX ;得到 x 轴的坐标。
GetKeyState, JoyY, JoyY ;得到 y 轴的坐标。
KeyToHoldDownPrev = %KeyToHoldDown% ; Prev 现在保存了先前按下的按键（如果有的话）。

if JoyX > 70
  KeyToHoldDown = Right
else if JoyX < 30
  KeyToHoldDown = Left
else if JoyY > 70
  KeyToHoldDown = Down
else if JoyY < 30
  KeyToHoldDown = Up
else
  KeyToHoldDown =

if KeyToHoldDown = %KeyToHoldDownPrev% ;已经按下了正确的按键（或不需要按键）。
  return ;什么也不做。

;否则，松开先前的按键并按下一个新键：
SetKeyDelay -1 ;避免击键之间的延时。
if KeyToHoldDownPrev ;先前的按键需要松开。
  Send, {%KeyToHoldDownPrev% up} ;松开它。
if KeyToHoldDown ;要按下一个键。
  Send, {%KeyToHoldDown% down} ;按下它。
return

下面的例子将让游戏杆的视点帽起到和键盘上的箭头按键群一样的作用；就是说，视点帽将发送方向键击（左、右、上、下）：

#Persistent ;保持脚本运行，直到用户明确地退出。
SetTimer, WatchPOV, 5
return

WatchPOV:
GetKeyState, POV, JoyPOV ;获得视点控制的坐标。
KeyToHoldDownPrev = %KeyToHoldDown% ; Prev 现在存储了先前按下的键（如果有的话）。

;有一些游戏杆会有平滑/连续的视角切换而不是固定的增幅。
;要全部支持它们，可用一个值域：
if POV < 0 ;没有角度
  KeyToHoldDown =
else if POV > 31500 ; 315 至 360 度：向上
  KeyToHoldDown = Up
else if POV between 0 and 4500 ; 0 至 45 度：向上
  KeyToHoldDown = Up
else if POV between 4501 and 13500 ; 45 至 135 度：向右
  KeyToHoldDown = Right
else if POV between 13501 and 22500 ; 135 至 225 度：向下
  KeyToHoldDown = Down
else ; 225 至 315 度：向左
  KeyToHoldDown = Left

if KeyToHoldDown = %KeyToHoldDownPrev% ;已经按下了正确的键（或者不需要任何键）。
  return ;什么也不做。

;否则，释放先前的键并且按下一个新键:
SetKeyDelay -1 ;避免击键之间的延时。
if KeyToHoldDownPrev ;先前的按键需要释放。
  Send, {%KeyToHoldDownPrev% up} ;释放它。
if KeyToHoldDown ;需要按下一个键。
  Send, {%KeyToHoldDown% down} ;按下它。
return

自动重复某个键击：以上两个例子都可以修改为重复地发送按键，而不仅仅是按住它（也就是说，它们可以模拟按住了键盘上的某键）。要做到这一点，只需将下面这行：

return ;什么也不做。

替换为：

{
 if KeyToHoldDown
   Send, {%KeyToHoldDown% down} ;自动地重复键击。
 return
}

备注

也可以使用除了第一个之外的游戏杆，只要通过在按钮或者轴名之前加上游戏杆编号。例如，2joy1 就是指二号杆的第一个按钮。

要获得更多有用的游戏杆脚本，请访问 AutoHotkey 论坛。搜索关键词例如 Joystick 和 GetKeyState 和 Send 有可能找到你想要的主题。

相关主题

Joystick-To-Mouse 脚本（将游戏杆当鼠标用）
游戏杆按钮、轴向以及控制器的列表
GetKeyState
重映射键盘和鼠标


PostMessage/SendMessage Tutorial

向窗口或者窗口控件发送消息，作者：Rajat

本页讨论 PostMessage 和 SendMessage 命令，并将回答这样一些问题：

“我如何按下已被最小化的窗口中的按钮？”
“当 WinMenuSelectItem 不起作用时，我如何选中一个菜单项？！”
“这是个可更换皮肤的窗口……如何保证我发送的命令每次都能生效？”
“隐藏窗口的话该怎么办？！”

环境要求：AutoHotkey v1.0.09+ 以及 Winspector Spy (www.windows-spy.com)

例如第一个例子中，注意 WinMenuSelectItem 命令就对 Outlook Express 的"New Message"窗口上的菜单栏无效。换言之，该代码不起任何作用：

WinMenuSelectItem, New Message,, &Insert, &Picture...

但 PostMessage 命令就能完成这个工作：

PostMessage, 0x111, 40239, 0, , New Message

好神奇啊！但那是啥鬼东西？0x111 是 wm_command 消息 的十六进制代码，40239 是让这个特殊的窗口理解为选择 'Insert Picture' 菜单项的代码。现在让我来告诉你如何获得一个类似 40239 这样的值：

  1. 启动 Winspector Spy 软件，打开 "New Message" 窗口。
  2. 拖动 Winspector Spy 窗口中的十字光标到 "New Message" 窗口的标题栏上(未被 Winspector Spy 窗口的覆盖效果遮蔽的部分)。
  3. 在左边列表中被选中的窗口名称上点击右键，选择 'Messages'。
  4. 右键点击空白窗口并选择 'Edit message filter'。
  5. 按 'filter all' 按钮，然后双击左边列表中的 'wm_command' 项。这样你将只监视此消息。
  6. 现在转到 "New Message" 窗口并从菜单栏选择:Insert > Picture 。
  7. 返回 Winspector Spy 并按下信号灯按钮来暂停监视。
  8. 展开收集到的 wm_command 消息(忽略其它消息)。
  9. 你想要找的(通常)是一个代码为 0 的消息。有时那里描述为 'win activated' 或者 'win destroyed' 以及其它等等……都是不需要的内容。你要是发现那有一个描述为 'Control ID: 40239' 的消息……那就是它了！
  10. 现在将它放入上面的命令中你就搞定了！它就是 wParam 参数的值。

在下一个例子中，我会用到画图，因为大概每个人都会有。现在，让我们假设你要使用 AutoHotkey 从一个程序的工具栏选择一个工具；假设选择的就是取色这个工具。

你会怎么做？很可能是在工具栏按钮上用鼠标点击，对吧？但是工具栏可以被移动或者隐藏！在画图中也可以。所以如果目标用户移动或隐藏了工具栏，那么你的脚本在那个点上将会失效。但是下面的命令仍将有效：

PostMessage, 0x111, 639,,,未命名 - 画图

PostMessage 的另一个好处是窗口可以处在后台；相比之下，发送鼠标击键需要窗口处于激活状态。

下面有更多的例子。注意：我用的是 WinXP Pro (SP1)……如果你使用的是不同的操作系统，那可能需要调整下参数(仅对于像写字板和记事本这种 windows 自带的应用程序；其它的程序而言参数应该不用改变)。

;写字板字体设为青色
PostMessage, 0x111, 32788, 0, ,文档 - 写字板

;在记事本打开关于对话框
PostMessage, 0x111, 65, 0, ,无标题 - 记事本

;在记事本切换自动换行
PostMessage, 0x111, 32, 0, ,无标题 - 记事本

;播放/暂停 Windows Media Player
PostMessage, 0x111, 32808, 0, , Windows Media Player

;挂起一个正在运行的AHK脚本的热键
DetectHiddenWindows, on
SetTitleMatchMode, 2
PostMessage, 0x111, 65305,,, MyScript.ahk - AutoHotkey ;对比挂起操作，使用 65306 来暂停脚本。

上文讲的是 PostMessage 命令。SendMessage 命令与之相同，此外还等待一个消息返回值。可以用作例如获取 Winamp 中当前播放的曲目(请看 Automating Winamp 里的例子)。

这里还有些注意事项：

  • 上文也提到了操作系统是 XP 并且要谨记消息值随着不同的操作系统而改变。如果你发现一个消息可以在你的系统上使用(对一个软件的某个版本)，那么它肯定也能用同样版本的软件在其它系统上使用。此外，大多数应用程序即使在不同的版本中也保持相同的消息值(例如 Windows Media Player 和 Winamp)。
  • 如果你已在 Winspector Spy 设置了过滤仅显示 wm_command 消息，而你仍然获得大量的消息,这时，在那消息上点右键选择 hide (消息名称)……你不会想要看到那个不是你与目标软件交互而出现的消息。
  • 在 Winspector Spy 中向右的箭头显示消息值，模糊的向左的箭头显示返回值。返回值为 0，可默认安全地视为 'no error'(使用 SendMessage 命令，返回值将会在 %ErrorLevel% 中)。
  • 要给部分标题匹配的窗口传递消息，在脚本里加上这行：
    SetTitleMatchMode, 2
  • 要给隐藏窗口传递消息，在脚本里加上这行：
    DetectHiddenWindows, On

注意：此技术对某些应用程序无效。我对 VB 和 Delphi 编写的应用程序用时只能侥幸。此技术最适于 C, C++ 编写的应用程序。对于 VB应用程序，同个命令的 'LParam' 参数在传递时总是变化。对于 Delphi 应用程序……一些程序的GUI (用户图形界面)甚至不使用 wm_command 。它大概使用了鼠标位置和点击。

去探索吧……要在 AutoHotkey 论坛分享你的经验哦。欢迎您反馈信息！

这个指南并不是为新手们准备的(没有冒犯的意思)，因为这些命令被认为是高级专题。所以如果读完本文，你还是摸不着头脑的话，请忘了它吧。

-Rajat


List of Windows Messages

Windows 消息列表

下文列举了 PostMessage 和 SendMessage 命令中 Msg 参数的值。更多关于特定消息(例如 WM_VSCROLL)的使用，请参考 http://msdn.microsoft.com 或使用你喜欢的搜索引擎。同样，查阅 Message Tutorial (消息指南)。

WM_NULL = 0x00
WM_CREATE = 0x01
WM_DESTROY = 0x02
WM_MOVE = 0x03
WM_SIZE = 0x05
WM_ACTIVATE = 0x06
WM_SETFOCUS = 0x07
WM_KILLFOCUS = 0x08
WM_ENABLE = 0x0A
WM_SETREDRAW = 0x0B
WM_SETTEXT = 0x0C
WM_GETTEXT = 0x0D
WM_GETTEXTLENGTH = 0x0E
WM_PAINT = 0x0F
WM_CLOSE = 0x10
WM_QUERYENDSESSION = 0x11
WM_QUIT = 0x12
WM_QUERYOPEN = 0x13
WM_ERASEBKGND = 0x14
WM_SYSCOLORCHANGE = 0x15
WM_ENDSESSION = 0x16
WM_SYSTEMERROR = 0x17
WM_SHOWWINDOW = 0x18
WM_CTLCOLOR = 0x19
WM_WININICHANGE = 0x1A
WM_SETTINGCHANGE = 0x1A
WM_DEVMODECHANGE = 0x1B
WM_ACTIVATEAPP = 0x1C
WM_FONTCHANGE = 0x1D
WM_TIMECHANGE = 0x1E
WM_CANCELMODE = 0x1F
WM_SETCURSOR = 0x20
WM_MOUSEACTIVATE = 0x21
WM_CHILDACTIVATE = 0x22
WM_QUEUESYNC = 0x23
WM_GETMINMAXINFO = 0x24
WM_PAINTICON = 0x26
WM_ICONERASEBKGND = 0x27
WM_NEXTDLGCTL = 0x28
WM_SPOOLERSTATUS = 0x2A
WM_DRAWITEM = 0x2B
WM_MEASUREITEM = 0x2C
WM_DELETEITEM = 0x2D
WM_VKEYTOITEM = 0x2E
WM_CHARTOITEM = 0x2F

WM_SETFONT = 0x30
WM_GETFONT = 0x31
WM_SETHOTKEY = 0x32
WM_GETHOTKEY = 0x33
WM_QUERYDRAGICON = 0x37
WM_COMPAREITEM = 0x39
WM_COMPACTING = 0x41
WM_WINDOWPOSCHANGING = 0x46
WM_WINDOWPOSCHANGED = 0x47
WM_POWER = 0x48
WM_COPYDATA = 0x4A
WM_CANCELJOURNAL = 0x4B
WM_NOTIFY = 0x4E
WM_INPUTLANGCHANGEREQUEST = 0x50
WM_INPUTLANGCHANGE = 0x51
WM_TCARD = 0x52
WM_HELP = 0x53
WM_USERCHANGED = 0x54
WM_NOTIFYFORMAT = 0x55
WM_CONTEXTMENU = 0x7B
WM_STYLECHANGING = 0x7C
WM_STYLECHANGED = 0x7D
WM_DISPLAYCHANGE = 0x7E
WM_GETICON = 0x7F
WM_SETICON = 0x80

WM_NCCREATE = 0x81
WM_NCDESTROY = 0x82
WM_NCCALCSIZE = 0x83
WM_NCHITTEST = 0x84
WM_NCPAINT = 0x85
WM_NCACTIVATE = 0x86
WM_GETDLGCODE = 0x87
WM_NCMOUSEMOVE = 0xA0
WM_NCLBUTTONDOWN = 0xA1
WM_NCLBUTTONUP = 0xA2
WM_NCLBUTTONDBLCLK = 0xA3
WM_NCRBUTTONDOWN = 0xA4
WM_NCRBUTTONUP = 0xA5
WM_NCRBUTTONDBLCLK = 0xA6
WM_NCMBUTTONDOWN = 0xA7
WM_NCMBUTTONUP = 0xA8
WM_NCMBUTTONDBLCLK = 0xA9

WM_KEYFIRST = 0x100
WM_KEYDOWN = 0x100
WM_KEYUP = 0x101
WM_CHAR = 0x102
WM_DEADCHAR = 0x103
WM_SYSKEYDOWN = 0x104
WM_SYSKEYUP = 0x105
WM_SYSCHAR = 0x106
WM_SYSDEADCHAR = 0x107
WM_KEYLAST = 0x108

WM_IME_STARTCOMPOSITION = 0x10D
WM_IME_ENDCOMPOSITION = 0x10E
WM_IME_COMPOSITION = 0x10F
WM_IME_KEYLAST = 0x10F

WM_INITDIALOG = 0x110
WM_COMMAND = 0x111
WM_SYSCOMMAND = 0x112
WM_TIMER = 0x113
WM_HSCROLL = 0x114
WM_VSCROLL = 0x115
WM_INITMENU = 0x116
WM_INITMENUPOPUP = 0x117
WM_MENUSELECT = 0x11F
WM_MENUCHAR = 0x120
WM_ENTERIDLE = 0x121

WM_CTLCOLORMSGBOX = 0x132
WM_CTLCOLOREDIT = 0x133
WM_CTLCOLORLISTBOX = 0x134
WM_CTLCOLORBTN = 0x135
WM_CTLCOLORDLG = 0x136
WM_CTLCOLORSCROLLBAR = 0x137
WM_CTLCOLORSTATIC = 0x138

WM_MOUSEFIRST = 0x200
WM_MOUSEMOVE = 0x200
WM_LBUTTONDOWN = 0x201
WM_LBUTTONUP = 0x202
WM_LBUTTONDBLCLK = 0x203
WM_RBUTTONDOWN = 0x204
WM_RBUTTONUP = 0x205
WM_RBUTTONDBLCLK = 0x206
WM_MBUTTONDOWN = 0x207
WM_MBUTTONUP = 0x208
WM_MBUTTONDBLCLK = 0x209
WM_MOUSEWHEEL = 0x20A
WM_MOUSEHWHEEL = 0x20E

WM_PARENTNOTIFY = 0x210
WM_ENTERMENULOOP = 0x211
WM_EXITMENULOOP = 0x212
WM_NEXTMENU = 0x213
WM_SIZING = 0x214
WM_CAPTURECHANGED = 0x215
WM_MOVING = 0x216
WM_POWERBROADCAST = 0x218
WM_DEVICECHANGE = 0x219

WM_MDICREATE = 0x220
WM_MDIDESTROY = 0x221
WM_MDIACTIVATE = 0x222
WM_MDIRESTORE = 0x223
WM_MDINEXT = 0x224
WM_MDIMAXIMIZE = 0x225
WM_MDITILE = 0x226
WM_MDICASCADE = 0x227
WM_MDIICONARRANGE = 0x228
WM_MDIGETACTIVE = 0x229
WM_MDISETMENU = 0x230
WM_ENTERSIZEMOVE = 0x231
WM_EXITSIZEMOVE = 0x232
WM_DROPFILES = 0x233
WM_MDIREFRESHMENU = 0x234

WM_IME_SETCONTEXT = 0x281
WM_IME_NOTIFY = 0x282
WM_IME_CONTROL = 0x283
WM_IME_COMPOSITIONFULL = 0x284
WM_IME_SELECT = 0x285
WM_IME_CHAR = 0x286
WM_IME_KEYDOWN = 0x290
WM_IME_KEYUP = 0x291

WM_MOUSEHOVER = 0x2A1
WM_NCMOUSELEAVE = 0x2A2
WM_MOUSELEAVE = 0x2A3

WM_CUT = 0x300
WM_COPY = 0x301
WM_PASTE = 0x302
WM_CLEAR = 0x303
WM_UNDO = 0x304

WM_RENDERFORMAT = 0x305
WM_RENDERALLFORMATS = 0x306
WM_DESTROYCLIPBOARD = 0x307
WM_DRAWCLIPBOARD = 0x308
WM_PAINTCLIPBOARD = 0x309
WM_VSCROLLCLIPBOARD = 0x30A
WM_SIZECLIPBOARD = 0x30B
WM_ASKCBFORMATNAME = 0x30C
WM_CHANGECBCHAIN = 0x30D
WM_HSCROLLCLIPBOARD = 0x30E
WM_QUERYNEWPALETTE = 0x30F
WM_PALETTEISCHANGING = 0x310
WM_PALETTECHANGED = 0x311

WM_HOTKEY = 0x312
WM_PRINT = 0x317
WM_PRINTCLIENT = 0x318

WM_HANDHELDFIRST = 0x358
WM_HANDHELDLAST = 0x35F
WM_PENWINFIRST = 0x380
WM_PENWINLAST = 0x38F
WM_COALESCE_FIRST = 0x390
WM_COALESCE_LAST = 0x39F
WM_DDE_FIRST = 0x3E0
WM_DDE_INITIATE = 0x3E0
WM_DDE_TERMINATE = 0x3E1
WM_DDE_ADVISE = 0x3E2
WM_DDE_UNADVISE = 0x3E3
WM_DDE_ACK = 0x3E4
WM_DDE_DATA = 0x3E5
WM_DDE_REQUEST = 0x3E6
WM_DDE_POKE = 0x3E7
WM_DDE_EXECUTE = 0x3E8
WM_DDE_LAST = 0x3E8

WM_USER = 0x400
WM_APP = 0x8000


GUI 样式

用于 Gui 和 GuiControl 命令的可用样式
目录
  • 用于 Gui/所属窗口和大多数控件类型的通用样式
  • Text | Edit | UpDown | Picture
  • Button | Checkbox | Radio | GroupBox
  • DropDownList | ComboBox
  • ListBox | ListView | TreeView
  • DateTime | MonthCal
  • Slider | Progress | Tab | StatusBar

?

通用样式 | 值 | 说明
GUI 窗口默认样式 | ? | WS_POPUP, WS_CAPTION, WS_SYSMENU, WS_MINIMIZEBOX
GUI 窗口强制样式 | ? | WS_CLIPSIBLINGS
WS_BORDER | 0x800000 | +/-Border. 创建含有薄边框的窗口.
WS_POPUP | 0x80000000 | 创建一个弹出窗口.此样式不能和 WS_CHILD 样式一起使用.
WS_CAPTION | 0xC00000 | +/-Caption. 创建含有标题栏的窗口. 此样式是 WS_BORDER 和 WS_DLGFRAME 的数值组合.
WS_DISABLED | 0x8000000 | +/-Disabled. 创建一个初始禁用的窗口.
WS_DLGFRAME | 0x400000 | 创建一个含有常用于对话框的边框样式的窗口.
WS_GROUP | 0x20000 | +/-Group. 表明此控件是一组控件的首个. 此样式自动用于管理 "一次只能选一个" 的单选按钮的行为. 在极少见的情况下, 连续添加两组单选按钮 (它们之间没有其他控件类型), 此时可以手动应用此样式到第二个单选按钮组的首个控件中, 此样式可以使此控件脱离第一个单选按钮组.
WS_HSCROLL | 0x100000 | 创建含有水平滚动条的窗口.
WS_MAXIMIZE | 0x1000000 | 创建初始为最大化的窗口.
WS_MAXIMIZEBOX | 0x10000 | +/-MaximizeBox. 创建含有最大化按钮的窗口. 不能和 WS_EX_CONTEXTHELP 样式联合使用. 必须同时指定 WS_SYSMENU 样式.
WS_MINIMIZE | 0x20000000 | 创建一个初始为最小化的窗口.
WS_MINIMIZEBOX | 0x20000 | +/-MinimizeBox. 创建含最小化按钮的窗口. 不能和 WS_EX_CONTEXTHELP 样式组合使用.必须同时指定 WS_SYSMENU 样式.
WS_OVERLAPPED | 0 | 创建一个重叠的窗口. 重叠的窗口含有标题栏和边框. 与 WS_TILED 样式效果相同.
WS_OVERLAPPEDWINDOW | 0xCF0000 | 创建一个拥有 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, 和 WS_MAXIMIZEBOX 样式的重叠窗口. 与 WS_TILEDWINDOW 样式效果相同.
WS_POPUPWINDOW | 0x80880000 | 创建一个拥有 WS_BORDER, WS_POPUP, 和 WS_SYSMENU 样式的弹出窗口. WS_CAPTION 和 WS_POPUPWINDOW 样式必须组合使用让窗口菜单可见.
WS_SIZEBOX | 0x40000 | +/-Resize. 创建一个含有可调整大小边框的窗口. 与 WS_THICKFRAME 样式效果相同.
WS_SYSMENU | 0x80000 | +/-SysMenu. 创建一个在标题栏有窗口菜单的窗口. 必须同时指定 WS_CAPTION 样式.
WS_TABSTOP | 0x10000 | +/-Tabstop. 指明一个控件在用户按下 TAB 键时可以接收键盘焦点. 按 TAB 键可以把键盘焦点切换到下一个拥有 WS_TABSTOP 样式的控件.
WS_THICKFRAME | 0x40000 | 创建一个含有可调整大小边框的窗口.与 WS_SIZEBOX 样式效果相同
WS_VSCROLL | 0x200000 | 创建含有垂直滚动条的窗口.
WS_VISIBLE | 0x10000000 | 创建初始可见的窗口.
WS_CHILD | 0x40000000 | 创建子窗口. 拥有此样式的窗口不含有菜单栏. 此样式不能和 WS_POPUP 样式一起使用.

?

Text 样式 | 值 | 说明
默认 | ? | 无
强制 | ? | 无
SS_BLACKFRAME | 0x7 | 指定一个带有使用窗体框架颜色描绘的框架的方形框.在默认颜色方案中此颜色为黑色.
SS_BLACKRECT | 0x4 | 指定一个使用当前窗体框架颜色填充的矩形. 在默认颜色方案中此颜色为黑色.
SS_CENTER | 0x1 | +/-Center. 指定一个简单的矩形并在其中居中显示错误值文本. 控件自动换行, 一行末尾多出的文本显示到下一个居中行的开始.
SS_ETCHEDFRAME | 0x12 | 使用 EDGE_ETCHED 边缘样式描绘静态控件边框.
SS_ETCHEDHORZ | 0x10 | 使用 EDGE_ETCHED 样式描绘静态控件的顶部和底部边缘.
SS_ETCHEDVERT | 0x11 | 使用 EDGE_ETCHED 样式描绘静态控件的左右边缘.
SS_GRAYFRAME | 0x8 | 指定一个带有使用屏幕背景 (桌面) 颜色描绘的框架的方形框.在默认颜色方案中此颜色为灰色.
SS_GRAYRECT | 0x5 | 指定一个使用当前屏幕背景颜色填充的矩形. 在默认颜色方案中此颜色为灰色.
SS_LEFT | 0 | +/-Left. 这是默认的. 指定一个简单的矩形并在其中左对齐显示文本. 显示前会格式化文本. 一行末尾超出的单词自动显示到下一个左对齐行的开始. 超出控件宽度的单词被截去.
SS_LEFTNOWORDWRAP | 0xC | +/-Wrap. 指定一个矩形并在其中左对齐显示文本. 制表符是展开的,但文本不换行. 超出一行的文本被截去.
SS_NOPREFIX | 0x80 | 防止控件文本中任何的与符号 (&) 作为用于强调的前缀字符解释. 此样式用于当包含与符号 (&) 的文件名或其他字符串需要显示在文本控件中时
SS_NOTIFY | 0x100 | 当用户点击控件时给所属窗口发送 STN_CLICKED 通告.
SS_RIGHT | 0x2 | +/-Right. 指定一个矩形并在其中右对齐显示指定的文本.
SS_SUNKEN | 0x1000 | 在静态控件周围绘制一个半凹陷边框.
SS_WHITEFRAME | 0x9 | 指定一个带有用窗体背景颜色描绘的框架的方形框. 在默认颜色方案中此颜色为白色.
SS_WHITERECT | 0x6 | 指定一个用当前窗体背景颜色填充的矩形. 在默认颜色方案中此颜色为白色.

?

Edit 样式 | 值 | 说明
默认 | ? | WS_TABSTOP 和 WS_EX_CLIENTEDGE (扩展样式 E0x200) 如果一个 Edit 由于初始内容包含多行, 高度大于 1 行, 或明确指定行数大于 1 而自动检测为多行控件时, 默认将自动应用下列样式: WS_VSCROLL, ES_WANTRETURN, 和 ES_AUTOVSCROLL 如果一个 Edit 自动检测为单行, 它默认含有 ES_AUTOHSCROLL 样式.
强制 | ? | 无
ES_AUTOHSCROLL | 0x80 | 对于多行编辑控件为 +/-Wrap, 而对于单行编辑控件为 +/-Limit. 当用户在一行的末尾输入一个字符时会自动把文本往右滚动 10 个字符. 当用户按下 ENTER 时, 控件把所有文本滚动回到零位置.
ES_AUTOVSCROLL | 0x40 | 当用户在最后一行按下 ENTER 时文本向上滚动一页.
ES_CENTER | 0x1 | +/-Center. 在多行编辑控件中居中显示文本.
ES_LOWERCASE | 0x10 | +/-Lowercase. 把在编辑控件中输入的所有字符转换成小写.
ES_NOHIDESEL | 0x100 | 取消编辑控件的默认行为. 当控件失去输入焦点时默认会不反色显示选区而获得输入焦点时会反色显示选区内容. 如果指定 ES_NOHIDESEL, 即使焦点不在控件上选区内容也反色显示.
ES_NUMBER | 0x2000 | +/-Number. 禁止用户输入数字外的其他内容到控件中.
ES_OEMCONVERT | 0x400 | 此样式对于包含文件名的编辑控件最有用.
ES_MULTILINE | 0x4 | +/-Multi. 指定多行编辑控件. 默认为单行编辑控件.
ES_PASSWORD | 0x20 | +/-Password. 在编辑控件中输入的每个字符的位置显示一个屏蔽字符来隐藏文本.
ES_READONLY | 0x800 | +/-ReadOnly. 禁止用户输入或编辑控件中的文本.
ES_RIGHT | 0x2 | +/-Right. 在多行编辑控件中右对齐显示文本.
ES_UPPERCASE | 0x8 | +/-Uppercase. 把在编辑控件中输入的所有字符转换成大写.
ES_WANTRETURN | 0x1000 | +/-WantReturn. 在对话框的多行编辑控件中输入文本时用户按下回车键则插入回车符. 如果不指定此样式, 按下回车键相当于按下对话框的默认按钮. 此样式对于单行编辑控件没有效果.

?

UpDown 样式 | 值 | 说明
默认 | ? | UDS_ARROWKEYS, UDS_ALIGNRIGHT, UDS_SETBUDDYINT, and UDS_AUTOBUDDY.
强制 | ? | 无
UDS_WRAP | 0x1 | 命名选项 "Wrap". 当用户试图超出最小值或最大值时使得控件返回到其范围的另一端.如果没有 Wrap, 当达到最小值或最大值时控件会停止.
UDS_SETBUDDYINT | 0x2 | 当位置变化时让 UpDown 控件设置其伙伴控件的文本 (使用 WM_SETTEXT 消息). 但是, 如果其伙伴控件为 ListBox, 则改变 ListBox 的当前选区.
UDS_ALIGNRIGHT | 0x4 | 命名选项 "Right" (默认). 定位 UpDown 在其伙伴控件的右边.
UDS_ALIGNLEFT | 0x8 | 命名选项 "Left". 定位 UpDown 在其伙伴控件的左边.
UDS_AUTOBUDDY | 0x10 | 自动选择z顺序中前面的控件作为 UpDown 控件的伙伴控件.
UDS_ARROWKEYS | 0x20 | 允许用户按下键盘上的 Up 或 Down 方向键来增加或减少 UpDown 控件的位置.
UDS_HORZ | 0x40 | 命名选项 "Horz". 使得控件的箭头指向左右而不是上下.
UDS_NOTHOUSANDS | 0x80 | 在伙伴控件中每三个十进制位之间不插入千位分隔符.
UDS_HOTTRACK | 0x100 | 让控件表现出 "热跟踪" 行为. 即鼠标从控件按钮上通过时高亮控件的按钮. 此样式需要 Microsoft Windows 98 或 Windows 2000. 如果运行的系统为 Windows 95 NT4, 此标志被忽略. 在 Windows XP 系统中当桌面主题覆盖此样式时它也被忽略.
(hex) | ? | 在伙伴控件中的数字格式可以从十进制转换为十六进制, 请参照此例: Gui +LastFound SendMessage, 1133, 16, 0, msctls_updown321 ; 1133 is UDM_SETBASE 然而, 此样式只影响伙伴控件, 不影响 UpDown 报告的位置.

?

Picture 样式 | 值 | 说明
默认 | ? | 无
强制 | ? | SS_ICON 适用于图标和光标. SS_BITMAP 适用于其他图像类型.
SS_REALSIZECONTROL | 0x40 | [Windows XP 或更高版本系统] 调整位图以适应控件的大小.
SS_CENTERIMAGE | 0x200 | 让位图在控件中居中显示. 如果位图过大, 它将被裁剪. 对于文本控件如果控件包含单行文本, 则会在控件的可用高度内垂直居中显示文本 Microsoft Windows XP: 此样式位不再使用位图或图标左上角像素的颜色填充控件的未使用部分. 控件的未使用部分将保持为背景颜色.

?

Button, Checkbox, Radio, 和 GroupBox 样式 | 值 | 说明
默认 | ? | BS_MULTILINE (除了 GroupBox 和既没有明确设置高度或宽度也没有在它们的文本中使用任何 CR/LF 字符的按钮, 复选框以及单选按钮) WS_TABSTOP (除了 GroupBox) -- 但是, 每个单选按钮组中除首个外的其他单选按钮默认不含 WS_TABSTOP 样式. 此外, 含有 BS_NOTIFY 样式的单选按钮才可以检测双击.
强制 | ? | Button: BS_PUSHBUTTON 或 BS_DEFPUSHBUTTON Radio: BS_AUTORADIOBUTTON Checkbox: BS_AUTOCHECKBOX 或 BS_AUTO3STATE GroupBox: BS_GROUPBOX
BS_LEFT | 0x100 | +/-Left. 左对齐文本.
BS_PUSHLIKE | 0x1000 | 使复选框或单选按钮外观和行为像按钮一样. 这样按钮当没有按下或复选时是凸起的, 当按下或复选时是凹陷的.
BS_RIGHT | 0x200 | +/-Right. 右对齐文本.
BS_RIGHTBUTTON | 0x20 | +Right (即 +Right 同时包含了 BS_RIGHT 和 BS_RIGHTBUTTON, 但 -Right 仅移除 BS_RIGHT, 而不包括 BS_RIGHTBUTTON). 定位复选框的方形或单选按钮的圆在控件可用宽度的右边而不是左边.
BS_BOTTOM | 0x800 | 定位文本到控件可用高度的底部.
BS_CENTER | 0x300 | +/-Center. 在控件的可用宽度内水平居中显示文本.
BS_DEFPUSHBUTTON | 0x1 | +/-Default. 创建带浓黑边框的按钮. 如果按钮在对话框中, 用户可以按下回车键选择按钮, 即使输入焦点不在按钮上. 此样式用于为用户启用快速选择最常用的选项.
BS_MULTILINE | 0x2000 | +/-Wrap. 如果文本过长无法容纳在控件可用宽度的单行时, 覆盖文本到多行. 此样式同时允许换行符 (`n) 开始文本的新行.
BS_TOP | 0x400 | 定位文本到控件可用高度的顶部.
BS_VCENTER | 0xC00 | 在控件的可用高度中垂直居中显示文本.
BS_FLAT | 0x8000 | 指定按钮为二维的; 它不使用默认的阴影来创建 3D 效果.

?

DropDownList 和 ComboBox 样式 | 值 | 说明
默认 | ? | WS_TABSTOP (+/-Tabstop) DropDownList: WS_VSCROLL ComboBox: WS_VSCROLL, CBS_AUTOHSCROLL
强制 | ? | DropDownList: CBS_DROPDOWNLIST ComboBox: CBS_DROPDOWN 或 CBS_SIMPLE
CBS_AUTOHSCROLL | 0x40 | +/-Limit. 当用户在行末输入一个字符时自动滚动编辑控件中的文本到右边. 如果此样式未设置, 仅启用适合矩形边界内的文本.
CBS_DISABLENOSCROLL | 0x800 | 当列表框中不包含需要滚动的足够项目时显示被禁用的垂直滚动条. 如果不含有此样式, 当列表框中不包含足够的项目时隐藏滚动条.
CBS_LOWERCASE | 0x4000 | +/-Lowercase. 把输入到组合框编辑控件中的所有大写字符转换成小写.
CBS_NOINTEGRALHEIGHT | 0x400 | 指定组合框将准确符合在应用程序创建它时指定的大小. 通常 Windows CE 会调整组合框的大小使得它不会只显示部分项目.
CBS_OEMCONVERT | 0x80 | 把输入到组合框编辑控件中的文本从 Windows CE 字符集转到 OEM 字符集, 然后转回 Windows CE 字符集. 此样式对于包含文件名称的组合框最有用. 它仅适用于创建时含有 CBS_DROPDOWN 样式的组合框.
CBS_SIMPLE | 0x1 | +/-Simple (仅 ComboBox). 总是显示列表框. 在编辑控件中显示列表框中的当前选择对象.
CBS_SORT | 0x100 | +/-Sort. 按字母顺序排列下拉列表中的项目.
CBS_UPPERCASE | 0x2000 | +/-Uppercase. 把输入到组合框编辑控件中的所有小写字符转换成大写.

?

ListBox 样式 | 值 | 说明
默认 | ? | WS_TABSTOP, LBS_USETABSTOPS, WS_VSCROLL, 和 WS_EX_CLIENTEDGE (扩展样式 E0x200).
强制 | ? | LBS_NOTIFY (支持双击的检测)
LBS_DISABLENOSCROLL | 0x1000 | 当列表框中不包含足够项目时显示被禁用的垂直滚动条.如果不指定此样式, 当列表框不包含足够项目时隐藏滚动条.
LBS_NOINTEGRALHEIGHT | 0x100 | 指定列表框将准确符合在应用程序创建它时指定的大小.
LBS_EXTENDEDSEL | 0x800 | +/-Multi. 允许通过 control-click 和 shift-click 选择多项.
LBS_MULTIPLESEL | 0x8 | 选择多项的一种简化方式, 此时不需要使用 control-click 和 shift-click 因为正常的左键单击可以增加选择对象或取消选择之前选择的项目.
LBS_NOSEL | 0x4000 | +/-ReadOnly. 指定用户可以查看列表框字符串但不能选择.
LBS_SORT | 0x2 | +/-Sort. 按字母顺序排列列表框中的项目.
LBS_USETABSTOPS | 0x80 | 当描绘其字符串时启用列表框识别并展开制表符. 默认制表符位置为 32 个对话框单位. 一个对话框单位等于当前对话框基础宽度单位的四分之一.

?

ListView 样式 | 值 | 说明
默认 ? WS_TABSTOP, LVS_REPORT, LVS_SHOWSELALWAYS, LVS_EX_FULLROWSELECT, LVS_EX_HEADERDRAGDROP, WS_EX_CLIENTEDGE (E0x200)
强制 ? 无
LVS_ALIGNLEFT | 0x800 | 在图标和小图标视图中左对齐项目.
LVS_ALIGNTOP | 0 | 在图标和小图标视图中把项目和列表视图控件的顶部对齐. 这是默认的.
LVS_AUTOARRANGE | 0x100 | 在图标和小图标视图中图标自动保持排列的.
LVS_EDITLABELS | 0x200 | +/-ReadOnly. 指定 -ReadOnly (或 +0x200) 允许用户编辑每行首个字段.
LVS_ICON | 0 | +Icon. 指定大图标视图.
LVS_LIST | 0x3 | +List. 指定列表视图.
LVS_NOCOLUMNHEADER | 0x4000 | +/-Hdr. 使报告视图中不显示列标题.
LVS_NOLABELWRAP | 0x80 | 在图标视图中让项目文本显示在单行. 默认情况下, 在图标视图中项目文本可能换行.
LVS_NOSCROLL | 0x2000 | 禁用滚动. 所有项目必须在客户区. 此样式不兼容于 LVS_LIST 或 LVS_REPORT 样式.
LVS_NOSORTHEADER | 0x8000 | +/-NoSortHdr. 列标题不像按钮一样工作. 如果希望在报告视图中点击列标题时不执行一个动作例如排序, 可以使用此样式.
LVS_OWNERDATA | 0x1000 | 此样式指定虚拟列表视图控件 (AutoHotkey 不直接支持).
LVS_OWNERDRAWFIXED | 0x400 | 所有者窗口可以在报告视图中描绘项目来响应 WM_DRAWITEM 消息 (AutoHotkey 不直接支持).
LVS_REPORT | 0x1 | +Report. 指定报告视图.
LVS_SHAREIMAGELISTS | 0x40 | 当销毁控件时 图像列表 将不会被删除. 此样式启用了在多个列表控件中使用相同的图像列表.
LVS_SHOWSELALWAYS | 0x8 | 选择对象, 如果有的话, 总是显示, 即使键盘焦点不在控件上.
LVS_SINGLESEL | 0x4 | +/-Multi. 在同一时刻只能有一个项目是选择的. 默认情况下可以选择多项.
LVS_SMALLICON | 0x2 | +IconSmall. 指定小图标视图.
LVS_SORTASCENDING | 0x10 | +/-Sort. 根据首个字段的内容对行按升序排列.
LVS_SORTDESCENDING | 0x20 | +/-SortDesc. 和上面一样, 除了按降序排列.
LVS_EX_BORDERSELECT | LV0x8000 | 当选择一个项目时, 改变项目边框的颜色而不是高亮显示项目 (在最近的操作系统中可能不起作用).
LVS_EX_CHECKBOXES LV0x4

+/-Checked. 每个项目显示一个复选框. 当设置此样式, 控件使用 DrawFrameControl 创建和设置含有两种图像的状态图像列表. 状态图像 1 为未选中的方框, 而状态 2 为选中的方框. 设置状态图像为零会完全移除复选框.

Windows XP 或更高版本: 除了在 Windows XP 中引入的 tile 视图外的其他列表控件视图模式复选框是可见并具有功能的. 在 tile 视图模式中点击复选框仅选择项目; 而状态不会改变.
LVS_EX_FLATSB | LV0x100 | 启用列表视图中的平坦滚动条.
LVS_EX_FULLROWSELECT | LV0x20 | 当选择一行时, 其所有字段都高亮显示. 此样式只有和 LVS_REPORT 样式组合使用才有效.
LVS_EX_GRIDLINES | LV0x1 | +/-Grid. 在行和列周围显示网格线. 此样式只有和 LVS_REPORT 样式组合使用才有效.
LVS_EX_HEADERDRAGDROP | LV0x10 | 在列表视图控件中启用拖放来对列重新排序. 此样式只有在含有 LVS_REPORT 样式的列表视图控件中才有效.
LVS_EX_INFOTIP | LV0x400 | 当列表视图控件使用 LVS_EX_INFOTIP 样式时, 在显示一个项目的 ToolTip 前会发送 LVN_GETINFOTIP 通告消息到所属窗口.
LVS_EX_LABELTIP | LV0x4000 | 在任何列表视图模式中如果一个部分隐藏的标签没有 ToolTip 文本, 则列表视图控件将展开此标签. 如果此样式未设置, 列表视图控件只有在大图标模式中才展开部分隐藏的标签. 需要 Windows XP 或更高版本, 或随 Internet Explorer 5.0 或更高版本一起发布的 DLL 文件. 注: 在某些版本的 Window 系统中, 如果 GUI 窗口设置为总是置顶此样式可能无法正常工作.
LVS_EX_MULTIWORKAREAS | LV0x2000 | 如果列表视图控件含有 LVS_AUTOARRANGE 样式, 只有在定义了一个或多个工作区域后控件才会自动排列其图标 (参见 LVM_SETWORKAREAS). 只有在定义任何工作区域前并且在添加任何项目到控件前设置此样式才有效.
LVS_EX_ONECLICKACTIVATE | LV0x40 | 当用户双击一个项目时列表视图控件会发送一个 LVN_ITEMACTIVATE 通告消息到所属窗口. 此样式还在列表视图中启用热跟踪. 热跟踪是指当鼠标移至一个项目时, 高亮显示此项目但未选择.
LVS_EX_REGIONAL | LV0x200 | 设置列表视图窗体区域仅包含使用 SetWindowRgn 的项目图标和文本. 任何非一个项目部分的区域被排除出窗体区域. 此样式只有在含有 LVS_ICON 样式的列表视图控件中才有效.
LVS_EX_SIMPLESELECT | LV0x100000 | 在图标视图中, 移动控件的状态图像到大图标效果图的右上角. 在图标视图外的其他视图中没有什么变化. 当用户使用空格键改变状态时, 循环通过所有选定的项目, 而不是含有焦点的项目. 需要 Windows XP 或更高版本的系统.
LVS_EX_SUBITEMIMAGES | LV0x2 | 允许图像显示在首个以后的其他字段. 此样式只有和 LVS_REPORT 样式组合使用才有效.
LVS_EX_TRACKSELECT | LV0x8 | 在列表视图控件中启用热跟踪选择对象. 热跟踪选择对象是指当鼠标悬停在某个项目上一段时间时自动选择此项目. 使用 LVM_SETHOVERTIME 消息可以改变系统默认设置的此延迟时间. 此样式适用于列表视图控件的所有视图模式. 通过调用 SystemParametersInfo 可以检查热跟踪选择对象是否启用.
LVS_EX_TWOCLICKACTIVATE | LV0x80 | 当用户双击一个项目时列表视图控件发送一个 LVN_ITEMACTIVATE 通告消息到所属窗口. 此样式还在列表视图中启用热跟踪.热跟踪是指当鼠标移至一个项目时, 高亮显示此项目但未选择.
LVS_EX_UNDERLINECOLD | LV0x1000 | 使得那些可以被激活的非热项目带有下划线文本显示. 此样式要求同时设置 LVS_EX_TWOCLICKACTIVATE 样式.
LVS_EX_UNDERLINEHOT | LV0x800 | 使得那些可以被激活的热项目带有下划线文本显示. 此样式要求同时设置 LVS_EX_ONECLICKACTIVATE 或 LVS_EX_TWOCLICKACTIVATE 样式.

?

TreeView 样式 | 值 | 说明
默认 | ? | WS_TABSTOP, TVS_SHOWSELALWAYS, TVS_HASLINES, TVS_LINESATROOT, TVS_HASBUTTONS, WS_EX_CLIENTEDGE (E0x200)
强制 | ? | 无
TVS_CHECKBOXES | 0x100 | +/-Checked.每个项目旁边显示一个复选框.
TVS_DISABLEDRAGDROP | 0x10 | 禁止树形视图控件发送 TVN_BEGINDRAG 通告消息.
TVS_EDITLABELS | 0x8 | +/-ReadOnly. 允许用户编辑树形视图项目的名称.
TVS_FULLROWSELECT | 0x1000 | 启用树形视图控件中的全行选择功能. 高亮被选择项目的整行, 并且点击一个项目所在行的任何地方都会选择此项目. 此样式不能和 TVS_HASLINES 样式组合使用.
TVS_HASBUTTONS | 0x1 | +/-Buttons. 在父项目的旁边显示加号 (+) 和 减号 (-) 按钮. 用户点击按钮来展开或折叠父项的子项列表.要在树形视图的根项目中包含按钮, 必须同时指定 TVS_LINESATROOT 样式.
TVS_HASLINES | 0x2 | +/-Lines. 使用线显示项目的层次结构.
TVS_INFOTIP | 0x800 | 通过发送 TVN_GETINFOTIP 通告获得 ToolTip 信息.
TVS_LINESATROOT | 0x4 | +/-Lines.使用线连接树形视图控件的根项目. 如果未指定 TVS_HASLINES 则此样式被忽略.
TVS_NOHSCROLL | 0x8000 | +/-HScroll. 禁用控件中的水平滚动. 控件中将不显示水平滚动条.
TVS_NONEVENHEIGHT | 0x4000 | 设置项目的高度为一个带有 TVM_SETITEMHEIGHT 消息的奇数的高度. 默认情况下, 项目的高度必须是偶数值.
TVS_NOSCROLL | 0x2000 | 同时禁用控件中的水平滚动和垂直滚动. 控件将不显示任何滚动条.
TVS_NOTOOLTIPS | 0x80 | 禁用 ToolTip.
TVS_RTLREADING | 0x40 | 使得文本从右到左 (RTL) 显示. 通常情况下, 窗体按从左到右 (LTR) 的顺序显示文本.
TVS_SHOWSELALWAYS | 0x20 | 使得所选项目保持选择的当树形视图控件失去焦点时.
TVS_SINGLEEXPAND | 0x400 | 在树形控件中选择后展开所选项目并折叠取消选择的项目. 当选择一个项目时如果用户按住 CTRL 键, 被取消选择的项目将不会折叠.
TVS_TRACKSELECT | 0x200 | 在树形视图控件中启用鼠标的热跟踪.

?

DateTime 样式 | 值 | 说明
默认 | ? | DTS_SHORTDATECENTURYFORMAT 和 WS_TABSTOP (+/-Tabstop)
强制 | ? | 无
DTS_UPDOWN | 0x1 | 在控件的右边提供一个增减控件来修改日期和时间的值, 这会取代其他地方可用的下拉月历的修改.
DTS_SHOWNONE | 0x2 | 在控件中显示复选框, 取消复选此复选框可以让控件不选择日期/时间. 当控件中不含日期/时间时, Gui Submit 和 GuiControlGet 命令将获取到一个空值 (空字符串).
DTS_SHORTDATEFORMAT | 0x0 | 显示短格式的日期. 在某些区域设置中, 它看起来像 6/1/05 或 6/1/2005. 在较旧版本的操作系统中, 年份可能显示为两位数. 这是为什么 DTS_SHORTDATECENTURYFORMAT 为默认样式而不是 DTS_SHORTDATEFORMAT.
DTS_LONGDATEFORMAT | 0x4 | Format option "LongDate". 用长格式显示日期.在某些区域设置中, 它看起来像 Wednesday, June 01, 2005.
DTS_SHORTDATECENTURYFORMAT | 0xC | 格式选项 为空/省略. 用短格式显示带有四位年份的日期. 在某些区域设置中, 它看起来像 6/1/2005. 如果系统的 Comctl32.dll 版本低于 5.8, 不支持此样式并自动使用 DTS_SHORTDATEFORMAT 代替.
DTS_TIMEFORMAT | 0x9 | 格式选项 "Time". 仅显示时间, 这在某些区域设置中看起来像 5:31:42 PM.
DTS_APPCANPARSE | 0x10 | 还不支持.允许拥有者分析用户的输入并采取必要的行动. 它启用了当用户按下 F2 时对控件的客户区进行编辑. 当用户完成编辑控件会发送 DTN_USERSTRING 通告消息.
DTS_RIGHTALIGN | 0x20 | +/-Right. 日历将在控件的右边而不是左边拉下.
(下拉日历内的颜色设置) | ? | 下拉日历中天数的颜色服从 Gui Font 命令或 c (Color) 选项的设置. 要改变日历其他部分的颜色, 请参照此例: Gui +LastFound SendMessage, 0x1006, 4, 0xFFAA99, SysDateTimePick321 ; 0x1006 is DTM_SETMCCOLOR. 4 is MCSC_MONTHBK (background color). 颜色必须使用 BGR 与 RGB 格式指定 (交换了红色和蓝色通道).

?

MonthCal 样式 | 值 | 说明
默认 | ? | 无
强制 | ? | 无
MCS_DAYSTATE | 0x1 | 让控件发送 MCN_GETDAYSTATE 通告来请求哪些日子应以粗体显示的信息. [还不支持]
MCS_MULTISELECT | 0x2 | 命名选项 "Multi". 允许用户选择一个日期范围而不限制于单个日期. 默认情况下, 最大的范围为 366 天, 此设置可以通过给控件发送 MCM_SETMAXSELCOUNT 消息改变. 例如: Gui +LastFound SendMessage, 0x1004, 7, 0, SysMonthCal321 ; 7 days. 0x1004 is MCM_SETMAXSELCOUNT.
MCS_WEEKNUMBERS | 0x4 | 在每行日子的左边显示周数 (1-52). Week 1 被定义为至少包含四天的第一周.
MCS_NOTODAYCIRCLE | 0x8 | 禁止控件中的当前日期往复循环.
MCS_NOTODAY | 0x10 | 禁止在控件的底部显示今天的日期.
(颜色) | ? | 日历中的天数颜色服从 Gui Font 命令或 c (Color) 选项的设置. 要改变日历其他部分的颜色, 请参照此例: Gui +LastFound SendMessage, 0x100A, 5, 0xFFAA99, SysMonthCal321 ; 0x100A is MCM_SETCOLOR. 5 is MCSC_TITLETEXT (color of title text). 颜色必须使用 BGR 与 RGB 格式指定 (交换了红色和蓝色通道).

?

Slider 样式 | 值 | 说明
默认 | ? | WS_TABSTOP (+/-Tabstop)
强制 | ? | 无
TBS_VERT | 0x2 | +/-Vertical. 控件是垂直导向的.
TBS_LEFT / TBS_TOP | 0x4 | +/-Left. 控件在其顶端显示刻度线 (如果含有 TBS_VERT 样式则在其左边).
TBS_BOTH | 0x8 | +/-Center. 控件在其两边显示刻度线. 与 TBS_HORZ 一起使用时为顶端和底端而与 TBS_VERT 一起使用时为左右两边.
TBS_AUTOTICKS | 0x1 | 控件在其值范围中的每个增量显示一个刻度线. 使用 +/-TickInterval 可以更灵活.
TBS_ENABLESELRANGE | 0x20 | 控件仅显示一个选择范围. 在选择范围起始位置和结束位置的刻度线显示为三角形 (而不是垂直的短划线), 并且选择范围是高亮的 (高亮可能需要通过 "Gui -theme" 移除主题). 要设置选择范围, 参照此例, 此处设置起始位置为 55 而结束位置为 66: SendMessage, 1035, 1, 55, msctls_trackbar321, WinTitle SendMessage, 1036, 1, 66, msctls_trackbar321, WinTitle
TBS_FIXEDLENGTH | 0x40 | +/-Thick. 允许改变滑块的大小.
TBS_NOTHUMB | 0x80 | 控件不显示可移动的滑块.
TBS_NOTICKS | 0x10 | +/-NoTicks. 控件不显示任何刻度线.
TBS_TOOLTIPS | 0x100 | +/-Tooltip. 控件支持 ToolTip. 当使用此样式创建控件时, 它自动创建一个默认的 ToolTip 控件用以显示滑动条的当前位置. 使用 TBM_SETTIPSIDE 消息可以改变 ToolTip 显示的位置. Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此样式.
TBS_REVERSED | 0x200 | 不幸的是, 此样式对控件的实际行为没有效果, 所以使用它是没有意义的 (作为替代, 在控件的选项中使用 +Invert 来反转它). 根据操作系统版本, 此样式可能需要 Internet Explorer 5.0 或更高版本.
TBS_DOWNISLEFT | 0x400 | 不幸的是, 此样式对控件的实际行为没有效果, 所以使用它是没有意义的. 根据操作系统版本, 此样式可能需要 Internet Explorer 5.01 或更高版本.

?

Progress 样式 | 值 | 说明
默认 | ? | PBS_SMOOTH
强制 | ? | 无
PBS_SMOOTH | 0x1 | +/-Smooth. 进度条使用平滑滚动条而不是默认分段的条显示进度状态. 含有此样式时, 在 Windows XP 或更高版本系统中控件自动恢复到经典主题外观. Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此选项.
PBS_VERTICAL | 0x4 | +/-Vertical.进度条显示垂直的进度状态, 从底部到顶部. Windows 95 和 NT4 需要 Internet Explorer 3.0 或更高版本才能支持此选项.
PBS_MARQUEE | 0x8 | [需要 Windows XP 或更高版本] 进度条的移动是这样的; 其位置的每次变化使得条沿着其可用长度向前滑动直到碰到另一端. 含有此样式的条没有明确的位置. 相反, 每次试图改变位置进度条将移动一格. 此样式常用于指示一个正在进行的操作, 其完成时间是未知的.

?

Tab 样式 | 值 | 说明
默认 | ? | WS_TABSTOP 和 TCS_MULTILINE
强制 | ? | WS_CLIPSIBLINGS TCS_OWNERDRAWFIXED: 根据控件的背景颜色和/或文本颜色的需要强制打开或关闭.
TCS_SCROLLOPPOSITE | 0x1 | 当选择一个标签页时不需要标签页滚动到控件的另一边.
TCS_BOTTOM | 0x2 | +/-Bottom. 标签页显示在控件的底部而不是顶部.
TCS_RIGHT | 0x2 | 标签页垂直显示在使用 TCS_VERTICAL 样式控件的右边.
TCS_MULTISELECT | 0x4 | 按住 CTRL 时进行点击可以选择多个标签页. 此样式必须和 TCS_BUTTONS 样式一起使用.
TCS_FLATBUTTONS | 0x8 | 选择的标签页显示为缩进到背景中而其他标签页和背景显示在相同平面上. 仅在标签控件含有 TCS_BUTTONS 样式时此样式才有效.
TCS_FORCEICONLEFT | 0x10 | 图标和每个固定宽度的左边缘对齐. 此样式只能和 TCS_FIXEDWIDTH 样式一起使用.
TCS_FORCELABELLEFT | 0x20 | 标签和每个固定宽度的标签页左边缘对齐; 即标签紧跟着显示在图标的右边而不是显示在中间. 此样式只能和 TCS_FIXEDWIDTH 样式一起使用, 同时它暗含了 TCS_FORCEICONLEFT 样式.
TCS_HOTTRACK | 0x40 | 在指针下的项目自动高亮显示
TCS_VERTICAL | 0x80 | +/-Left 或 +/-Right. 标签页显示在控件的左边, 并标签页文本垂直显示. 此样式仅在和 TCS_MULTILINE 样式一起使用才有效. 要让标签页显示在控件的右边, 同时使用 TCS_RIGHT 样式. 如果自定义背景颜色或文本颜色有效时, 此样式将无法正确显示标签页. 为了解决此问题, 请在标签控件选项中指定 -Background 和/或 cDefault.
TCS_BUTTONS | 0x100 | +/-Buttons.标签页显示为按钮, 并且在显示区域周围不描绘边框.
TCS_SINGLELINE | 0 | +/-Wrap. 仅显示一行标签. 必要时用户可以滚动查看到更多的标签页. 此样式是默认的.
TCS_MULTILINE | 0x200 | +/-Wrap. 必要时显示多行标签页, 这样所有的标签页可以同时看见.
TCS_RIGHTJUSTIFY | 0 | 这是默认的.必要时可以增加每个标签页的宽度, 这样每行的标签页会填充标签控件的整个宽度. 只有在同时指定 TCS_MULTILINE 样式时此样式才不会被忽略.
TCS_FIXEDWIDTH | 0x400 | 所有标签页使用相同的宽度. 此样式不能和 TCS_RIGHTJUSTIFY 样式一起组合使用.
TCS_RAGGEDRIGHT | 0x800 | 将不会拉伸标签页所在的行来填充控件的整个宽度. 此样式是默认的.
TCS_FOCUSONBUTTONDOWN | 0x1000 | 点击时标签控件接收输入焦点.
TCS_OWNERDRAWFIXED | 0x2000 | 所属窗口负责描绘标签页.
TCS_TOOLTIPS | 0x4000 | 标签控件有与其关联的工具提示控件.
TCS_FOCUSNEVER | 0x8000 | 点击时标签控件不接收输入焦点.

?

StatusBar 样式 | 值 | 说明
默认 ? SBARS_TOOLTIPS 和 SBARS_SIZEGRIP (如果窗口大小可调整则仅后者).
强制 ? 无
SBARS_TOOLTIPS 0x800

当鼠标悬停在状态栏的部分上时显示工具提示: 1) 文本过多以致无法完全显示; 或 2) 含有图标但没有文本.

ToolTip 的文本可以用下面的方法设置:

Gui +LastFound
SendMessage, 0x410, 0, "Text to display", msctls_statusbar321

上面的粗体 0 是从零开始的状态栏部分的编号. 要使用首个外的其他部分, 对第二个指定 1, 对第三个指定 2, 等. 注: 在某些操作版本的系统中 ToolTip 可能永远不会显示.
SBARS_SIZEGRIP | 0x100 | 在状态栏的右端包含一个大小调整手柄. 大小调整手柄类似于大小调整边框; 它是一个矩形区域, 用户可以点击并拖动它来调整所属窗口的大小.


Threads

线程

由最近的热键、定时的子程序、自定义的菜单项 和 GUI 事件所调用的执行流被定义为当前线程。当前线程可以是它自身子程序或由子程序调用的其它子程序中的执行命令。

尽管 AutoHotkey 没有真正地使用多线程，但却模拟了它的特性：如果启动了第二个线程，例如前一个热键仍在执行时又按了另一个热键，那么当前线程将被中断(暂时地停止)以允许新的线程变成当前的线程。如果在第二个线程还在运行时又启动了第三个线程，那么第二个和第一个线程都会进入休眠状态，以此类推。

在当前线程结束时，最近中断的那个线程将被恢复，以此类推，直到所有线程最终结束。在线程被恢复时，它的设置比如 ErrorLevel 和 SendMode 将自动恢复到中断前的状态；换句话说，线程不会受到中断的副作用(除了在激活的窗口中可能有改变 )。

注意: KeyHistory 命令或菜单项显示了有多少线程处于中断状态，ListHotkeys 命令或菜单项显示了哪些热键拥有线程。

一个脚本可以同时产生多个 MsgBox, InputBox, FileSelectFile 和 FileSelectFolder 对话框。这是在先前的线程已经显示了一个对话框的情况下通过启用新线程来实现的(通过热键、定时的子程序、自定义的菜单项等等)。

默认情况下，如果一个给定的热键或热字符串子程序已经运行，那么它不能再次运行。可用 #MaxThreadsPerHotkey 改变此特性。

线程优先级

比当前线程优先级低的线程(热键、定时的子程序、自定义菜单项等等)不能中断它。在这个时候，那些定时器都不会运行，并且如果用户尝试创建线程(比如按下热键或 GUI 按钮)的话，将无任何反应也不会被缓存起来。由于这个原因，通常设计时最好让高优先级的线程尽快结束，或者使用 Critical 而不是将它们设置成高优先级。

默认优先级是 0。所有线程都使用默认优先级除非被下列方法之一所改变:
1) 通过 SetTimer 给一个定时的子程序指定优先级。
2) 通过 Hotkey 命令给一个热键指定优先级。
3) 在定义一个热字符串时指定优先级，或者通过 #Hotstring 指令。
4) 通过 Menu 命令给一个自定义菜单项指定优先级。
5) 通过 Thread 命令来设置当前线程自身的优先级。

不管当前线程的优先级高低，OnExit 子程序(如果有的话)在它被调用时将总能运行起来。


Automating Winamp

自动化 Winamp(某媒体播放器)

这一节主要演示当Winamp处于最小化或非激活状态下时如何通过热键控制Winamp。这些代码已经在 Winamp 2.78c 下测试成功其他发行版应该同样运行得很好。如有错误请到论坛提交改进方法或者联系作者。

这个示例使得 Ctrl+Alt+P 热键等价于按了 Winamp 的暂停/开始按钮:

^!p::
IfWinNotExist ahk_class Winamp v1.x
    return
; 否则, 下面将使用最近使用到的窗口。
ControlSend, ahk_parent, c  ; 暂停/开始
return

下面是 Winamp 2.x (可能其他的版本中也可工作) 中的一些快捷键。上面的示例可以使用下面这些快捷键:

要发送的键 | 效果
c | 暂停/开始
x | 播放/重放/开始
v | 停止
+v | 渐隐停止
^v | 播放该曲后停止
b | 下一曲
z | 上一曲
{left} | 后退五秒钟
{right} | 前进五秒钟
{up} | 增大音量
{down} | 减小音量

; 如下示例获取 Winamp 当前曲目序数:
SendMessage, 1024, 0, 120, ahk_class Winamp v1.x
if ErrorLevel <> FAIL
{
    ErrorLevel += 1  ; Winamp 从 0 开始计数, 所以调整为 1。
    MsgBox, Track #%ErrorLevel% is active or playing.
}


Func Object

Func 对象 [v1.1.00+]

表示可以被脚本调用的用户定义或内置函数.

Call

调用函数.

Func.(Parameters)

参数和返回值由函数定义.

如果 Func 是实现了 __Call 的函数名或用户定义对象, 那么此语法也是有效的.

Name

返回函数的名称.

Func.Name

IsBuiltIn

如果函数是内置的则返回 true, 否则返回 false.

Func.IsBuiltIn

IsVariadic

如果函数是 可变参数的 则返回 true, 否则返回 false.

Func.IsVariadic

MinParams

返回必需的参数数目.

Func.MinParams

MaxParams

对于用户定义函数返回正式声明的参数数目, 对于内置函数返回最大的参数数目.

Func.MaxParams

如果函数是 可变参数的, 返回值表示函数在不考虑 "variadic*" 参数时可以接受的最大参数数目.

IsByRef()

确定一个参数是否为 ByRef 类型.

Func.IsByRef(ParamIndex)
ParamIndex | 可选: 基于 1 的参数索引. 如果省略, 那么返回值表示此函数是否含有 ByRef 参数.
返回值 | 如果函数为内置函数或 ParamIndex 无效时返回空字符串; 否则返回布尔值表示此参数是否为 ByRef 类型.

IsOptional()

确定一个参数是否是可选的.

Func.IsOptional(ParamIndex)
ParamIndex | 可选: 基于 1 的参数索引. 如果省略, 返回值表示此函数是否含有可选参数.
返回值 | 如果 ParamIndex 无效则返回空字符串; 否则返回布尔值表示此参数是否可选.

如果此函数是可变参数的, 那么参数可以不进行正式声明. 支持内置函数.


Context Sensitive Help in Any Editor -- by Rajat

This script makes Ctrl+2 (or another hotkey of your choice) show the help file page for the selected AutoHotkey command or keyword. If nothing is selected, the command name will be extracted from the beginning of the current line.

Download This Script | Other Sample Scripts | Home

; The hotkey below uses the clipboard to provide compatibility with the maximum
; number of editors (since ControlGet doesn't work with most advanced editors).
; It restores the original clipboard contents afterward, but as plain text,
; which seems better than nothing.

$^2::
; The following values are in effect only for the duration of this hotkey thread.
; Therefore, there is no need to change them back to their original values
; because that is done automatically when the thread ends:
SetWinDelay 10
SetKeyDelay 0
AutoTrim, On

if A_OSType = WIN32_WINDOWS  ; Windows 9x
    Sleep, 500  ; Give time for the user to release the key.

C_ClipboardPrev = %clipboard%
clipboard =
; Use the highlighted word if there is one (since sometimes the user might
; intentionally highlight something that isn't a command):
Send, ^c
ClipWait, 0.1
if ErrorLevel <> 0
{
    ; Get the entire line because editors treat cursor navigation keys differently:
    Send, {home}+{end}^c
    ClipWait, 0.2
    if ErrorLevel <> 0  ; Rare, so no error is reported.
    {
        clipboard = %C_ClipboardPrev%
        return
    }
}
C_Cmd = %clipboard%  ; This will trim leading and trailing tabs & spaces.
clipboard = %C_ClipboardPrev%  ; Restore the original clipboard for the user.
Loop, parse, C_Cmd, %A_Space%`,  ; The first space or comma is the end of the command.
{
    C_Cmd = %A_LoopField%
    break ; i.e. we only need one interation.
}
IfWinNotExist, AutoHotkey Help
{
    ; Determine AutoHotkey's location:
    RegRead, ahk_dir, HKEY_LOCAL_MACHINE, SOFTWARE\AutoHotkey, InstallDir
    if ErrorLevel  ; Not found, so look for it in some other common locations.
    {
        if A_AhkPath
            SplitPath, A_AhkPath,, ahk_dir
        else IfExist ..\..\AutoHotkey.chm
            ahk_dir = ..\..
        else IfExist %A_ProgramFiles%\AutoHotkey\AutoHotkey.chm
            ahk_dir = %A_ProgramFiles%\AutoHotkey
        else
        {
            MsgBox Could not find the AutoHotkey folder.
            return
        }
    }
    Run %ahk_dir%\AutoHotkey.chm
    WinWait AutoHotkey Help
}
; The above has set the "last found" window which we use below:
WinActivate
WinWaitActive
StringReplace, C_Cmd, C_Cmd, #, {#}
send, !n{home}+{end}%C_Cmd%{enter}
return


Easy Window Dragging (requires XP/2k/NT)

Normally, a window can only be dragged by clicking on its title bar. This script extends that so that any point inside a window can be dragged. To activate this mode, hold down CapsLock or the middle mouse button while clicking, then drag the window to a new position.

Download This Script | Other Sample Scripts | Home

; Note: You can optionally release Capslock or the middle mouse button after
; pressing down the mouse button rather than holding it down the whole time.
; This script requires v1.0.25+.

~MButton & LButton::
CapsLock & LButton::
CoordMode, Mouse  ; Switch to screen/absolute coordinates.
MouseGetPos, EWD_MouseStartX, EWD_MouseStartY, EWD_MouseWin
WinGetPos, EWD_OriginalPosX, EWD_OriginalPosY,,, ahk_id %EWD_MouseWin%
WinGet, EWD_WinState, MinMax, ahk_id %EWD_MouseWin%
if EWD_WinState = 0  ; Only if the window isn't maximized
    SetTimer, EWD_WatchMouse, 10 ; Track the mouse as the user drags it.
return

EWD_WatchMouse:
GetKeyState, EWD_LButtonState, LButton, P
if EWD_LButtonState = U  ; Button has been released, so drag is complete.
{
    SetTimer, EWD_WatchMouse, off
    return
}
GetKeyState, EWD_EscapeState, Escape, P
if EWD_EscapeState = D  ; Escape has been pressed, so drag is cancelled.
{
    SetTimer, EWD_WatchMouse, off
    WinMove, ahk_id %EWD_MouseWin%,, %EWD_OriginalPosX%, %EWD_OriginalPosY%
    return
}
; Otherwise, reposition the window to match the change in mouse coordinates
; caused by the user having dragged the mouse:
CoordMode, Mouse
MouseGetPos, EWD_MouseX, EWD_MouseY
WinGetPos, EWD_WinX, EWD_WinY,,, ahk_id %EWD_MouseWin%
SetWinDelay, -1   ; Makes the below move faster/smoother.
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY
EWD_MouseStartX := EWD_MouseX  ; Update for the next timer-call to this subroutine.
EWD_MouseStartY := EWD_MouseY
return


Easy Window Dragging -- KDE style (requires XP/2k/NT) -- by Jonny

This script makes it much easier to move or resize a window: 1) Hold down the ALT key and LEFT-click anywhere inside a window to drag it to a new location; 2) Hold down ALT and RIGHT-click-drag anywhere inside a window to easily resize it; 3) Press ALT twice, but before releasing it the second time, left-click to minimize the window under the mouse cursor, right-click to maximize it, or middle-click to close it.

Download This Script | Other Sample Scripts | Home

; This script was inspired by and built on many like it
; in the forum. Thanks go out to ck, thinkstorm, Chris,
; and aurelian for a job well done.

; Change history:
; November 07, 2006: Optimized resizing code in !RButton, courtesy of bluedawn.
; February 05, 2006: Fixed double-alt (the ~Alt hotkey) to work with latest versions of AHK.

; The Double-Alt modifier is activated by pressing
; Alt twice, much like a double-click. Hold the second
; press down until you click.
;
; The shortcuts:
;  Alt + Left Button  : Drag to move a window.
;  Alt + Right Button : Drag to resize a window.
;  Double-Alt + Left Button   : Minimize a window.
;  Double-Alt + Right Button  : Maximize/Restore a window.
;  Double-Alt + Middle Button : Close a window.
;
; You can optionally release Alt after the first
; click rather than holding it down the whole time.

If (A_AhkVersion < "1.0.39.00")
{
    MsgBox,20,,This script may not work properly with your version of AutoHotkey. Continue?
    IfMsgBox,No
    ExitApp
}

; This is the setting that runs smoothest on my
; system. Depending on your video card and cpu
; power, you may want to raise or lower this value.
SetWinDelay,2

CoordMode,Mouse
return

!LButton::
If DoubleAlt
{
    MouseGetPos,,,KDE_id
    ; This message is mostly equivalent to WinMinimize,
    ; but it avoids a bug with PSPad.
    PostMessage,0x112,0xf020,,,ahk_id %KDE_id%
    DoubleAlt := false
    return
}
; Get the initial mouse position and window id, and
; abort if the window is maximized.
MouseGetPos,KDE_X1,KDE_Y1,KDE_id
WinGet,KDE_Win,MinMax,ahk_id %KDE_id%
If KDE_Win
    return
; Get the initial window position.
WinGetPos,KDE_WinX1,KDE_WinY1,,,ahk_id %KDE_id%
Loop
{
    GetKeyState,KDE_Button,LButton,P ; Break if button has been released.
    If KDE_Button = U
        break
    MouseGetPos,KDE_X2,KDE_Y2 ; Get the current mouse position.
    KDE_X2 -= KDE_X1 ; Obtain an offset from the initial mouse position.
    KDE_Y2 -= KDE_Y1
    KDE_WinX2 := (KDE_WinX1 + KDE_X2) ; Apply this offset to the window position.
    KDE_WinY2 := (KDE_WinY1 + KDE_Y2)
    WinMove,ahk_id %KDE_id%,,%KDE_WinX2%,%KDE_WinY2% ; Move the window to the new position.
}
return

!RButton::
If DoubleAlt
{
    MouseGetPos,,,KDE_id
    ; Toggle between maximized and restored state.
    WinGet,KDE_Win,MinMax,ahk_id %KDE_id%
    If KDE_Win
        WinRestore,ahk_id %KDE_id%
    Else
        WinMaximize,ahk_id %KDE_id%
    DoubleAlt := false
    return
}
; Get the initial mouse position and window id, and
; abort if the window is maximized.
MouseGetPos,KDE_X1,KDE_Y1,KDE_id
WinGet,KDE_Win,MinMax,ahk_id %KDE_id%
If KDE_Win
    return
; Get the initial window position and size.
WinGetPos,KDE_WinX1,KDE_WinY1,KDE_WinW,KDE_WinH,ahk_id %KDE_id%
; Define the window region the mouse is currently in.
; The four regions are Up and Left, Up and Right, Down and Left, Down and Right.
If (KDE_X1 < KDE_WinX1 + KDE_WinW / 2)
   KDE_WinLeft := 1
Else
   KDE_WinLeft := -1
If (KDE_Y1 < KDE_WinY1 + KDE_WinH / 2)
   KDE_WinUp := 1
Else
   KDE_WinUp := -1
Loop
{
    GetKeyState,KDE_Button,RButton,P ; Break if button has been released.
    If KDE_Button = U
        break
    MouseGetPos,KDE_X2,KDE_Y2 ; Get the current mouse position.
    ; Get the current window position and size.
    WinGetPos,KDE_WinX1,KDE_WinY1,KDE_WinW,KDE_WinH,ahk_id %KDE_id%
    KDE_X2 -= KDE_X1 ; Obtain an offset from the initial mouse position.
    KDE_Y2 -= KDE_Y1
    ; Then, act according to the defined region.
    WinMove,ahk_id %KDE_id%,, KDE_WinX1 + (KDE_WinLeft+1)/2*KDE_X2  ; X of resized window
                            , KDE_WinY1 +   (KDE_WinUp+1)/2*KDE_Y2  ; Y of resized window
                            , KDE_WinW  -     KDE_WinLeft  *KDE_X2  ; W of resized window
                            , KDE_WinH  -       KDE_WinUp  *KDE_Y2  ; H of resized window
    KDE_X1 := (KDE_X2 + KDE_X1) ; Reset the initial position for the next iteration.
    KDE_Y1 := (KDE_Y2 + KDE_Y1)
}
return

; "Alt + MButton" may be simpler, but I
; like an extra measure of security for
; an operation like this.
!MButton::
If DoubleAlt
{
    MouseGetPos,,,KDE_id
    WinClose,ahk_id %KDE_id%
    DoubleAlt := false
    return
}
return

; This detects "double-clicks" of the alt key.
~Alt::
DoubleAlt := A_PriorHotKey = "~Alt" AND A_TimeSincePriorHotkey < 400
Sleep 0
KeyWait Alt  ; This prevents the keyboard's auto-repeat feature from interfering.
return


Easy Access to Favorite Folders -- by Savage

When you click the middle mouse button while certain types of windows are active, this script displays a menu of your favorite folders. Upon selecting a favorite, the script will instantly switch to that folder within the active window. The following window types are supported: 1) Standard file-open or file-save dialogs; 2) Explorer windows; 3) Console (command prompt) windows. The menu can also be optionally shown for unsupported window types, in which case the chosen favorite will be opened as a new Explorer window.

Download This Script | Other Sample Scripts | Home

; Note: In Windows Explorer, if "View > Toolbars > Address Bar" is
; not enabled, the menu will not be shown if the hotkey chosen below
; has a tilde.  If it does have a tilde, the menu will be shown
; but the favorite will be opened in a new Explorer window rather
; than switching the active Explorer window to that folder.

; CONFIG: CHOOSE YOUR HOTKEY
; If your mouse has more than 3 buttons, you could try using
; XButton1 (the 4th) or XButton2 (the 5th) instead of MButton.
; You could also use a modified mouse button (such as ^MButton) or
; a keyboard hotkey.  In the case of MButton, the tilde (~) prefix
; is used so that MButton's normal functionality is not lost when
; you click in other window types, such as a browser.  The presence
; of a tilde tells the script to avoid showing the menu for
; unsupported window types.  In other words, if there is no tilde,
; the hotkey will always display the menu; and upon selecting a
; favorite while an unsupported window type is active, a new
; Explorer window will be opened to display the contents of that
; folder.
f_Hotkey = ~MButton

; CONFIG: CHOOSE YOUR FAVORITES
; Update the special commented section below to list your favorite
; folders.  Specify the name of the menu item first, followed by a
; semicolon, followed by the name of the actual path of the favorite.
; Use a blank line to create a separator line.

/*
ITEMS IN FAVORITES MENU <-- Do not change this string.
Desktop      ; %A_Desktop%
Favorites    ; %A_Desktop%\..\Favorites
My Documents ; %A_MyDocuments%

Program Files; %A_ProgramFiles%
*/

; END OF CONFIGURATION SECTION
; Do not make changes below this point unless you want to change
; the basic functionality of the script.

#SingleInstance  ; Needed since the hotkey is dynamically created.

Hotkey, %f_Hotkey%, f_DisplayMenu
StringLeft, f_HotkeyFirstChar, f_Hotkey, 1
if f_HotkeyFirstChar = ~  ; Show menu only for certain window types.
    f_AlwaysShowMenu = n
else
    f_AlwaysShowMenu = y

; Used to reliably determine whether script is compiled:
SplitPath, A_ScriptName,,, f_FileExt
if f_FileExt = Exe  ; Read the menu items from an external file.
    f_FavoritesFile = %A_ScriptDir%\Favorites.ini
else  ; Read the menu items directly from this script file.
    f_FavoritesFile = %A_ScriptFullPath%

;----Read the configuration file.
f_AtStartingPos = n
f_MenuItemCount = 0
Loop, Read, %f_FavoritesFile%
{
    if f_FileExt <> Exe
    {
        ; Since the menu items are being read directly from this
        ; script, skip over all lines until the starting line is
        ; arrived at.
        if f_AtStartingPos = n
        {
            IfInString, A_LoopReadLine, ITEMS IN FAVORITES MENU
                f_AtStartingPos = y
            continue  ; Start a new loop iteration.
        }
        ; Otherwise, the closing comment symbol marks the end of the list.
        if A_LoopReadLine = */
            break  ; terminate the loop
    }
    ; Menu separator lines must also be counted to be compatible
    ; with A_ThisMenuItemPos:
    f_MenuItemCount++
    if A_LoopReadLine =  ; Blank indicates a separator line.
        Menu, Favorites, Add
    else
    {
        StringSplit, f_line, A_LoopReadLine, `;
        f_line1 = %f_line1%  ; Trim leading and trailing spaces.
        f_line2 = %f_line2%  ; Trim leading and trailing spaces.
        ; Resolve any references to variables within either field, and
        ; create a new array element containing the path of this favorite:
        Transform, f_path%f_MenuItemCount%, deref, %f_line2%
        Transform, f_line1, deref, %f_line1%
        Menu, Favorites, Add, %f_line1%, f_OpenFavorite
    }
}
return  ;----End of auto-execute section.

;----Open the selected favorite
f_OpenFavorite:
; Fetch the array element that corresponds to the selected menu item:
StringTrimLeft, f_path, f_path%A_ThisMenuItemPos%, 0
if f_path =
    return
if f_class = #32770    ; It's a dialog.
{
    if f_Edit1Pos <>   ; And it has an Edit1 control.
    {
        ; Activate the window so that if the user is middle-clicking
        ; outside the dialog, subsequent clicks will also work:
        WinActivate ahk_id %f_window_id%
        ; Retrieve any filename that might already be in the field so
        ; that it can be restored after the switch to the new folder:
        ControlGetText, f_text, Edit1, ahk_id %f_window_id%
        ControlSetText, Edit1, %f_path%, ahk_id %f_window_id%
        ControlSend, Edit1, {Enter}, ahk_id %f_window_id%
        Sleep, 100  ; It needs extra time on some dialogs or in some cases.
        ControlSetText, Edit1, %f_text%, ahk_id %f_window_id%
        return
    }
    ; else fall through to the bottom of the subroutine to take standard action.
}
else if f_class in ExploreWClass,CabinetWClass  ; In Explorer, switch folders.
{
    if f_Edit1Pos <>   ; And it has an Edit1 control.
    {
        ControlSetText, Edit1, %f_path%, ahk_id %f_window_id%
        ; Tekl reported the following: "If I want to change to Folder L:\folder
        ; then the addressbar shows http://www.L:\folder.com. To solve this,
        ; I added a {right} before {Enter}":
        ControlSend, Edit1, {Right}{Enter}, ahk_id %f_window_id%
        return
    }
    ; else fall through to the bottom of the subroutine to take standard action.
}
else if f_class = ConsoleWindowClass ; In a console window, CD to that directory
{
    WinActivate, ahk_id %f_window_id% ; Because sometimes the mclick deactivates it.
    SetKeyDelay, 0  ; This will be in effect only for the duration of this thread.
    IfInString, f_path, :  ; It contains a drive letter
    {
        StringLeft, f_path_drive, f_path, 1
        Send %f_path_drive%:{enter}
    }
    Send, cd %f_path%{Enter}
    return
}
; Since the above didn't return, one of the following is true:
; 1) It's an unsupported window type but f_AlwaysShowMenu is y (yes).
; 2) It's a supported type but it lacks an Edit1 control to facilitate the custom
;    action, so instead do the default action below.
Run, Explorer %f_path%  ; Might work on more systems without double quotes.
return

;----Display the menu
f_DisplayMenu:
; These first few variables are set here and used by f_OpenFavorite:
WinGet, f_window_id, ID, A
WinGetClass, f_class, ahk_id %f_window_id%
if f_class in #32770,ExploreWClass,CabinetWClass  ; Dialog or Explorer.
    ControlGetPos, f_Edit1Pos,,,, Edit1, ahk_id %f_window_id%
if f_AlwaysShowMenu = n  ; The menu should be shown only selectively.
{
    if f_class in #32770,ExploreWClass,CabinetWClass  ; Dialog or Explorer.
    {
        if f_Edit1Pos =  ; The control doesn't exist, so don't display the menu
            return
    }
    else if f_class <> ConsoleWindowClass
        return ; Since it's some other window type, don't display menu.
}
; Otherwise, the menu should be presented for this type of window:
Menu, Favorites, show
return


IntelliSense -- by Rajat (requires XP/2k/NT)

This script watches while you edit an AutoHotkey script. When it sees you type a command followed by a comma or space, it displays that command's parameter list to guide you. In addition, you can press Ctrl+F1 (or another hotkey of your choice) to display that command's page in the help file. To dismiss the parameter list, press Escape or Enter.

Download This Script | Other Sample Scripts | Home

; Requires v1.0.41+

; CONFIGURATION SECTION: Customize the script with the following variables.

; The hotkey below is pressed to display the current command's page in the
; help file:
I_HelpHotkey = ^F1

; The string below must exist somewhere in the active window's title for
; IntelliSense to be in effect while you're typing.  Make it blank to have
; IntelliSense operate in all windows.  Make it Pad to have it operate in
; editors such as Metapad, Notepad, and Textpad.  Make it .ahk to have it
; operate only when a .ahk file is open in Notepad, Metapad, etc.
I_Editor = pad

; If you wish to have a different icon for this script to distinguish it from
; other scripts in the tray, provide the filename below (leave blank to have
; no icon). For example: E:\stuff\Pics\icons\GeoIcons\Information.ico
I_Icon =

; END OF CONFIGURATION SECTION (do not make changes below this point unless
; you want to change the basic functionality of the script).

SetKeyDelay, 0
#SingleInstance

if I_HelpHotkey <>
    Hotkey, %I_HelpHotkey%, I_HelpHotkey

; Change tray icon (if one was specified in the configuration section above):
if I_Icon <>
    IfExist, %I_Icon%
        Menu, Tray, Icon, %I_Icon%

; Determine AutoHotkey's location:
RegRead, ahk_dir, HKEY_LOCAL_MACHINE, SOFTWARE\AutoHotkey, InstallDir
if ErrorLevel  ; Not found, so look for it in some other common locations.
{
    if A_AhkPath
        SplitPath, A_AhkPath,, ahk_dir
    else IfExist ..\..\AutoHotkey.chm
        ahk_dir = ..\..
    else IfExist %A_ProgramFiles%\AutoHotkey\AutoHotkey.chm
        ahk_dir = %A_ProgramFiles%\AutoHotkey
    else
    {
        MsgBox Could not find the AutoHotkey folder.
        ExitApp
    }
}

ahk_help_file = %ahk_dir%\AutoHotkey.chm

; Read command syntaxes:
Loop, Read, %ahk_dir%\Extras\Editors\Syntax\Commands.txt
{
    I_FullCmd = %A_LoopReadLine%

    ; Directives have a first space instead of a first comma.
    ; So use whichever comes first as the end of the command name:
    StringGetPos, I_cPos, I_FullCmd, `,
    StringGetPos, I_sPos, I_FullCmd, %A_Space%
    if (I_cPos = -1 or (I_cPos > I_sPos and I_sPos <> -1))
        I_EndPos := I_sPos
    else
        I_EndPos := I_cPos

    if I_EndPos <> -1
        StringLeft, I_CurrCmd, I_FullCmd, %I_EndPos%
    else  ; This is a directive/command with no parameters.
        I_CurrCmd = %A_LoopReadLine%

    StringReplace, I_CurrCmd, I_CurrCmd, [,, All
    StringReplace, I_CurrCmd, I_CurrCmd, %A_Space%,, All
    StringReplace, I_FullCmd, I_FullCmd, ``n, `n, All
    StringReplace, I_FullCmd, I_FullCmd, ``t, `t, All

    ; Make arrays of command names and full cmd syntaxes:
    I_Cmd%A_Index% = %I_CurrCmd%
    I_FullCmd%A_Index% = %I_FullCmd%
}

; Use the Input command to watch for commands that the user types:
Loop
{
    ; Editor window check:
    WinGetTitle, ActiveTitle, A
    IfNotInString, ActiveTitle, %I_Editor%
    {
        ToolTip
        Sleep, 500
        Continue
    }

    ; Get all keys till endkey:
    Input, I_Word, V, {enter}{escape}{space}`,
    I_EndKey = %ErrorLevel%

    ; Tooltip is hidden in these cases:
    if I_EndKey in EndKey:Enter,EndKey:Escape
    {
        ToolTip
        Continue
    }

    ; Editor window check again!
    WinGetActiveTitle, ActiveTitle
    IfNotInString, ActiveTitle, %I_Editor%
    {
        ToolTip
        Continue
    }

    ; Compensate for any indentation that is present:
    StringReplace, I_Word, I_Word, %A_Space%,, All
    StringReplace, I_Word, I_Word, %A_Tab%,, All
    if I_Word =
        Continue

    ; Check for commented line:
    StringLeft, I_Check, I_Word, 1
    if (I_Check = ";" or I_Word = "If")  ; "If" seems a little too annoying to show tooltip for.
        Continue

    ; Match word with command:
    I_Index =
    Loop
    {
        ; It helps performance to resolve dynamic variables only once.
        ; In addition, the value put into I_ThisCmd is also used by the
        ; I_HelpHotkey subroutine:
        I_ThisCmd := I_Cmd%A_Index%
        if I_ThisCmd =
            break
        if (I_Word = I_ThisCmd)
        {
            I_Index := A_Index
            I_HelpOn = %I_ThisCmd%
            break
        }
    }

    ; If no match then resume watching user input:
    if I_Index =
        Continue

    ; Show matched command to guide the user:
    I_ThisFullCmd := I_FullCmd%I_Index%
    ToolTip, %I_ThisFullCmd%, A_CaretX, A_CaretY + 20
}

I_HelpHotkey:
WinGetTitle, ActiveTitle, A
IfNotInString, ActiveTitle, %I_Editor%, Return

ToolTip  ; Turn off syntax helper since there is no need for it now.

SetTitleMatchMode, 1  ; In case it's 3. This setting is in effect only for this thread.
IfWinNotExist, AutoHotkey Help
{
    IfNotExist, %ahk_help_file%
    {
        MsgBox, Could not find the help file: %ahk_help_file%.
        return
    }
    Run, %ahk_help_file%
    WinWait, AutoHotkey Help
}

if I_ThisCmd =  ; Instead, use what was most recently typed.
    I_ThisCmd := I_Word

; The above has set the "last found" window which we use below:
WinActivate
WinWaitActive
StringReplace, I_ThisCmd, I_ThisCmd, #, {#}  ; Replace leading #, if any.
Send, !n{home}+{end}%I_HelpOn%{enter}
return


Using a Joystick as a Mouse

This script converts a joystick into a three-button mouse. It allows each button to drag just like a mouse button and it uses virtually no CPU time. Also, it will move the cursor faster depending on how far you push the joystick from center. You can personalize various settings at the top of the script.

Download This Script | Other Sample Scripts | Home

; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 0.30

; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse.  However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThreshold = 3

; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false

; Change these values to use joystick button numbers other than 1, 2, and 3 for
; the left, right, and middle mouse buttons.  Available numbers are 1 through 32.
; Use the Joystick Test Script to find out your joystick's numbers more easily.
ButtonLeft = 1
ButtonRight = 2
ButtonMiddle = 3

; If your joystick has a POV control, you can use it as a mouse wheel.  The
; following value is the number of milliseconds between turns of the wheel.
; Decrease it to have the wheel turn faster:
WheelDelay = 250

; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1

; END OF CONFIG SECTION -- Don't change anything below this point unless you want
; to alter the basic nature of the script.

#SingleInstance

JoystickPrefix = %JoystickNumber%Joy
Hotkey, %JoystickPrefix%%ButtonLeft%, ButtonLeft
Hotkey, %JoystickPrefix%%ButtonRight%, ButtonRight
Hotkey, %JoystickPrefix%%ButtonMiddle%, ButtonMiddle

; Calculate the axis displacements that are needed to start moving the cursor:
JoyThresholdUpper := 50 + JoyThreshold
JoyThresholdLower := 50 - JoyThreshold
if InvertYAxis
    YAxisMultiplier = -1
else
    YAxisMultiplier = 1

SetTimer, WatchJoystick, 10  ; Monitor the movement of the joystick.

GetKeyState, JoyInfo, %JoystickNumber%JoyInfo
IfInString, JoyInfo, P  ; Joystick has POV control, so use it as a mouse wheel.
    SetTimer, MouseWheel, %WheelDelay%

return  ; End of auto-execute section.

; The subroutines below do not use KeyWait because that would sometimes trap the
; WatchJoystick quasi-thread beneath the wait-for-button-up thread, which would
; effectively prevent mouse-dragging with the joystick.

ButtonLeft:
SetMouseDelay, -1  ; Makes movement smoother.
MouseClick, left,,, 1, 0, D  ; Hold down the left mouse button.
SetTimer, WaitForLeftButtonUp, 10
return

ButtonRight:
SetMouseDelay, -1  ; Makes movement smoother.
MouseClick, right,,, 1, 0, D  ; Hold down the right mouse button.
SetTimer, WaitForRightButtonUp, 10
return

ButtonMiddle:
SetMouseDelay, -1  ; Makes movement smoother.
MouseClick, middle,,, 1, 0, D  ; Hold down the right mouse button.
SetTimer, WaitForMiddleButtonUp, 10
return

WaitForLeftButtonUp:
if GetKeyState(JoystickPrefix . ButtonLeft)
    return  ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForLeftButtonUp, off
SetMouseDelay, -1  ; Makes movement smoother.
MouseClick, left,,, 1, 0, U  ; Release the mouse button.
return

WaitForRightButtonUp:
if GetKeyState(JoystickPrefix . ButtonRight)
    return  ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForRightButtonUp, off
MouseClick, right,,, 1, 0, U  ; Release the mouse button.
return

WaitForMiddleButtonUp:
if GetKeyState(JoystickPrefix . ButtonMiddle)
    return  ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForMiddleButtonUp, off
MouseClick, middle,,, 1, 0, U  ; Release the mouse button.
return

WatchJoystick:
MouseNeedsToBeMoved := false  ; Set default.
SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY
if joyx > %JoyThresholdUpper%
{
    MouseNeedsToBeMoved := true
    DeltaX := joyx - JoyThresholdUpper
}
else if joyx < %JoyThresholdLower%
{
    MouseNeedsToBeMoved := true
    DeltaX := joyx - JoyThresholdLower
}
else
    DeltaX = 0
if joyy > %JoyThresholdUpper%
{
    MouseNeedsToBeMoved := true
    DeltaY := joyy - JoyThresholdUpper
}
else if joyy < %JoyThresholdLower%
{
    MouseNeedsToBeMoved := true
    DeltaY := joyy - JoyThresholdLower
}
else
    DeltaY = 0
if MouseNeedsToBeMoved
{
    SetMouseDelay, -1  ; Makes movement smoother.
    MouseMove, DeltaX * JoyMultiplier, DeltaY * JoyMultiplier * YAxisMultiplier, 0, R
}
return

MouseWheel:
GetKeyState, JoyPOV, %JoystickNumber%JoyPOV
if JoyPOV = -1  ; No angle.
    return
if (JoyPOV > 31500 or JoyPOV < 4500)  ; Forward
    Send {WheelUp}
else if JoyPOV between 13500 and 22500  ; Back
    Send {WheelDown}
return


Joystick Test Script

This script helps determine the button numbers and other attributes of your joystick. It might also reveal if your joystick is in need of calibration; that is, whether the range of motion of each of its axes is from 0 to 100 percent as it should be. If calibration is needed, use the operating system's control panel or the software that came with your joystick.

Download This Script | Other Sample Scripts | Home

; July 6, 2005: Added auto-detection of joystick number.
; May 8, 2005 : Fixed: JoyAxes is no longer queried as a means of
; detecting whether the joystick is connected.  Some joysticks are
; gamepads and don't have even a single axis.

; If you want to unconditionally use a specific joystick number, change
; the following value from 0 to the number of the joystick (1-32).
; A value of 0 causes the joystick number to be auto-detected:
JoystickNumber = 0

; END OF CONFIG SECTION. Do not make changes below this point unless
; you wish to alter the basic functionality of the script.

; Auto-detect the joystick number if called for:
if JoystickNumber <= 0
{
    Loop 32  ; Query each joystick number to find out which ones exist.
    {
        GetKeyState, JoyName, %A_Index%JoyName
        if JoyName <>
        {
            JoystickNumber = %A_Index%
            break
        }
    }
    if JoystickNumber <= 0
    {
        MsgBox The system does not appear to have any joysticks.
        ExitApp
    }
}

#SingleInstance
SetFormat, float, 03  ; Omit decimal point from axis position percentages.
GetKeyState, joy_buttons, %JoystickNumber%JoyButtons
GetKeyState, joy_name, %JoystickNumber%JoyName
GetKeyState, joy_info, %JoystickNumber%JoyInfo
Loop
{
    buttons_down =
    Loop, %joy_buttons%
    {
        GetKeyState, joy%a_index%, %JoystickNumber%joy%a_index%
        if joy%a_index% = D
            buttons_down = %buttons_down%%a_space%%a_index%
    }
    GetKeyState, joyx, %JoystickNumber%JoyX
    axis_info = X%joyx%
    GetKeyState, joyy, %JoystickNumber%JoyY
    axis_info = %axis_info%%a_space%%a_space%Y%joyy%
    IfInString, joy_info, Z
    {
        GetKeyState, joyz, %JoystickNumber%JoyZ
        axis_info = %axis_info%%a_space%%a_space%Z%joyz%
    }
    IfInString, joy_info, R
    {
        GetKeyState, joyr, %JoystickNumber%JoyR
        axis_info = %axis_info%%a_space%%a_space%R%joyr%
    }
    IfInString, joy_info, U
    {
        GetKeyState, joyu, %JoystickNumber%JoyU
        axis_info = %axis_info%%a_space%%a_space%U%joyu%
    }
    IfInString, joy_info, V
    {
        GetKeyState, joyv, %JoystickNumber%JoyV
        axis_info = %axis_info%%a_space%%a_space%V%joyv%
    }
    IfInString, joy_info, P
    {
        GetKeyState, joyp, %JoystickNumber%JoyPOV
        axis_info = %axis_info%%a_space%%a_space%POV%joyp%
    }
    ToolTip, %joy_name% (#%JoystickNumber%):`n%axis_info%`nButtons Down: %buttons_down%`n`n(right-click the tray icon to exit)
    Sleep, 100
}
return


On-Screen Keyboard (requires XP/2k/NT) -- by Jon

This script creates a mock keyboard at the bottom of your screen that shows the keys you are pressing in real time. I made it to help me to learn to touch-type (to get used to not looking at the keyboard). The size of the on-screen keyboard can be customized at the top of the script. Also, you can double-click the tray icon to show or hide the keyboard.

Download This Script | Other Sample Scripts | Home

;---- Configuration Section: Customize the size of the on-screen keyboard and
; other options here.

; Changing this font size will make the entire on-screen keyboard get
; larger or smaller:
k_FontSize = 10
k_FontName = Verdana  ; This can be blank to use the system's default font.
k_FontStyle = Bold    ; Example of an alternative: Italic Underline

; Names for the tray menu items:
k_MenuItemHide = Hide on-screen &keyboard
k_MenuItemShow = Show on-screen &keyboard

; To have the keyboard appear on a monitor other than the primary, specify
; a number such as 2 for the following variable.  Leave it blank to use
; the primary:
k_Monitor =

;---- End of configuration section.  Don't change anything below this point
; unless you want to alter the basic nature of the script.

;---- Alter the tray icon menu:
Menu, Tray, Add, %k_MenuItemHide%, k_ShowHide
Menu, Tray, Add, &Exit, k_MenuExit
Menu, Tray, Default, %k_MenuItemHide%
Menu, Tray, NoStandard

;---- Calculate object dimensions based on chosen font size:
k_KeyWidth = %k_FontSize%
k_KeyWidth *= 3
k_KeyHeight = %k_FontSize%
k_KeyHeight *= 3
k_KeyMargin = %k_FontSize%
k_KeyMargin /= 6
k_SpacebarWidth = %k_FontSize%
k_SpacebarWidth *= 25
k_KeyWidthHalf = %k_KeyWidth%
k_KeyWidthHalf /= 2

k_KeySize = w%k_KeyWidth% h%k_KeyHeight%
k_Position = x+%k_KeyMargin% %k_KeySize%

;---- Create a GUI window for the on-screen keyboard:
Gui, Font, s%k_FontSize% %k_FontStyle%, %k_FontName%
Gui, -Caption +E0x200 +ToolWindow
TransColor = F1ECED
Gui, Color, %TransColor%  ; This color will be made transparent later below.

;---- Add a button for each key. Position the first button with absolute
; coordinates so that all other buttons can be positioned relative to it:
Gui, Add, Button, section %k_KeySize% xm+%k_KeyWidth%, 1
Gui, Add, Button, %k_Position%, 2
Gui, Add, Button, %k_Position%, 3
Gui, Add, Button, %k_Position%, 4
Gui, Add, Button, %k_Position%, 5
Gui, Add, Button, %k_Position%, 6
Gui, Add, Button, %k_Position%, 7
Gui, Add, Button, %k_Position%, 8
Gui, Add, Button, %k_Position%, 9
Gui, Add, Button, %k_Position%, 0
Gui, Add, Button, %k_Position%, -
Gui, Add, Button, %k_Position%, =
Gui, Add, Button, %k_Position%, Bk

Gui, Add, Button, xm y+%k_KeyMargin% h%k_KeyHeight%, Tab  ; Auto-width.
Gui, Add, Button, %k_Position%, Q
Gui, Add, Button, %k_Position%, W
Gui, Add, Button, %k_Position%, E
Gui, Add, Button, %k_Position%, R
Gui, Add, Button, %k_Position%, T
Gui, Add, Button, %k_Position%, Y
Gui, Add, Button, %k_Position%, U
Gui, Add, Button, %k_Position%, I
Gui, Add, Button, %k_Position%, O
Gui, Add, Button, %k_Position%, P
Gui, Add, Button, %k_Position%, [
Gui, Add, Button, %k_Position%, ]
Gui, Add, Button, %k_Position%, \

Gui, Add, Button, xs+%k_KeyWidthHalf% y+%k_KeyMargin% %k_KeySize%, A
Gui, Add, Button, %k_Position%, S
Gui, Add, Button, %k_Position%, D
Gui, Add, Button, %k_Position%, F
Gui, Add, Button, %k_Position%, G
Gui, Add, Button, %k_Position%, H
Gui, Add, Button, %k_Position%, J
Gui, Add, Button, %k_Position%, K
Gui, Add, Button, %k_Position%, L
Gui, Add, Button, %k_Position%, `;
Gui, Add, Button, %k_Position%, '
Gui, Add, Button, x+%k_KeyMargin% h%k_KeyHeight%, Enter  ; Auto-width.

; The first button below adds %A_Space% at the end to widen it a little,
; making the layout of keys next to it more accurately reflect a real keyboard:
Gui, Add, Button, xm y+%k_KeyMargin% h%k_KeyHeight%, Shift%A_Space%%A_Space%
Gui, Add, Button, %k_Position%, Z
Gui, Add, Button, %k_Position%, X
Gui, Add, Button, %k_Position%, C
Gui, Add, Button, %k_Position%, V
Gui, Add, Button, %k_Position%, B
Gui, Add, Button, %k_Position%, N
Gui, Add, Button, %k_Position%, M
Gui, Add, Button, %k_Position%, `,
Gui, Add, Button, %k_Position%, .
Gui, Add, Button, %k_Position%, /

Gui, Add, Button, xm y+%k_KeyMargin% h%k_KeyHeight%, Ctrl  ; Auto-width.
Gui, Add, Button, h%k_KeyHeight% x+%k_KeyMargin%, Win      ; Auto-width.
Gui, Add, Button, h%k_KeyHeight% x+%k_KeyMargin%, Alt      ; Auto-width.
Gui, Add, Button, h%k_KeyHeight% x+%k_KeyMargin% w%k_SpacebarWidth%, Space

;---- Show the window:
Gui, Show
k_IsVisible = y

WinGet, k_ID, ID, A   ; Get its window ID.
WinGetPos,,, k_WindowWidth, k_WindowHeight, A

;---- Position the keyboard at the bottom of the screen (taking into account
; the position of the taskbar):
SysGet, k_WorkArea, MonitorWorkArea, %k_Monitor%

; Calculate window's X-position:
k_WindowX = %k_WorkAreaRight%
k_WindowX -= %k_WorkAreaLeft%  ; Now k_WindowX contains the width of this monitor.
k_WindowX -= %k_WindowWidth%
k_WindowX /= 2  ; Calculate position to center it horizontally.
; The following is done in case the window will be on a non-primary monitor
; or if the taskbar is anchored on the left side of the screen:
k_WindowX += %k_WorkAreaLeft%

; Calculate window's Y-position:
k_WindowY = %k_WorkAreaBottom%
k_WindowY -= %k_WindowHeight%

WinMove, A,, %k_WindowX%, %k_WindowY%
WinSet, AlwaysOnTop, On, ahk_id %k_ID%
WinSet, TransColor, %TransColor% 220, ahk_id %k_ID%

;---- Set all keys as hotkeys. See www.asciitable.com
k_n = 1
k_ASCII = 45

Loop
{
    Transform, k_char, Chr, %k_ASCII%
    StringUpper, k_char, k_char
    if k_char not in <,>,^,~,,`,
        Hotkey, ~*%k_char%, k_KeyPress
        ; In the above, the asterisk prefix allows the key to be detected regardless
        ; of whether the user is holding down modifier keys such as Control and Shift.
    if k_ASCII = 93
        break
    k_ASCII++
}

return ; End of auto-execute section.

;---- When a key is pressed by the user, click the corresponding button on-screen:

~*Backspace::
ControlClick, Bk, ahk_id %k_ID%, , LEFT, 1, D
KeyWait, Backspace
ControlClick, Bk, ahk_id %k_ID%, , LEFT, 1, U
return

; LShift and RShift are used rather than "Shift" because when used as a hotkey,
; "Shift" would default to firing upon release of the key (in older AHK versions):
~*LShift::
~*RShift::
~*LCtrl::  ; Must use Ctrl not Control to match button names.
~*RCtrl::
~*LAlt::
~*RAlt::
~*LWin::
~*RWin::
StringTrimLeft, k_ThisHotkey, A_ThisHotkey, 3
ControlClick, %k_ThisHotkey%, ahk_id %k_ID%, , LEFT, 1, D
KeyWait, %k_ThisHotkey%
ControlClick, %k_ThisHotkey%, ahk_id %k_ID%, , LEFT, 1, U
return

~*,::
~*'::
~*Space::
~*Enter::
~*Tab::
k_KeyPress:
StringReplace, k_ThisHotkey, A_ThisHotkey, ~
StringReplace, k_ThisHotkey, k_ThisHotkey, *
SetTitleMatchMode, 3  ; Prevents the T and B keys from being confused with Tab and Backspace.
ControlClick, %k_ThisHotkey%, ahk_id %k_ID%, , LEFT, 1, D
KeyWait, %k_ThisHotkey%
ControlClick, %k_ThisHotkey%, ahk_id %k_ID%, , LEFT, 1, U
Return

k_ShowHide:
if k_IsVisible = y
{
    Gui, Cancel
    Menu, Tray, Rename, %k_MenuItemHide%, %k_MenuItemShow%
    k_IsVisible = n
}
else
{
    Gui, Show
    Menu, Tray, Rename, %k_MenuItemShow%, %k_MenuItemHide%
    k_IsVisible = y
}
return

GuiClose:
k_MenuExit:
ExitApp


Minimize Window to Tray Menu

This script assigns a hotkey of your choice to hide any window so that it becomes an entry at the bottom of the script's tray menu. Hidden windows can then be unhidden individually or all at once by selecting the corresponding item on the menu. If the script exits for any reason, all the windows that it hid will be unhidden automatically.

Download This Script | Other Sample Scripts | Home

; CHANGES:
; July 22, 2005 (changes provided by egilmour):
; - Added new hotkey to unhide the last hidden window (Win+U)
;
; November 3, 2004 (changes provided by trogdor):
; - Program manager is prevented from being hidden.
; - If there is no active window, the minimize-to-tray hotkey will have
;   no effect rather than waiting indefinitely.
;
; October 23, 2004:
; - The taskbar is prevented from being hidden.
; - Some possible problems with long window titles have been fixed.
; - Windows without a title can be hidden without causing problems.
; - If the script is running under AHK v1.0.22 or greater, the
;   maximum length of each menu item is increased from 100 to 260.

; CONFIGURATION SECTION: Change the below values as desired.

; This is the maximum number of windows to allow to be hidden (having a
; limit helps performance):
mwt_MaxWindows = 50

; This is the hotkey used to hide the active window:
mwt_Hotkey = #h  ; Win+H

; This is the hotkey used to unhide the last hidden window:
mwt_UnHotkey = #u  ; Win+U

; If you prefer to have the tray menu empty of all the standard items,
; such as Help and Pause, use N.  Otherwise, use Y:
mwt_StandardMenu = N

; These next few performance settings help to keep the action within the
; #HotkeyModifierTimeout period, and thus avoid the need to release and
; press down the hotkey's modifier if you want to hide more than one
; window in a row.  These settings are not needed you choose to have the
; script use the keyboard hook via #InstallKeybdHook or other means:
#HotkeyModifierTimeout 100
SetWinDelay 10
SetKeyDelay 0

#SingleInstance  ; Allow only one instance of this script to be running.

; END OF CONFIGURATION SECTION (do not make changes below this point
; unless you want to change the basic functionality of the script).

Hotkey, %mwt_Hotkey%, mwt_Minimize
Hotkey, %mwt_UnHotkey%, mwt_UnMinimize

; If the user terminates the script by any means, unhide all the
; windows first:
OnExit, mwt_RestoreAllThenExit

if mwt_StandardMenu = Y
    Menu, Tray, Add
else
{
    Menu, Tray, NoStandard
    Menu, Tray, Add, E&xit and Unhide All, mwt_RestoreAllThenExit
}
Menu, Tray, Add, &Unhide All Hidden Windows, mwt_RestoreAll
Menu, Tray, Add  ; Another separator line to make the above more special.

if a_AhkVersion =   ; Since it's blank, version is older than 1.0.22.
    mwt_MaxLength = 100
else
    mwt_MaxLength = 260  ; Reduce this to restrict the width of the menu.

return  ; End of auto-execute section.

mwt_Minimize:
if mwt_WindowCount >= %mwt_MaxWindows%
{
    MsgBox No more than %mwt_MaxWindows% may be hidden simultaneously.
    return
}

; Set the "last found window" to simplify and help performance.
; Since in certain cases it is possible for there to be no active window,
; a timeout has been added:
WinWait, A,, 2
if ErrorLevel <> 0  ; It timed out, so do nothing.
    return

; Otherwise, the "last found window" has been set and can now be used:
WinGet, mwt_ActiveID, ID
WinGetTitle, mwt_ActiveTitle
WinGetClass, mwt_ActiveClass
if mwt_ActiveClass in Shell_TrayWnd,Progman
{
    MsgBox The desktop and taskbar cannot be hidden.
    return
}
; Because hiding the window won't deactivate it, activate the window
; beneath this one (if any). I tried other ways, but they wound up
; activating the task bar.  This way sends the active window (which is
; about to be hidden) to the back of the stack, which seems best:
Send, !{esc}
; Hide it only now that WinGetTitle/WinGetClass above have been run (since
; by default, those commands cannot detect hidden windows):
WinHide

; If the title is blank, use the class instead.  This serves two purposes:
; 1) A more meaningful name is used as the menu name.
; 2) Allows the menu item to be created (otherwise, blank items wouldn't
;    be handled correctly by the various routines below).
if mwt_ActiveTitle =
    mwt_ActiveTitle = ahk_class %mwt_ActiveClass%
; Ensure the title is short enough to fit. mwt_ActiveTitle also serves to
; uniquely identify this particular menu item.
StringLeft, mwt_ActiveTitle, mwt_ActiveTitle, %mwt_MaxLength%

; In addition to the tray menu requiring that each menu item name be
; unique, it must also be unique so that we can reliably look it up in
; the array when the window is later unhidden.  So make it unique if it
; isn't already:
Loop, %mwt_MaxWindows%
{
    if mwt_WindowTitle%a_index% = %mwt_ActiveTitle%
    {
        ; Match found, so it's not unique.
        ; First remove the 0x from the hex number to conserve menu space:
        StringTrimLeft, mwt_ActiveIDShort, mwt_ActiveID, 2
        StringLen, mwt_ActiveIDShortLength, mwt_ActiveIDShort
        StringLen, mwt_ActiveTitleLength, mwt_ActiveTitle
        mwt_ActiveTitleLength += %mwt_ActiveIDShortLength%
        mwt_ActiveTitleLength += 1 ; +1 the 1 space between title & ID.
        if mwt_ActiveTitleLength > %mwt_MaxLength%
        {
            ; Since menu item names are limted in length, trim the title
            ; down to allow just enough room for the Window's Short ID at
            ; the end of its name:
            TrimCount = %mwt_ActiveTitleLength%
            TrimCount -= %mwt_MaxLength%
            StringTrimRight, mwt_ActiveTitle, mwt_ActiveTitle, %TrimCount%
        }
        ; Build unique title:
        mwt_ActiveTitle = %mwt_ActiveTitle% %mwt_ActiveIDShort%
        break
    }
}

; First, ensure that this ID doesn't already exist in the list, which can
; happen if a particular window was externally unhidden (or its app unhid
; it) and now it's about to be re-hidden:
mwt_AlreadyExists = n
Loop, %mwt_MaxWindows%
{
    if mwt_WindowID%a_index% = %mwt_ActiveID%
    {
        mwt_AlreadyExists = y
        break
    }
}

; Add the item to the array and to the menu:
if mwt_AlreadyExists = n
{
    Menu, Tray, add, %mwt_ActiveTitle%, RestoreFromTrayMenu
    mwt_WindowCount += 1
    Loop, %mwt_MaxWindows%  ; Search for a free slot.
    {
        ; It should always find a free slot if things are designed right.
        if mwt_WindowID%a_index% =  ; An empty slot was found.
        {
            mwt_WindowID%a_index% = %mwt_ActiveID%
            mwt_WindowTitle%a_index% = %mwt_ActiveTitle%
            break
        }
    }
}
return

RestoreFromTrayMenu:
Menu, Tray, delete, %A_ThisMenuItem%
; Find window based on its unique title stored as the menu item name:
Loop, %mwt_MaxWindows%
{
    if mwt_WindowTitle%a_index% = %A_ThisMenuItem%  ; Match found.
    {
        StringTrimRight, IDToRestore, mwt_WindowID%a_index%, 0
        WinShow, ahk_id %IDToRestore%
        WinActivate ahk_id %IDToRestore%  ; Sometimes needed.
        mwt_WindowID%a_index% =  ; Make it blank to free up a slot.
        mwt_WindowTitle%a_index% =
        mwt_WindowCount -= 1
        break
    }
}
return

;; This will pop the last minimized window off the stack and unhide it.
mwt_UnMinimize:
;; Make sure there's something to unhide.
if mwt_WindowCount > 0
{
    ;; Get the id of the last window minimized and unhide it
    StringTrimRight, IDToRestore, mwt_WindowID%mwt_WindowCount%, 0
    WinShow, ahk_id %IDToRestore%
    WinActivate ahk_id %IDToRestore%

    ;; Get the menu name of the last window minimized and remove it
    StringTrimRight, MenuToRemove, mwt_WindowTitle%mwt_WindowCount%, 0
    Menu, Tray, delete, %MenuToRemove%

    ;; clean up our 'arrays' and decrement the window count
    mwt_WindowID%mwt_WindowCount% =
    mwt_WindowTitle%mwt_WindowCount% =
    mwt_WindowCount -= 1
}
return

mwt_RestoreAllThenExit:
Gosub, mwt_RestoreAll
ExitApp  ; Do a true exit.

mwt_RestoreAll:
Loop, %mwt_MaxWindows%
{
    if mwt_WindowID%a_index% <>
    {
        StringTrimRight, IDToRestore, mwt_WindowID%a_index%, 0
        WinShow, ahk_id %IDToRestore%
        WinActivate ahk_id %IDToRestore%  ; Sometimes needed.
        ; Do it this way vs. DeleteAll so that the sep. line and first
        ; item are retained:
        StringTrimRight, MenuToRemove, mwt_WindowTitle%a_index%, 0
        Menu, Tray, delete, %MenuToRemove%
        mwt_WindowID%a_index% =  ; Make it blank to free up a slot.
        mwt_WindowTitle%a_index% =
        mwt_WindowCount -= 1
    }
    if mwt_WindowCount = 0
        break
}
return


Mouse Gestures -- by deguix

This script watches how you move the mouse whenever the right mouse button is being held down. If it sees you "draw" a recognized shape or symbol, it will launch a program or perform another custom action of your choice (just like hotkeys). See the included README file for how to define gestures.


Changing MsgBox's Button Names

This is a working example script that uses a timer to change the names of the buttons in a MsgBox dialog. Although the button names are changed, the IfMsgBox command still requires that the buttons be referred to by their original names.

Download This Script | Other Sample Scripts | Home

#SingleInstance
SetTimer, ChangeButtonNames, 50
MsgBox, 4, Add or Delete, Choose a button:
IfMsgBox, YES
    MsgBox, You chose Add.
else
    MsgBox, You chose Delete.
return

ChangeButtonNames:
IfWinNotExist, Add or Delete
    return  ; Keep waiting.
SetTimer, ChangeButtonNames, off
WinActivate
ControlSetText, Button1, &Add
ControlSetText, Button2, &Delete
return


Numpad 000 Key

This example script makes the special 000 key that appears on certain keypads into an equals key. You can change the action by replacing the “Send, =” line with line(s) of your choice.

Download This Script | Other Sample Scripts | Home

#MaxThreadsPerHotkey 5  ; Allow multiple threads for this hotkey.
$Numpad0::
#MaxThreadsPerHotkey 1
; Above: Use the $ to force the hook to be used, which prevents an
; infinite loop since this subroutine itself sends Numpad0, which
; would otherwise result in a recursive call to itself.
SetBatchLines, 100 ; Make it run a little faster in this case.
DelayBetweenKeys = 30 ; Adjust this value if it doesn't work.
if A_PriorHotkey = %A_ThisHotkey%
{
    if A_TimeSincePriorHotkey < %DelayBetweenKeys%
    {
        if Numpad0Count =
            Numpad0Count = 2 ; i.e. This one plus the prior one.
        else if Numpad0Count = 0
            Numpad0Count = 2
        else
        {
            ; Since we're here, Numpad0Count must be 2 as set by
            ; prior calls, which means this is the third time the
            ; the key has been pressed. Thus, the hotkey sequence
            ; should fire:
            Numpad0Count = 0
            Send, = ; ******* This is the action for the 000 key
        }
        ; In all the above cases, we return without further action:
        CalledReentrantly = y
        return
    }
}
; Otherwise, this Numpad0 event is either the first in the series
; or it happened too long after the first one (e.g. perhaps the
; user is holding down the Numpad0 key to auto-repeat it, which
; we want to allow).  Therefore, after a short delay -- during
; which another Numpad0 hotkey event may re-entrantly call this
; subroutine -- we'll send the key on through if no reentrant
; calls occurred:
Numpad0Count = 0
CalledReentrantly = n
; During this sleep, this subroutine may be reentrantly called
; (i.e. a simultaneous "thread" which runs in parallel to the
; call we're in now):
Sleep, %DelayBetweenKeys%
if CalledReentrantly = y ; Another "thread" changed the value.
{
    ; Since it was called reentrantly, this key event was the first in
    ; the sequence so should be suppressed (hidden from the system):
    CalledReentrantly = n
    return
}
; Otherwise it's not part of the sequence so we send it through normally.
; In other words, the *real* Numpad0 key has been pressed, so we want it
; to have its normal effect:
Send, {Numpad0}
return


Using Keyboard Numpad as a Mouse -- by deguix

This script makes mousing with your keyboard almost as easy as using a real mouse (maybe even easier for some tasks). It supports up to five mouse buttons and the turning of the mouse wheel. It also features customizable movement speed, acceleration, and "axis inversion".

Download This Script | Other Sample Scripts | Home

/*
o------------------------------------------------------------o
|Using Keyboard Numpad as a Mouse                            |
(------------------------------------------------------------)
| By deguix           / A Script file for AutoHotkey 1.0.22+ |
|                    ----------------------------------------|
|                                                            |
|    This script is an example of use of AutoHotkey. It uses |
| the remapping of numpad keys of a keyboard to transform it |
| into a mouse. Some features are the acceleration which     |
| enables you to increase the mouse movement when holding    |
| a key for a long time, and the rotation which makes the    |
| numpad mouse to "turn". I.e. NumPadDown as NumPadUp        |
| and vice-versa. See the list of keys used below:           |
|                                                            |
|------------------------------------------------------------|
| Keys                  | Description                        |
|------------------------------------------------------------|
| ScrollLock (toggle on)| Activates numpad mouse mode.       |
|-----------------------|------------------------------------|
| NumPad0               | Left mouse button click.           |
| NumPad5               | Middle mouse button click.         |
| NumPadDot             | Right mouse button click.          |
| NumPadDiv/NumPadMult  | X1/X2 mouse button click. (Win 2k+)|
| NumPadSub/NumPadAdd   | Moves up/down the mouse wheel.     |
|                       |                                    |
|-----------------------|------------------------------------|
| NumLock (toggled off) | Activates mouse movement mode.     |
|-----------------------|------------------------------------|
| NumPadEnd/Down/PgDn/  | Mouse movement.                    |
| /Left/Right/Home/Up/  |                                    |
| /PgUp                 |                                    |
|                       |                                    |
|-----------------------|------------------------------------|
| NumLock (toggled on)  | Activates mouse speed adj. mode.   |
|-----------------------|------------------------------------|
| NumPad7/NumPad1       | Inc./dec. acceleration per         |
|                       | button press.                      |
| NumPad8/NumPad2       | Inc./dec. initial speed per        |
|                       | button press.                      |
| NumPad9/NumPad3       | Inc./dec. maximum speed per        |
|                       | button press.                      |
| ^NumPad7/^NumPad1     | Inc./dec. wheel acceleration per   |
|                       | button press*.                     |
| ^NumPad8/^NumPad2     | Inc./dec. wheel initial speed per  |
|                       | button press*.                     |
| ^NumPad9/^NumPad3     | Inc./dec. wheel maximum speed per  |
|                       | button press*.                     |
| NumPad4/NumPad6       | Inc./dec. rotation angle to        |
|                       | right in degrees. (i.e. 180° =     |
|                       | = inversed controls).              |
|------------------------------------------------------------|
| * = These options are affected by the mouse wheel speed    |
| adjusted on Control Panel. If you don't have a mouse with  |
| wheel, the default is 3 +/- lines per option button press. |
o------------------------------------------------------------o
*/

;START OF CONFIG SECTION

#SingleInstance force
#MaxHotkeysPerInterval 500

; Using the keyboard hook to implement the Numpad hotkeys prevents
; them from interfering with the generation of ANSI characters such
; as à.  This is because AutoHotkey generates such characters
; by holding down ALT and sending a series of Numpad keystrokes.
; Hook hotkeys are smart enough to ignore such keystrokes.
#UseHook

MouseSpeed = 1
MouseAccelerationSpeed = 1
MouseMaxSpeed = 5

;Mouse wheel speed is also set on Control Panel. As that
;will affect the normal mouse behavior, the real speed of
;these three below are times the normal mouse wheel speed.
MouseWheelSpeed = 1
MouseWheelAccelerationSpeed = 1
MouseWheelMaxSpeed = 5

MouseRotationAngle = 0

;END OF CONFIG SECTION

;This is needed or key presses would faulty send their natural
;actions. Like NumPadDiv would send sometimes "/" to the
;screen.
#InstallKeybdHook

Temp = 0
Temp2 = 0

MouseRotationAnglePart = %MouseRotationAngle%
;Divide by 45º because MouseMove only supports whole numbers,
;and changing the mouse rotation to a number lesser than 45º
;could make strange movements.
;
;For example: 22.5º when pressing NumPadUp:
;  First it would move upwards until the speed
;  to the side reaches 1.
MouseRotationAnglePart /= 45

MouseCurrentAccelerationSpeed = 0
MouseCurrentSpeed = %MouseSpeed%

MouseWheelCurrentAccelerationSpeed = 0
MouseWheelCurrentSpeed = %MouseSpeed%

SetKeyDelay, -1
SetMouseDelay, -1

Hotkey, *NumPad0, ButtonLeftClick
Hotkey, *NumpadIns, ButtonLeftClickIns
Hotkey, *NumPad5, ButtonMiddleClick
Hotkey, *NumpadClear, ButtonMiddleClickClear
Hotkey, *NumPadDot, ButtonRightClick
Hotkey, *NumPadDel, ButtonRightClickDel
Hotkey, *NumPadDiv, ButtonX1Click
Hotkey, *NumPadMult, ButtonX2Click

Hotkey, *NumpadSub, ButtonWheelUp
Hotkey, *NumpadAdd, ButtonWheelDown

Hotkey, *NumPadUp, ButtonUp
Hotkey, *NumPadDown, ButtonDown
Hotkey, *NumPadLeft, ButtonLeft
Hotkey, *NumPadRight, ButtonRight
Hotkey, *NumPadHome, ButtonUpLeft
Hotkey, *NumPadEnd, ButtonUpRight
Hotkey, *NumPadPgUp, ButtonDownLeft
Hotkey, *NumPadPgDn, ButtonDownRight

Hotkey, Numpad8, ButtonSpeedUp
Hotkey, Numpad2, ButtonSpeedDown
Hotkey, Numpad7, ButtonAccelerationSpeedUp
Hotkey, Numpad1, ButtonAccelerationSpeedDown
Hotkey, Numpad9, ButtonMaxSpeedUp
Hotkey, Numpad3, ButtonMaxSpeedDown

Hotkey, Numpad6, ButtonRotationAngleUp
Hotkey, Numpad4, ButtonRotationAngleDown

Hotkey, !Numpad8, ButtonWheelSpeedUp
Hotkey, !Numpad2, ButtonWheelSpeedDown
Hotkey, !Numpad7, ButtonWheelAccelerationSpeedUp
Hotkey, !Numpad1, ButtonWheelAccelerationSpeedDown
Hotkey, !Numpad9, ButtonWheelMaxSpeedUp
Hotkey, !Numpad3, ButtonWheelMaxSpeedDown

Gosub, ~ScrollLock  ; Initialize based on current ScrollLock state.
return

;Key activation support

~ScrollLock::
; Wait for it to be released because otherwise the hook state gets reset
; while the key is down, which causes the up-event to get suppressed,
; which in turn prevents toggling of the ScrollLock state/light:
KeyWait, ScrollLock
GetKeyState, ScrollLockState, ScrollLock, T
If ScrollLockState = D
{
    Hotkey, *NumPad0, on
    Hotkey, *NumpadIns, on
    Hotkey, *NumPad5, on
    Hotkey, *NumPadDot, on
    Hotkey, *NumPadDel, on
    Hotkey, *NumPadDiv, on
    Hotkey, *NumPadMult, on

    Hotkey, *NumpadSub, on
    Hotkey, *NumpadAdd, on

    Hotkey, *NumPadUp, on
    Hotkey, *NumPadDown, on
    Hotkey, *NumPadLeft, on
    Hotkey, *NumPadRight, on
    Hotkey, *NumPadHome, on
    Hotkey, *NumPadEnd, on
    Hotkey, *NumPadPgUp, on
    Hotkey, *NumPadPgDn, on

    Hotkey, Numpad8, on
    Hotkey, Numpad2, on
    Hotkey, Numpad7, on
    Hotkey, Numpad1, on
    Hotkey, Numpad9, on
    Hotkey, Numpad3, on

    Hotkey, Numpad6, on
    Hotkey, Numpad4, on

    Hotkey, !Numpad8, on
    Hotkey, !Numpad2, on
    Hotkey, !Numpad7, on
    Hotkey, !Numpad1, on
    Hotkey, !Numpad9, on
    Hotkey, !Numpad3, on
}
else
{
    Hotkey, *NumPad0, off
    Hotkey, *NumpadIns, off
    Hotkey, *NumPad5, off
    Hotkey, *NumPadDot, off
    Hotkey, *NumPadDel, off
    Hotkey, *NumPadDiv, off
    Hotkey, *NumPadMult, off

    Hotkey, *NumpadSub, off
    Hotkey, *NumpadAdd, off

    Hotkey, *NumPadUp, off
    Hotkey, *NumPadDown, off
    Hotkey, *NumPadLeft, off
    Hotkey, *NumPadRight, off
    Hotkey, *NumPadHome, off
    Hotkey, *NumPadEnd, off
    Hotkey, *NumPadPgUp, off
    Hotkey, *NumPadPgDn, off

    Hotkey, Numpad8, off
    Hotkey, Numpad2, off
    Hotkey, Numpad7, off
    Hotkey, Numpad1, off
    Hotkey, Numpad9, off
    Hotkey, Numpad3, off

    Hotkey, Numpad6, off
    Hotkey, Numpad4, off

    Hotkey, !Numpad8, off
    Hotkey, !Numpad2, off
    Hotkey, !Numpad7, off
    Hotkey, !Numpad1, off
    Hotkey, !Numpad9, off
    Hotkey, !Numpad3, off
}
return

;Mouse click support

ButtonLeftClick:
GetKeyState, already_down_state, LButton
If already_down_state = D
    return
Button2 = NumPad0
ButtonClick = Left
Goto ButtonClickStart
ButtonLeftClickIns:
GetKeyState, already_down_state, LButton
If already_down_state = D
    return
Button2 = NumPadIns
ButtonClick = Left
Goto ButtonClickStart

ButtonMiddleClick:
GetKeyState, already_down_state, MButton
If already_down_state = D
    return
Button2 = NumPad5
ButtonClick = Middle
Goto ButtonClickStart
ButtonMiddleClickClear:
GetKeyState, already_down_state, MButton
If already_down_state = D
    return
Button2 = NumPadClear
ButtonClick = Middle
Goto ButtonClickStart

ButtonRightClick:
GetKeyState, already_down_state, RButton
If already_down_state = D
    return
Button2 = NumPadDot
ButtonClick = Right
Goto ButtonClickStart
ButtonRightClickDel:
GetKeyState, already_down_state, RButton
If already_down_state = D
    return
Button2 = NumPadDel
ButtonClick = Right
Goto ButtonClickStart

ButtonX1Click:
GetKeyState, already_down_state, XButton1
If already_down_state = D
    return
Button2 = NumPadDiv
ButtonClick = X1
Goto ButtonClickStart

ButtonX2Click:
GetKeyState, already_down_state, XButton2
If already_down_state = D
    return
Button2 = NumPadMult
ButtonClick = X2
Goto ButtonClickStart

ButtonClickStart:
MouseClick, %ButtonClick%,,, 1, 0, D
SetTimer, ButtonClickEnd, 10
return

ButtonClickEnd:
GetKeyState, kclickstate, %Button2%, P
if kclickstate = D
    return

SetTimer, ButtonClickEnd, off
MouseClick, %ButtonClick%,,, 1, 0, U
return

;Mouse movement support

ButtonSpeedUp:
MouseSpeed++
ToolTip, Mouse speed: %MouseSpeed% pixels
SetTimer, RemoveToolTip, 1000
return
ButtonSpeedDown:
If MouseSpeed > 1
    MouseSpeed--
If MouseSpeed = 1
    ToolTip, Mouse speed: %MouseSpeed% pixel
else
    ToolTip, Mouse speed: %MouseSpeed% pixels
SetTimer, RemoveToolTip, 1000
return
ButtonAccelerationSpeedUp:
MouseAccelerationSpeed++
ToolTip, Mouse acceleration speed: %MouseAccelerationSpeed% pixels
SetTimer, RemoveToolTip, 1000
return
ButtonAccelerationSpeedDown:
If MouseAccelerationSpeed > 1
    MouseAccelerationSpeed--
If MouseAccelerationSpeed = 1
    ToolTip, Mouse acceleration speed: %MouseAccelerationSpeed% pixel
else
    ToolTip, Mouse acceleration speed: %MouseAccelerationSpeed% pixels
SetTimer, RemoveToolTip, 1000
return

ButtonMaxSpeedUp:
MouseMaxSpeed++
ToolTip, Mouse maximum speed: %MouseMaxSpeed% pixels
SetTimer, RemoveToolTip, 1000
return
ButtonMaxSpeedDown:
If MouseMaxSpeed > 1
    MouseMaxSpeed--
If MouseMaxSpeed = 1
    ToolTip, Mouse maximum speed: %MouseMaxSpeed% pixel
else
    ToolTip, Mouse maximum speed: %MouseMaxSpeed% pixels
SetTimer, RemoveToolTip, 1000
return

ButtonRotationAngleUp:
MouseRotationAnglePart++
If MouseRotationAnglePart >= 8
    MouseRotationAnglePart = 0
MouseRotationAngle = %MouseRotationAnglePart%
MouseRotationAngle *= 45
ToolTip, Mouse rotation angle: %MouseRotationAngle%°
SetTimer, RemoveToolTip, 1000
return
ButtonRotationAngleDown:
MouseRotationAnglePart--
If MouseRotationAnglePart < 0
    MouseRotationAnglePart = 7
MouseRotationAngle = %MouseRotationAnglePart%
MouseRotationAngle *= 45
ToolTip, Mouse rotation angle: %MouseRotationAngle%°
SetTimer, RemoveToolTip, 1000
return

ButtonUp:
ButtonDown:
ButtonLeft:
ButtonRight:
ButtonUpLeft:
ButtonUpRight:
ButtonDownLeft:
ButtonDownRight:
If Button <> 0
{
    IfNotInString, A_ThisHotkey, %Button%
    {
        MouseCurrentAccelerationSpeed = 0
        MouseCurrentSpeed = %MouseSpeed%
    }
}
StringReplace, Button, A_ThisHotkey, *

ButtonAccelerationStart:
If MouseAccelerationSpeed >= 1
{
    If MouseMaxSpeed > %MouseCurrentSpeed%
    {
        Temp = 0.001
        Temp *= %MouseAccelerationSpeed%
        MouseCurrentAccelerationSpeed += %Temp%
        MouseCurrentSpeed += %MouseCurrentAccelerationSpeed%
    }
}

;MouseRotationAngle convertion to speed of button direction
{
    MouseCurrentSpeedToDirection = %MouseRotationAngle%
    MouseCurrentSpeedToDirection /= 90.0
    Temp = %MouseCurrentSpeedToDirection%

    if Temp >= 0
    {
        if Temp < 1
        {
            MouseCurrentSpeedToDirection = 1
            MouseCurrentSpeedToDirection -= %Temp%
            Goto EndMouseCurrentSpeedToDirectionCalculation
        }
    }
    if Temp >= 1
    {
        if Temp < 2
        {
            MouseCurrentSpeedToDirection = 0
            Temp -= 1
            MouseCurrentSpeedToDirection -= %Temp%
            Goto EndMouseCurrentSpeedToDirectionCalculation
        }
    }
    if Temp >= 2
    {
        if Temp < 3
        {
            MouseCurrentSpeedToDirection = -1
            Temp -= 2
            MouseCurrentSpeedToDirection += %Temp%
            Goto EndMouseCurrentSpeedToDirectionCalculation
        }
    }
    if Temp >= 3
    {
        if Temp < 4
        {
            MouseCurrentSpeedToDirection = 0
            Temp -= 3
            MouseCurrentSpeedToDirection += %Temp%
            Goto EndMouseCurrentSpeedToDirectionCalculation
        }
    }
}
EndMouseCurrentSpeedToDirectionCalculation:

;MouseRotationAngle convertion to speed of 90 degrees to right
{
    MouseCurrentSpeedToSide = %MouseRotationAngle%
    MouseCurrentSpeedToSide /= 90.0
    Temp = %MouseCurrentSpeedToSide%
    Transform, Temp, mod, %Temp%, 4

    if Temp >= 0
    {
        if Temp < 1
        {
            MouseCurrentSpeedToSide = 0
            MouseCurrentSpeedToSide += %Temp%
            Goto EndMouseCurrentSpeedToSideCalculation
        }
    }
    if Temp >= 1
    {
        if Temp < 2
        {
            MouseCurrentSpeedToSide = 1
            Temp -= 1
            MouseCurrentSpeedToSide -= %Temp%
            Goto EndMouseCurrentSpeedToSideCalculation
        }
    }
    if Temp >= 2
    {
        if Temp < 3
        {
            MouseCurrentSpeedToSide = 0
            Temp -= 2
            MouseCurrentSpeedToSide -= %Temp%
            Goto EndMouseCurrentSpeedToSideCalculation
        }
    }
    if Temp >= 3
    {
        if Temp < 4
        {
            MouseCurrentSpeedToSide = -1
            Temp -= 3
            MouseCurrentSpeedToSide += %Temp%
            Goto EndMouseCurrentSpeedToSideCalculation
        }
    }
}
EndMouseCurrentSpeedToSideCalculation:

MouseCurrentSpeedToDirection *= %MouseCurrentSpeed%
MouseCurrentSpeedToSide *= %MouseCurrentSpeed%

Temp = %MouseRotationAnglePart%
Transform, Temp, Mod, %Temp%, 2

If Button = NumPadUp
{
    if Temp = 1
    {
        MouseCurrentSpeedToSide *= 2
        MouseCurrentSpeedToDirection *= 2
    }

    MouseCurrentSpeedToDirection *= -1
    MouseMove, %MouseCurrentSpeedToSide%, %MouseCurrentSpeedToDirection%, 0, R
}
else if Button = NumPadDown
{
    if Temp = 1
    {
        MouseCurrentSpeedToSide *= 2
        MouseCurrentSpeedToDirection *= 2
    }

    MouseCurrentSpeedToSide *= -1
    MouseMove, %MouseCurrentSpeedToSide%, %MouseCurrentSpeedToDirection%, 0, R
}
else if Button = NumPadLeft
{
    if Temp = 1
    {
        MouseCurrentSpeedToSide *= 2
        MouseCurrentSpeedToDirection *= 2
    }

    MouseCurrentSpeedToSide *= -1
    MouseCurrentSpeedToDirection *= -1

    MouseMove, %MouseCurrentSpeedToDirection%, %MouseCurrentSpeedToSide%, 0, R
}
else if Button = NumPadRight
{
    if Temp = 1
    {
        MouseCurrentSpeedToSide *= 2
        MouseCurrentSpeedToDirection *= 2
    }

    MouseMove, %MouseCurrentSpeedToDirection%, %MouseCurrentSpeedToSide%, 0, R
}
else if Button = NumPadHome
{
    Temp = %MouseCurrentSpeedToDirection%
    Temp -= %MouseCurrentSpeedToSide%
    Temp *= -1
    Temp2 = %MouseCurrentSpeedToDirection%
    Temp2 += %MouseCurrentSpeedToSide%
    Temp2 *= -1
    MouseMove, %Temp%, %Temp2%, 0, R
}
else if Button = NumPadPgUp
{
    Temp = %MouseCurrentSpeedToDirection%
    Temp += %MouseCurrentSpeedToSide%
    Temp2 = %MouseCurrentSpeedToDirection%
    Temp2 -= %MouseCurrentSpeedToSide%
    Temp2 *= -1
    MouseMove, %Temp%, %Temp2%, 0, R
}
else if Button = NumPadEnd
{
    Temp = %MouseCurrentSpeedToDirection%
    Temp += %MouseCurrentSpeedToSide%
    Temp *= -1
    Temp2 = %MouseCurrentSpeedToDirection%
    Temp2 -= %MouseCurrentSpeedToSide%
    MouseMove, %Temp%, %Temp2%, 0, R
}
else if Button = NumPadPgDn
{
    Temp = %MouseCurrentSpeedToDirection%
    Temp -= %MouseCurrentSpeedToSide%
    Temp2 *= -1
    Temp2 = %MouseCurrentSpeedToDirection%
    Temp2 += %MouseCurrentSpeedToSide%
    MouseMove, %Temp%, %Temp2%, 0, R
}

SetTimer, ButtonAccelerationEnd, 10
return

ButtonAccelerationEnd:
GetKeyState, kstate, %Button%, P
if kstate = D
    Goto ButtonAccelerationStart

SetTimer, ButtonAccelerationEnd, off
MouseCurrentAccelerationSpeed = 0
MouseCurrentSpeed = %MouseSpeed%
Button = 0
return

;Mouse wheel movement support

ButtonWheelSpeedUp:
MouseWheelSpeed++
RegRead, MouseWheelSpeedMultiplier, HKCU, Control Panel\Desktop, WheelScrollLines
If MouseWheelSpeedMultiplier <= 0
    MouseWheelSpeedMultiplier = 1
MouseWheelSpeedReal = %MouseWheelSpeed%
MouseWheelSpeedReal *= %MouseWheelSpeedMultiplier%
ToolTip, Mouse wheel speed: %MouseWheelSpeedReal% lines
SetTimer, RemoveToolTip, 1000
return
ButtonWheelSpeedDown:
RegRead, MouseWheelSpeedMultiplier, HKCU, Control Panel\Desktop, WheelScrollLines
If MouseWheelSpeedMultiplier <= 0
    MouseWheelSpeedMultiplier = 1
If MouseWheelSpeedReal > %MouseWheelSpeedMultiplier%
{
    MouseWheelSpeed--
    MouseWheelSpeedReal = %MouseWheelSpeed%
    MouseWheelSpeedReal *= %MouseWheelSpeedMultiplier%
}
If MouseWheelSpeedReal = 1
    ToolTip, Mouse wheel speed: %MouseWheelSpeedReal% line
else
    ToolTip, Mouse wheel speed: %MouseWheelSpeedReal% lines
SetTimer, RemoveToolTip, 1000
return

ButtonWheelAccelerationSpeedUp:
MouseWheelAccelerationSpeed++
RegRead, MouseWheelSpeedMultiplier, HKCU, Control Panel\Desktop, WheelScrollLines
If MouseWheelSpeedMultiplier <= 0
    MouseWheelSpeedMultiplier = 1
MouseWheelAccelerationSpeedReal = %MouseWheelAccelerationSpeed%
MouseWheelAccelerationSpeedReal *= %MouseWheelSpeedMultiplier%
ToolTip, Mouse wheel acceleration speed: %MouseWheelAccelerationSpeedReal% lines
SetTimer, RemoveToolTip, 1000
return
ButtonWheelAccelerationSpeedDown:
RegRead, MouseWheelSpeedMultiplier, HKCU, Control Panel\Desktop, WheelScrollLines
If MouseWheelSpeedMultiplier <= 0
    MouseWheelSpeedMultiplier = 1
If MouseWheelAccelerationSpeed > 1
{
    MouseWheelAccelerationSpeed--
    MouseWheelAccelerationSpeedReal = %MouseWheelAccelerationSpeed%
    MouseWheelAccelerationSpeedReal *= %MouseWheelSpeedMultiplier%
}
If MouseWheelAccelerationSpeedReal = 1
    ToolTip, Mouse wheel acceleration speed: %MouseWheelAccelerationSpeedReal% line
else
    ToolTip, Mouse wheel acceleration speed: %MouseWheelAccelerationSpeedReal% lines
SetTimer, RemoveToolTip, 1000
return

ButtonWheelMaxSpeedUp:
MouseWheelMaxSpeed++
RegRead, MouseWheelSpeedMultiplier, HKCU, Control Panel\Desktop, WheelScrollLines
If MouseWheelSpeedMultiplier <= 0
    MouseWheelSpeedMultiplier = 1
MouseWheelMaxSpeedReal = %MouseWheelMaxSpeed%
MouseWheelMaxSpeedReal *= %MouseWheelSpeedMultiplier%
ToolTip, Mouse wheel maximum speed: %MouseWheelMaxSpeedReal% lines
SetTimer, RemoveToolTip, 1000
return
ButtonWheelMaxSpeedDown:
RegRead, MouseWheelSpeedMultiplier, HKCU, Control Panel\Desktop, WheelScrollLines
If MouseWheelSpeedMultiplier <= 0
    MouseWheelSpeedMultiplier = 1
If MouseWheelMaxSpeed > 1
{
    MouseWheelMaxSpeed--
    MouseWheelMaxSpeedReal = %MouseWheelMaxSpeed%
    MouseWheelMaxSpeedReal *= %MouseWheelSpeedMultiplier%
}
If MouseWheelMaxSpeedReal = 1
    ToolTip, Mouse wheel maximum speed: %MouseWheelMaxSpeedReal% line
else
    ToolTip, Mouse wheel maximum speed: %MouseWheelMaxSpeedReal% lines
SetTimer, RemoveToolTip, 1000
return

ButtonWheelUp:
ButtonWheelDown:

If Button <> 0
{
    If Button <> %A_ThisHotkey%
    {
        MouseWheelCurrentAccelerationSpeed = 0
        MouseWheelCurrentSpeed = %MouseWheelSpeed%
    }
}
StringReplace, Button, A_ThisHotkey, *

ButtonWheelAccelerationStart:
If MouseWheelAccelerationSpeed >= 1
{
    If MouseWheelMaxSpeed > %MouseWheelCurrentSpeed%
    {
        Temp = 0.001
        Temp *= %MouseWheelAccelerationSpeed%
        MouseWheelCurrentAccelerationSpeed += %Temp%
        MouseWheelCurrentSpeed += %MouseWheelCurrentAccelerationSpeed%
    }
}

If Button = NumPadSub
    MouseClick, wheelup,,, %MouseWheelCurrentSpeed%, 0, D
else if Button = NumPadAdd
    MouseClick, wheeldown,,, %MouseWheelCurrentSpeed%, 0, D

SetTimer, ButtonWheelAccelerationEnd, 100
return

ButtonWheelAccelerationEnd:
GetKeyState, kstate, %Button%, P
if kstate = D
    Goto ButtonWheelAccelerationStart

MouseWheelCurrentAccelerationSpeed = 0
MouseWheelCurrentSpeed = %MouseWheelSpeed%
Button = 0
return

RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return


Seek -- by Phi

Navigating the Start Menu can be a hassle, especially if you have installed many programs over time. 'Seek' lets you specify a case-insensitive key word/phrase that it will use to filter only the matching programs and directories from the Start Menu, so that you can easily open your target program from a handful of matched entries. This eliminates the drudgery of searching and traversing the Start Menu.

Download This Script | Other Sample Scripts | Home

;*****************************************************************
;
;  Program : Seek
;  Coder   : Phi
;  Updated : Mon Jan 31 10:08:37 2005
;
;  What do you seek, my friend?
;
;*****************************************************************
;
;  I have a lot of fun coding this, and hope you will
;  enjoy using it too. Feel free to drop me an email with
;  your comments and feedback at: phi1618 (*a.t*) gmail
;  :D0T: com.
;
;  Options:
;    -cache Use the cached directory-listing if available
;           (this is the default mode when no option is specified)
;    -scan  Force a directory scan to retrieve the latest
;           directory listing
;    -scex  Scan & exit (this is useful for scheduling the
;           potentially time-consuming directory-scanning as
;           a background job)
;    -help  Show this help
;
;*****************************************************************
;
; HOW TO 'SEEK':
;
; 1. 'Seek' is an AutoHotkey script. You can either run it
;    as Seek.ahk (original script) or Seek.exe (compiled
;    executable).
;
;    To obtain Seek.exe, you can download Seek.zip (includes
;    both the source code and the compiled binary) from
;    http://home.ripway.com/2004-10/188589/
;    Otherwise, you can compile Seek.ahk on your own by
;    using AutoHotkey's Ahk2Exe.exe compiler, or you can
;    ask me for a copy via email. The filesize is small at
;    about 200 kbytes. I can be reached at: phi1618 (*a.t*)
;    gmail :D0T: com.
;
;    To use Seek.ahk, first, you'll need to install
;    AutoHotkey v1.0.25 or higher on your PC (download from
;    http://www.autohotkey.com). Next, run the command:
;
;    X:\myTools\AutoHotkey\AutoHotkey.exe Y:\myAHK\Seek.ahk
;
;    Remember to replace X:\myTools and Y:\myAHK with
;    the proper directory names on your PC.
;
; 2. You can place the executable Seek.exe anywhere you
;    want. There is no installation required, it doesn't
;    write anything to your registry, and it doesn't
;    access the Internet at all (no phoning home). To
;    uninstall, simply delete Seek.exe.
;
;    The only 2 files 'Seek' creates are placed in your
;    TMP directory:
;
;      a. _Seek.key  (cache file for last query string)
;      b. _Seek.list (cache file for directory listing)
;
;    If you're a purist, you can delete them manually
;    when you decide to remove 'Seek' from your system.
;
; 3. The most convenient way to run 'Seek' is via a
;    shortcut/hotkey. If you are not already using any
;    hotkey management program on your PC, I highly
;    recommend AutoHotkey. If you don't intend to install
;    any hotkey management program at the moment, you can
;    make use of Windows shortcut feature and bind a
;    shortcut key (e.g. ALT-F1) to launch 'Seek'. This is
;    important so that you can run 'Seek' at anytime and
;    anywhere.
;
; 4. When you run 'Seek' for the first time, it'll scan
;    your Start Menu, and save the directory listing into
;    a cache file.
;
;    The following directories are included in the scanning:
;    - %A_StartMenu%
;    - %A_StartMenuCommon%
;
;    By default, subsequent runs will read from the
;    cache file so as to reduce the loading time. For
;    more info on options, run 'Seek.exe -help'. If you
;    think your Start Menu doesn't contain too many
;    programs, you can choose not to use the cache and
;    instruct 'Seek' to always do a directory scan (via
;    option -scan).  That way, you will always get the
;    latest listing.
;
; 5. When you run 'Seek', a window will appear, waiting
;    for you to enter a key word/phrase. After you have
;    entered a query string, a list of matching records
;    will be displayed. Next, you need to highlight an
;    entry and press <Enter> or click on the 'Open'
;    button to run the selected program or open the
;    selected directory.
;
;*****************************************************************
;
; TECHNICAL NOTES:
;
; - 'Seek' requires Chris Mallett's AutoHotkey v1.0.25
;   or higher version (http://www.autohotkey.com).
;   Thanks to Chris for his great work on AutoHotkey. :)
;
; - The following environment variables must be valid:
;   a. TMP
;
;*****************************************************************
;
; KNOWN PROBLEMS:
;
; - Nil
;
;*****************************************************************
;
; IMPLEMENTED SUGGESTIONS:
;
; - Highlight 1st matching record by default so that
;   user can just hit <Enter> to run it.
;   (Suggested by Yih Yeong)
;
; - Enable double-click on the listing of the search
;   results to launch the program.
;   (Suggested by Yih Yeong & Jack)
;
; - Auto real-time incremental search.
;   (Suggested by Rajat)
;
; - Fuzzy search when user enters multiple query strings,
;   separated by space.
;   (Suggested by Rajat)
;
;*****************************************************************
;
; SUGGESTED FEATURES (MAY OR MAY NOT BE IMPLEMENTED):
;
; - Log the launch history. List the most frequently
;   used programs at the top of the search results.
;   (Suggested by Yih Yeong)
;
; - Instead of using list box, can it display a series
;   of application icons so that hovering the cursor
;   over the icon will display a tooltip containing the
;   program information (path, etc).
;   (Suggested by Yih Yeong)
;
; - Instead of matching text in the middle, match only
;   those program/directory names that begin with the
;   query string.
;   (Suggested by Stefan)
;
; - Add favorites management. Launch group of programs
;   in a single run.
;   (Suggested by Atomhrt)
;
; - Integrate Seek into the Windows taskbar/toolbar so that
;   it is always available and there is no need to bind a
;   hotkey to launch Seek.
;   (Suggested by Deniz Akay)
;
; - Search by wildcards/regex.
;   (Suggested by Steve)
;
;*****************************************************************
;
; CHANGE HISTORY:
;
; * v1.1.0
; - Initial release.
;
; * v1.1.1
; - Removed maximise-window option since some programs don't
;   function well with it.
; - Added double-click detection to trigger 'Open' function.
;
; * v2.0.0
; - Integrated the 'Seek' popup window into the output screen
;   so that user can re-enter the query string to search for
;   something else without having to exit and run Seek again.
; - Added 'Scan Start-Menu' button.
; - Added real-time incremental search which will auto
;   filter for matching records while you type away,
;   without waiting for you to press <Enter>.
; - Added internal switch (TrackKeyPhrase) to track search-string.
; - Added internal switch (ToolTipFilename) to show filename
;   using tooltip.
;
; * v2.0.1
; - Added horizontal scrollbar to ListBox so that very
;   long records will not be cut-off in the middle.
;
; * v2.0.2
; - Allowed user to add their own customised list of directories
;   to be included in the scanning. User just needs to create a
;   text file 'Seek.dir' in the same directory as Seek.exe or
;   Seek.ahk, and specify the full path of the directory to be
;   added, one directory per line. Do not enclose the path in
;   quotes or double-quotes.
;
; * v2.0.3
; - Added /on option to DIR-command to sort by name.
; - Fuzzy search when user enters multiple query strings,
;   separated by space, for e.g. "med pla". It's a match
;   when all the strings ("med" & "pla") are found. This
;   will match "Media Player", "Macromedia Flash Player",
;   "Play Medieval King", "medpla", "plamed".
; - Corrected tab-movement sequence by adding all buttons
;   right from the start, but disable them until they can
;   be used.
; - Added status bar to replace tooltip-feedback.
; - Removed obsolete internal switch (ToolTipFilename).
; - Replaced the use of "dir" command with AutoHotkey's
;   own "Loop" command for scanning directory contents.
;   "dir" cannot handle extended character set and thus
;   non-English (e.g German) directory and filename are
;   captured wrongly. (Thanks Wolfgang Bujatti and
;   Sietse Fliege for testing this modification)
; - Added internal switch (ScanMode) to define whether
;   files and/or directories are to be included in scan.
; - Replaced hardcoded directory paths of Start Menu with
;   built-in variables A_StartMenu, A_StartMenuCommon.
;   With this, Seek now works for different locales with
;   different naming convention of the Start Menu.
;   (Thanks Wolfgang Bujatti and Sietse Fliege for help
;   in testing another method before these new variables
;   are available.)
; - Added the pre-selection of the last-run program
;   record so that a quick double-<ENTER> will run it.
;
;*****************************************************************

;**************************
;<--- BEGIN OF PROGRAM --->
;**************************

;==== Your Customisation ===================================

; Specify which program to use when opening a directory.
; If the program cannot be found or is not specified
; (i.e. variable is unassigned or assigned a null value),
; the default Explorer will be used.
dirExplorer = E:\utl\xplorer2_lite\xplorer2.exe

; User's customised list of additional directories to be
; included in the scanning. The full path must not be
; enclosed by quotes or double-quotes. If this file is
; missing, only the default directories will be scanned.
SeekMyDir = %A_ScriptDir%\Seek.dir

; Specify the filename and directory location to save
; the cached directory/program listing. There is no
; need to change this unless you want to.
dirListing = %A_Temp%\_Seek.list

; Specify the filename and directory location to save
; the cached key word/phrase of last search. There is
; no need to change this unless you want to.
keyPhrase = %A_Temp%\_Seek.key

; Track search string (ON/OFF)
; If ON, the last-used query string will be re-used as
; the default query string the next time you run Seek.
; If OFF, the last-used query string will not be tracked
; and there will not be a default query string value the
; next time you run Seek.
TrackKeyPhrase = ON

; Specify what should be included in scan.
; 0: Directories are excluded (only files).
; 1: All files and directories are included.
; 2: Only directories are included (no files).
ScanMode = 1

;...........................................................

; INIT
;#NoTrayIcon
StringCaseSense, Off
version = Seek v2.0.3

; DISPLAY HELP INSTRUCTIONS
If 1 in --help,-help,/h,-h,/?,-?
{
    MsgBox,, %version%, Navigating the Start Menu can be a hassle, especially if you have installed many programs over time. 'Seek' lets you specify a case-insensitive key word/phrase that it will use to filter only the matching programs and directories from the Start Menu, so that you can easily open your target program from a handful of matched entries. This eliminates the drudgery of searching and traversing the Start Menu.`n`nI have a lot of fun coding this, and hope you will enjoy using it too. Feel free to drop me an email with your comments and feedback at: phi1618 (*a.t*) gmail :D0T: com.`n`nOptions:`n  -cache`tUse the cached directory-listing if available (this is the default mode when no option is specified)`n  -scan`tForce a directory scan to retrieve the latest directory listing`n  -scex`tScan & exit (this is useful for scheduling the potentially time-consuming directory-scanning as a background job)`n  -help`tShow this help
    Goto QuitNoSave
}

; CHECK THAT THE MANDATORY ENVIRONMENT VARIABLES EXIST AND ARE VALID
; *TMP*
IfNotExist, %A_Temp% ; PATH DOES NOT EXIST
{
    MsgBox This mandatory environment variable is either not defined or invalid:`n`n    TMP = %A_Temp%`n`nPlease fix it before running Seek.
    Goto QuitNoSave
}

; IF NOT SCAN-AND-EXIT
IfNotEqual 1, -scex
{
    ; RETRIEVE THE LAST USED KEY-PHRASE FROM CACHE FILE
    ; TO BE USED AS THE DEFAULT QUERY STRING
    If TrackKeyPhrase = ON
    {
        FileReadLine, PrevKeyPhrase, %keyPhrase%, 1
        FileReadLine, PrevOpenTarget, %keyPhrase%, 2
    }
    NewKeyPhrase = %PrevKeyPhrase%
    NewOpenTarget = %PrevOpenTarget%

    ; ADD THE TEXT BOX FOR USER TO ENTER THE QUERY STRING
    Gui, 1:Add, Edit, vFilename W600, %NewKeyPhrase%

    ; ADD MY FAV TAGLINE
    Gui, 1:Add, Text, X625 Y10, What do you seek, my friend?

    ; ADD THE STATUS BAR FOR PROVIDING FEEDBACK TO USER
    Gui, 1:Add, Text, vStatusBar X10 Y31 R1 W764

    ; ADD THE SELECTION LISTBOX FOR DISPLAYING SEARCH RESULTS
    Gui, 1:Add, ListBox, vOpenTarget gTargetSelection X10 Y53 R28 W764 HScroll Disabled, %List%

    ; ADD THESE BUTTONS, BUT DISABLE THEM FOR NOW
    Gui, 1:Add, Button, gButtonOPEN vButtonOPEN Default X10 Y446 Disabled, Open
    Gui, 1:Add, Button, gButtonOPENDIR vButtonOPENDIR X59 Y446 Disabled, Open Directory
    Gui, 1:Add, Button, gButtonSCANSTARTMENU vButtonSCANSTARTMENU X340 Y446 Disabled, Scan Start-Menu

    ; ADD THE EXIT BUTTON
    Gui, 1:Add, Button, gButtonEXIT X743 Y446, Exit

    ; POP-UP THE QUERY WINDOW
    Gui, 1:Show, Center, %version%
}

; ENABLE RE-SCANNING OF LATEST DIRECTORY LISTING
If 1 in -scan,-scex
    rescan = Y
; CHECK WHETHER THE DIRECTORY LISTING CACHE FILE ALREADY EXISTS. IF NOT, DO A RE-SCAN.
Else IfNotExist, %dirListing%
    rescan = Y

If rescan = Y ; DO A RE-SCAN
{
    ; SHOW STATUS UNLESS USER SPECIFIES SCAN-AND-EXIT OPTION
    IfNotEqual 1, -scex
        GuiControl,, StatusBar, Scanning directory listing...

    ; SCAN START-MENU AND STORE DIRECTORY/PROGRAM LISTINGS IN CACHE FILE
    Gosub ScanStartMenu

    ; QUIT IF USER SPECIFIES SCAN-AND-EXIT OPTION
    IfEqual 1, -scex, Goto, QuitNoSave
}

GuiControl,, StatusBar, Retrieving last query result...

; RETRIEVE THE MATCHING LIST FOR THE LAST USED KEY-PHRASE
Gosub SilentFindMatches

; REMOVE THE STATUS TEXT
GuiControl,, StatusBar,

; DIRECTORY LISTING IS NOW LOADED. ENABLE THE OTHER BUTTONS.
; THESE BUTTONS ARE DISABLED EARLIER BECAUSE THEY SHOULD NOT
; BE FUNCTIONAL UNTIL THIS PART OF THE SCRIPT.
GuiControl, 1:Enable, ButtonOPEN
GuiControl, 1:Enable, ButtonOPENDIR
GuiControl, 1:Enable, ButtonSCANSTARTMENU

; TURN ON INCREMENTAL SEARCH
SetTimer, tIncrementalSearch, 500

; REFRESH THE GUI
Gosub EnterQuery

Return

;***********************************************************
;                                                          *
;                 END OF MAIN PROGRAM                      *
;                                                          *
;***********************************************************

;=== BEGIN ButtonSCANSTARTMENU EVENT =======================

ButtonSCANSTARTMENU:

Gui, 1:Submit, NoHide
GuiControl,, StatusBar, Scanning directory listing...

; DISABLE LISTBOX WHILE SCANNING IS IN PROGRESS
GuiControl, 1:Disable, OpenTarget
GuiControl, 1:Disable, ButtonEXIT
GuiControl, 1:Disable, ButtonOPEN
GuiControl, 1:Disable, ButtonOPENDIR
GuiControl, 1:Disable, ButtonSCANSTARTMENU

; DO THE SCANNING
Gosub ScanStartMenu

; INFORM USER THAT SCANNING HAS COMPLETED
If Filename =
{
    ; IF QUERY STRING IS EMPTY...
    GuiControl, 1:Enable, ButtonEXIT
    GuiControl, 1:Enable, ButtonOPEN
    GuiControl, 1:Enable, ButtonSCANSTARTMENU
    GuiControl,, StatusBar, Scan completed.
    Gosub EnterQuery
}
Else
{
    ; IF QUERY STRING EXISTS...
    ; FILTER FOR SEARCH STRING WITH THE NEW LISTING
    NewKeyPhrase =
    Gosub FindMatches
}
Return

;... END ButtonSCANSTARTMENU EVENT .........................

;=== BEGIN ScanStartMenu SUBROUTINE ========================
; SCAN THE START-MENU AND STORE THE DIRECTORY/PROGRAM
; LISTINGS IN A CACHE FILE
ScanStartMenu:

; DEFINE THE DIRECTORY PATHS TO RETRIEVE.
; THE PATH MUST NOT BE ENCLOSED BY QUOTES OR DOUBLE-QUOTES.
;
; FOR ENGLISH VERSION OF WINDOWS
scanPath = %A_StartMenu%|%A_StartMenuCommon%

; INCLUDE ADDITIONAL USER-DEFINED PATHS FOR SCANNING
IfExist, %SeekMyDir%
{
    Loop, read, %SeekMyDir%
    {
        IfNotExist, %A_LoopReadLine%
            MsgBox, 8192, %version%, Processing your customised directory list...`n`n"%A_LoopReadLine%" does not exist and will be excluded from the scanning.`nPlease update [ %SeekMyDir% ].
        Else
            scanPath = %scanPath%|%A_LoopReadLine%
    }
}

; DELETE EXISTING FILE BEFORE CREATING A NEW VERSION
FileDelete, %dirListing%

; SCAN DIRECTORY LISTING (DELIMITER = |) BY RECURSING
; EACH DIRECTORY TO RETRIEVE THE CONTENTS. HIDDEN FILES
; ARE EXCLUDED.
Loop, parse, scanPath, |
{
    Loop, %A_LoopField%\*, %ScanMode%, 1
    {
        FileGetAttrib, fileAttrib, %A_LoopFileFullPath%
        IfNotInString, fileAttrib, H ; EXCLUDE HIDDEN FILE
            FileAppend, %A_LoopFileFullPath%`n, %dirListing%
    }
}

Return

;... END ScanStartMenu SUBROUTINE ..........................

;=== BEGIN FindMatches SUBROUTINE ==========================
; SEARCH AND DISPLAY ALL MATCHING RECORDS IN THE LISTBOX
FindMatches:

Gui, 1:Submit, NoHide
CurFilename = %Filename%
GuiControl,, StatusBar,

; CHECK FOR EMPTY QUERY STRING
If CurFilename =
{
    MsgBox, 8192, %version%, Please enter the key word/phrase to search for.
    Goto EnterQuery
}

; tIncrementalSearch IS BEING INTERRUPTED. LET IT FINISHES.
If NewKeyPhrase <> %CurFilename%
{
    ; INFORM USER THAT PATIENCE IS A VIRTUE
    GuiControl,, StatusBar, Seeking...
    ResumeFindMatches = TRUE
    Return
}

If List = |
{
    ; NOT EVEN A SINGLE MATCHING RECORD IS FOUND.
    ; LET USER MODIFY THE QUERY STRING AND TRY AGAIN.
    MsgBox, 8192, %version%, The query string "%CurFilename%" does not match any record. Try again.
    GuiControl, 1:Disable, ButtonOPENDIR
    GuiControl, 1:Enable, ButtonSCANSTARTMENU
    Goto EnterQuery
}
Else
{
    ; SELECT THE FIRST RECORD IF NO OTHER RECORD HAS BEEN SELECTED
    Gui, 1:Submit, NoHide
    GuiControl, 1:Enable, OpenTarget
    GuiControl, 1:Enable, ButtonOPEN
    GuiControl, 1:Enable, ButtonOPENDIR
    GuiControl, 1:Enable, ButtonSCANSTARTMENU
    GuiControl, Focus, OpenTarget
    If OpenTarget =
        GuiControl, 1:Choose, OpenTarget, |1
}

; REFRESH GUI
Gui, 1:Show, Center, %version%

Return

;... END FindMatches SUBROUTINE ............................

;=== BEGIN SilentFindMatches SUBROUTINE ====================

SilentFindMatches:

Gui, 1:Submit, NoHide
sfmFilename = %Filename%

; FILTER MATCHING RECORDS BASED ON USER QUERY STRING
List = |
If sfmFilename <>
{
    Loop, read, %dirListing%
    {
        Gui, 1:Submit, NoHide
        tFilename = %Filename%
        If sfmFilename <> %tFilename%
        {
            ; USER HAS CHANGED THE SEARCH STRING. THERE IS NO POINT
            ; TO CONTINUE SEARCHING USING THE OLD STRING, SO ABORT.
            Return
        }
        Else
        {
            ; APPEND MATCHING RECORDS INTO THE LIST
            SplitPath, A_LoopReadLine, name, dir, ext, name_no_ext, drive
            MatchFound = Y
            Loop, parse, sfmFilename, %A_Space%
            {
                IfNotInString, name, %A_LoopField%
                {
                    MatchFound = N
                    Break
                }
            }
            IfEqual, MatchFound, Y
            {
                ; ADD RECORD TO LIST
                List = %List%%A_LoopReadLine%|

                ; PRE-SELECT IF THIS MATCHES THE LAST-RUN PROGRAM
                If (A_LoopReadLine = PrevOpenTarget && sfmFilename = PrevKeyPhrase)
                    List = %List%|
            }
        }
    }
}

; REFRESH LIST WITH SEARCH RESULTS
GuiControl, 1:, OpenTarget, %List%

If List = |
{
    ; NO MATCHING RECORD IS FOUND
    ; DISABLE LISTBOX
    GuiControl, 1:Disable, OpenTarget
    GuiControl, 1:Disable, ButtonOPENDIR
}
Else
{
    ; MATCHING RECORDS ARE FOUND
    ; ENABLE LISTBOX
    GuiControl, 1:Enable, OpenTarget
    GuiControl, 1:Enable, ButtonOPENDIR
}

; REFRESH GUI
Gui, 1:Show, Center, %version%

Return

;... END SilentFindMatches SUBROUTINE ......................

;=== BEGIN EnterQuery SUBROUTINE ===========================
; REFRESH GUI AND LET USER ENTERS SEARCH STRING
EnterQuery:
GuiControl, Focus, Filename
GuiControl, 1:Enable, ButtonOPEN
Gui, 1:Show, Center, %version%
Return
;... END EnterQuery SUBROUTINE .............................

;=== BEGIN TargetSelection EVENT ===========================

TargetSelection:
Gui, 1:Submit, NoHide

; DOUBLE-CLICK DETECTION TO LAUNCH PROGRAM
If A_GuiControlEvent = DoubleClick
{
    Gosub ButtonOPEN
}
Else
{
    ; STUB - FOR FUTURE USE
    If A_GuiControlEvent = Normal
    {
        ; DO NOTHING FOR NOW
    }
}

Return

;... END TargetSelection EVENT .............................

;=== BEGIN ButtonOPEN EVENT ================================

; USER CLICKED ON 'OPEN' BUTTON OR PRESSED <ENTER>
ButtonOPEN:
Gui, 1:Submit, NoHide

; FIND OUT WHERE THE KEYBOARD FOCUS WAS. IF IT'S THE
; TEXT FIELD, RUN THE QUERY TO FIND MATCHES. ELSE, IT
; MUST BE FROM THE LISTBOX.
GuiControlGet, focusControl, 1:Focus
If focusControl = Edit1
{
    GuiControl, Focus, OpenTarget
    GuiControl, 1:Disable, OpenTarget
    GuiControl, 1:Disable, ButtonOPENDIR
    GuiControl, 1:Disable, ButtonSCANSTARTMENU
    Goto FindMatches
}

; NO RECORD FROM THE LISTBOX IS SELECTED
If OpenTarget =
{
    MsgBox, 8192, %version%, Please make a selection before hitting <Enter>.`nPress <Esc> to exit.
    Goto EnterQuery
}

; SELECTED RECORD DOES NOT EXIST (FILE OR DIRECTORY NOT FOUND)
IfNotExist, %OpenTarget%
{
    MsgBox, 8192, %version%, %OpenTarget% does not exist. This means that the directory cache is outdated. You may click on the 'Scan Start-Menu' button below to update the directory cache with your latest directory listing now.
    Goto EnterQuery
}

; CHECK WHETHER THE SELECTED RECORD IS A FILE OR DIRECTORY
FileGetAttrib, fileAttrib, %OpenTarget%
IfInString, fileAttrib, D ; IS DIRECTORY
{
    Gosub sOpenDir
}
Else If fileAttrib <> ; IS FILE
{
    Run, %OpenTarget%
}
Else
{
    MsgBox %OpenTarget% is neither a DIRECTORY or a FILE. This shouldn't happen. Seek cannot proceed. Quitting...
}

Goto Quit

;... END ButtonOPEN EVENT ..................................

;=== BEGIN ButtonOPENDIR EVENT =============================

; USER CLICKED ON 'OPEN DIRECTORY' BUTTON
ButtonOPENDIR:
Gui, 1:Submit, NoHide

; CHECK THAT USER HAS SELECTED A RECORD ALREADY
If OpenTarget =
{
    MsgBox, 8192, %version%, Please make a selection first.
    Goto EnterQuery
}

; RUN SUBROUTINE TO OPEN A DIRECTORY
Gosub sOpenDir

Goto Quit

;... END ButtonOPENDIR EVENT ...............................

;=== BEGIN sOpenDir SUBROUTINE =============================

sOpenDir:

; IF USER SELECTED A FILE-RECORD INSTEAD OF A DIRECTORY-RECORD,
; EXTRACT THE DIRECTORY PATH. (I'M USING DriveGet INSTEAD OF
; FileGetAttrib TO ALLOW THE SCENARIO WHEREBY OpenTarget IS
; INVALID BUT THE DIRECTORY PATH OF OpenTarget IS VALID.
DriveGet, status, status, %OpenTarget%
If status <> Ready ; NOT A DIRECTORY
{
    SplitPath, OpenTarget, name, dir, ext, name_no_ext, drive
    OpenTarget = %dir%
}

; CHECK WHETHER DIRECTORY EXISTS
IfNotExist, %OpenTarget%
{
    MsgBox, 8192, %version%, %OpenTarget% does not exist. This means that the directory cache is outdated. You may click on the 'Scan Start-Menu' button below to update the directory cache with your latest directory listing now.
    Goto EnterQuery
}

; OPEN THE DIRECTORY
IfExist, %dirExplorer%
{
    Run, "%dirExplorer%" "%OpenTarget%", , Max ; OPEN WITH CUSTOMISED FILE EXPLORER
}
Else
{
    Run, %OpenTarget%, , Max ; OPEN WITH DEFAULT WINDOWS FILE EXPLORER
}
Return

;... END sOpenDir SUBROUTINE ...............................

;=== BEGIN tIncrementalSearch EVENT ========================
; AUTOMATICALLY CONDUCT REAL-TIME INCREMENTAL SEARCH
; TO FIND MATCHING RECORDS WITHOUT WAITING FOR USER
; TO PRESS <ENTER>
tIncrementalSearch:

Loop
; REPEAT SEARCHING UNTIL USER HAS STOPPED CHANGING THE QUERY STRING
{
    Gui, 1:Submit, NoHide
    CurFilename = %Filename%
    If NewKeyPhrase <> %CurFilename%
    {
        OpenTarget =
        Gosub SilentFindMatches
        NewKeyPhrase = %CurFilename%
        Sleep, 100 ; DON'T HOG THE CPU!
    }
    Else
    {
        ; QUERY STRING HAS STOPPED CHANGING
        Break
    }
}

; USER HAS HIT <ENTER> TO LOOK FOR MATCHING RECORDS.
; RUN FindMatches NOW.
If ResumeFindMatches = TRUE
{
    ResumeFindMatches = FALSE
    Gosub FindMatches
}

; CONTINUE MONITORING FOR CHANGES
SetTimer, tIncrementalSearch, 500

Return

;... END tIncrementalSearch EVENT ..........................

;=== BEGIN Quit SUBROUTINE =================================

Quit:
ButtonEXIT:
GuiClose:
GuiEscape:

Gui, 1:Submit, NoHide

; SAVE THE KEY WORD/PHRASE FOR NEXT RUN IF IT HAS CHANGED
If TrackKeyPhrase = ON
{
    If (PrevKeyPhrase <> Filename || PrevOpenTarget <> OpenTarget)
    {
        FileDelete, %keyPhrase%
        FileAppend, %Filename%`n, %keyPhrase%
        FileAppend, %OpenTarget%`n, %keyPhrase%
    }
}

QuitNoSave:
ExitApp ; JOB DONE. G'DAY!

;... END Quit SUBROUTINE ...................................

;************************
;<--- END OF PROGRAM --->
;************************

; /* vim: set noexpandtab shiftwidth=4: */


ToolTip Mouse Menu (requires XP/2k/NT) -- by Rajat

This script displays a popup menu in response to briefly holding down the middle mouse button. Select a menu item by left-clicking it. Cancel the menu by left-clicking outside of it. A recent improvement is that the contents of the menu can change depending on which type of window is active (Notepad and Word are used as examples here).

Download This Script | Other Sample Scripts | Home

; You can set any title here for the menu:
MenuTitle = -=-=-=-=-=-=-=-

; This is how long the mouse button must be held to cause the menu to appear:
UMDelay = 20

SetFormat, float, 0.0
SetBatchLines, 10ms
SetTitleMatchMode, 2
#SingleInstance

;___________________________________________
;_____Menu Definitions______________________

; Create / Edit Menu Items here.
; You can't use spaces in keys/values/section names.

; Don't worry about the order, the menu will be sorted.

MenuItems = Notepad/Calculator/Section 3/Section 4/Section 5

;___________________________________________
;______Dynamic menuitems here_______________

; Syntax:
;     Dyn# = MenuItem|Window title

Dyn1 = MS Word|- Microsoft Word
Dyn2 = Notepad II|- Notepad

;___________________________________________

Exit

;___________________________________________
;_____Menu Sections_________________________

; Create / Edit Menu Sections here.

Notepad:
Run, Notepad.exe
Return

Calculator:
Run, Calc
Return

Section3:
MsgBox, You selected 3
Return

Section4:
MsgBox, You selected 4
Return

Section5:
MsgBox, You selected 5
Return

MSWord:
msgbox, this is a dynamic entry (word)
Return

NotepadII:
msgbox, this is a dynamic entry (notepad)
Return

;___________________________________________
;_____Hotkey Section________________________

~MButton::
HowLong = 0
Loop
{
    HowLong ++
    Sleep, 10
    GetKeyState, MButton, MButton, P
    IfEqual, MButton, U, Break
}
IfLess, HowLong, %UMDelay%, Return

;prepares dynamic menu
DynMenu =
Loop
{
    IfEqual, Dyn%a_index%,, Break

    StringGetPos, ppos, dyn%a_index%, |
    StringLeft, item, dyn%a_index%, %ppos%
    ppos += 2
    StringMid, win, dyn%a_index%, %ppos%, 1000

    IfWinActive, %win%,
        DynMenu = %DynMenu%/%item%
}

;Joins sorted main menu and dynamic menu
Sort, MenuItems, D/
TempMenu = %MenuItems%%DynMenu%

;clears earlier entries
Loop
{
    IfEqual, MenuItem%a_index%,, Break
    MenuItem%a_index% =
}

;creates new entries
Loop, Parse, TempMenu, /
{
    MenuItem%a_index% = %a_loopfield%
}

;creates the menu
Menu = %MenuTitle%
Loop
{
    IfEqual, MenuItem%a_index%,, Break
    numItems ++
    StringTrimLeft, MenuText, MenuItem%a_index%, 0
    Menu = %Menu%`n%MenuText%
}

MouseGetPos, mX, mY
HotKey, ~LButton, MenuClick
HotKey, ~LButton, On
ToolTip, %Menu%, %mX%, %mY%
WinActivate, %MenuTitle%
Return

MenuClick:
HotKey, ~LButton, Off
IfWinNotActive, %MenuTitle%
{
    ToolTip
    Return
}

MouseGetPos, mX, mY
ToolTip
mY -= 3        ;space after which first line starts
mY /= 13    ;space taken by each line
IfLess, mY, 1, Return
IfGreater, mY, %numItems%, Return
StringTrimLeft, TargetSection, MenuItem%mY%, 0
StringReplace, TargetSection, TargetSection, %a_space%,, A
Gosub, %TargetSection%
Return


Volume On-Screen-Display (OSD) -- by Rajat

This script assigns hotkeys of your choice to raise and lower the master and/or wave volume. Both volumes are displayed as different color bar graphs.

Download This Script | Other Sample Scripts | Home

;_________________________________________________
;_______User Settings_____________________________

; Make customisation only in this area or hotkey area only!!

; The percentage by which to raise or lower the volume each time:
vol_Step = 4

; How long to display the volume level bar graphs:
vol_DisplayTime = 2000

; Master Volume Bar color (see the help file to use more
; precise shades):
vol_CBM = Red

; Wave Volume Bar color
vol_CBW = Blue

; Background color
vol_CW = Silver

; Bar's screen position.  Use -1 to center the bar in that dimension:
vol_PosX = -1
vol_PosY = -1
vol_Width = 150  ; width of bar
vol_Thick = 12   ; thickness of bar

; If your keyboard has multimedia buttons for Volume, you can
; try changing the below hotkeys to use them by specifying
; Volume_Up, ^Volume_Up, Volume_Down, and ^Volume_Down:
HotKey, #Up, vol_MasterUp      ; Win+UpArrow
HotKey, #Down, vol_MasterDown
HotKey, +#Up, vol_WaveUp       ; Shift+Win+UpArrow
HotKey, +#Down, vol_WaveDown

;___________________________________________
;_____Auto Execute Section__________________

; DON'T CHANGE ANYTHING HERE (unless you know what you're doing).

vol_BarOptionsMaster = 1:B ZH%vol_Thick% ZX0 ZY0 W%vol_Width% CB%vol_CBM% CW%vol_CW%
vol_BarOptionsWave   = 2:B ZH%vol_Thick% ZX0 ZY0 W%vol_Width% CB%vol_CBW% CW%vol_CW%

; If the X position has been specified, add it to the options.
; Otherwise, omit it to center the bar horizontally:
if vol_PosX >= 0
{
    vol_BarOptionsMaster = %vol_BarOptionsMaster% X%vol_PosX%
    vol_BarOptionsWave   = %vol_BarOptionsWave% X%vol_PosX%
}

; If the Y position has been specified, add it to the options.
; Otherwise, omit it to have it calculated later:
if vol_PosY >= 0
{
    vol_BarOptionsMaster = %vol_BarOptionsMaster% Y%vol_PosY%
    vol_PosY_wave = %vol_PosY%
    vol_PosY_wave += %vol_Thick%
    vol_BarOptionsWave = %vol_BarOptionsWave% Y%vol_PosY_wave%
}

#SingleInstance
SetBatchLines, 10ms
Return

;___________________________________________

vol_WaveUp:
SoundSet, +%vol_Step%, Wave
Gosub, vol_ShowBars
return

vol_WaveDown:
SoundSet, -%vol_Step%, Wave
Gosub, vol_ShowBars
return

vol_MasterUp:
SoundSet, +%vol_Step%
Gosub, vol_ShowBars
return

vol_MasterDown:
SoundSet, -%vol_Step%
Gosub, vol_ShowBars
return

vol_ShowBars:
; To prevent the "flashing" effect, only create the bar window if it
; doesn't already exist:
IfWinNotExist, vol_Wave
    Progress, %vol_BarOptionsWave%, , , vol_Wave
IfWinNotExist, vol_Master
{
    ; Calculate position here in case screen resolution changes while
    ; the script is running:
    if vol_PosY < 0
    {
        ; Create the Wave bar just above the Master bar:
        WinGetPos, , vol_Wave_Posy, , , vol_Wave
        vol_Wave_Posy -= %vol_Thick%
        Progress, %vol_BarOptionsMaster% Y%vol_Wave_Posy%, , , vol_Master
    }
    else
        Progress, %vol_BarOptionsMaster%, , , vol_Master
}
; Get both volumes in case the user or an external program changed them:
SoundGet, vol_Master, Master
SoundGet, vol_Wave, Wave
Progress, 1:%vol_Master%
Progress, 2:%vol_Wave%
SetTimer, vol_BarOff, %vol_DisplayTime%
return

vol_BarOff:
SetTimer, vol_BarOff, off
Progress, 1:Off
Progress, 2:Off
return


Window Shading (roll up a window to its title bar) -- by Rajat

This script reduces a window to its title bar and then back to its original size by pressing a single hotkey. Any number of windows can be reduced in this fashion (the script remembers each). If the script exits for any reason, all "rolled up" windows will be automatically restored to their original heights.

Download This Script | Other Sample Scripts | Home

; Set the height of a rolled up window here.  The operating system
; probably won't allow the title bar to be hidden regardless of
; how low this number is:
ws_MinHeight = 25

; This line will unroll any rolled up windows if the script exits
; for any reason:
OnExit, ExitSub
return  ; End of auto-execute section

#z::  ; Change this line to pick a different hotkey.
; Below this point, no changes should be made unless you want to
; alter the script's basic functionality.
; Uncomment this next line if this subroutine is to be converted
; into a custom menu item rather than a hotkey.  The delay allows
; the active window that was deactivated by the displayed menu to
; become active again:
;Sleep, 200
WinGet, ws_ID, ID, A
Loop, Parse, ws_IDList, |
{
    IfEqual, A_LoopField, %ws_ID%
    {
        ; Match found, so this window should be restored (unrolled):
        StringTrimRight, ws_Height, ws_Window%ws_ID%, 0
        WinMove, ahk_id %ws_ID%,,,,, %ws_Height%
        StringReplace, ws_IDList, ws_IDList, |%ws_ID%
        return
    }
}
WinGetPos,,,, ws_Height, A
ws_Window%ws_ID% = %ws_Height%
WinMove, ahk_id %ws_ID%,,,,, %ws_MinHeight%
ws_IDList = %ws_IDList%|%ws_ID%
return

ExitSub:
Loop, Parse, ws_IDList, |
{
    if A_LoopField =  ; First field in list is normally blank.
        continue      ; So skip it.
    StringTrimRight, ws_Height, ws_Window%A_LoopField%, 0
    WinMove, ahk_id %A_LoopField%,,,,, %ws_Height%
}
ExitApp  ; Must do this for the OnExit subroutine to actually Exit the script.


WinLIRC Client

This script receives notifications from WinLIRC whenever you press a button on your remote control. It can be used to automate Winamp, Windows Media Player, etc. It's easy to configure. For example, if WinLIRC recognizes a button named "VolUp" on your remote control, create a label named VolUp and beneath it use the command "SoundSet +5" to increase the soundcard's volume by 5%.

Download This Script | Other Sample Scripts | Home

; Here are the steps to use this script:
; 1) Configure WinLIRC to recognize your remote control and its buttons.
;    WinLIRC is at http://winlirc.sourceforge.net
; 2) Edit the WinLIRC path, address, and port in the CONFIG section below.
; 3) Launch this script. It will start the WinLIRC server if needed.
; 4) Press some buttons on your remote control. A small window will
;    appear showing the name of each button as you press it.
; 5) Configure your buttons to send keystrokes and mouse clicks to
;    windows such as Winamp, Media Player, etc. See the examples below.

; This script requires AutoHotkey 1.0.38.04 or later.
; HISTORY OF CHANGES
; March 2, 2007:
; - Improved reliability via "Critical" in ReceiveData().
; October 5, 2005:
; - Eliminated Winsock warning dialog "10054" upon system shutdown/logoff.
; - Added option "DelayBetweenButtonRepeats" to throttle the repeat speed.

; -------------------------------------------------
; CONFIGURATION SECTION: Set your preferences here.
; -------------------------------------------------
; Some remote controls repeat the signal rapidly while you're holding down
; a button. This makes it difficult to get the remote to send only a single
; signal. The following setting solves this by ignoring repeated signals
; until the specified time has passed. 200 is often a good setting.  Set it
; to 0 to disable this feature.
DelayBetweenButtonRepeats = 200

; Specify the path to WinLIRC, such as C:\WinLIRC\winlirc.exe
WinLIRC_Path = %A_ProgramFiles%\WinLIRC\winlirc.exe

; Specify WinLIRC's address and port. The most common are 127.0.0.1 (localhost) and 8765.
WinLIRC_Address = 127.0.0.1
WinLIRC_Port = 8765

; Do not change the following two lines. Skip them and continue below.
Gosub WinLIRC_Init
return

; --------------------------------------------
; ASSIGN ACTIONS TO THE BUTTONS ON YOUR REMOTE
; --------------------------------------------
; Configure your remote control's buttons below. Use WinLIRC's names
; for the buttons, which can be seen in your WinLIRC config file
; (.cf file) -- or you can press any button on your remote and the
; script will briefly display the button's name in a small window.
;
; Below are some examples. Feel free to revise or delete them to suit
; your preferences.

VolUp:
SoundSet +5  ; Increase master volume by 5%. On Vista, replace this line with: Send {Volume_Up}
return

VolDown:
SoundSet -5  ; Reduce master volume by 5%. On Vista, replace this line with: Send {Volume_Down}
return

ChUp:
WinGetClass, ActiveClass, A
if ActiveClass in Winamp v1.x,Winamp PE  ; Winamp is active.
    Send {right}  ; Send a right-arrow keystroke.
else  ; Some other type of window is active.
    Send {WheelUp}  ; Rotate the mouse wheel up by one notch.
return

ChDown:
WinGetClass, ActiveClass, A
if ActiveClass in Winamp v1.x,Winamp PE  ; Winamp is active.
    Send {left}  ; Send a left-arrow keystroke.
else  ; Some other type of window is active.
    Send {WheelDown}  ; Rotate the mouse wheel down by one notch.
return

Menu:
IfWinExist, Untitled - Notepad
{
    WinActivate
}
else
{
    Run, Notepad
    WinWait, Untitled - Notepad
    WinActivate
}
Send Here are some keystrokes sent to Notepad.{Enter}
return

; The examples above give a feel for how to accomplish common tasks.
; To learn the basics of AutoHotkey, check out the Quick-start Tutorial
; at http://www.autohotkey.com/docs/Tutorial.htm

; ----------------------------
; END OF CONFIGURATION SECTION
; ----------------------------
; Do not make changes below this point unless you want to change the core
; functionality of the script.

WinLIRC_Init:
OnExit, ExitSub  ; For connection cleanup purposes.

; Launch WinLIRC if it isn't already running:
Process, Exist, winlirc.exe
if not ErrorLevel  ; No PID for WinLIRC was found.
{
    IfNotExist, %WinLIRC_Path%
    {
        MsgBox The file "%WinLIRC_Path%" does not exist. Please edit this script to specify its location.
        ExitApp
    }
    Run %WinLIRC_Path%
    Sleep 200  ; Give WinLIRC a little time to initialize (probably never needed, just for peace of mind).
}

; Connect to WinLIRC (or any type of server for that matter):
socket := ConnectToAddress(WinLIRC_Address, WinLIRC_Port)
if socket = -1  ; Connection failed (it already displayed the reason).
    ExitApp

; Find this script's main window:
Process, Exist  ; This sets ErrorLevel to this script's PID (it's done this way to support compiled scripts).
DetectHiddenWindows On
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
DetectHiddenWindows Off

; When the OS notifies the script that there is incoming data waiting to be received,
; the following causes a function to be launched to read the data:
NotificationMsg = 0x5555  ; An arbitrary message number, but should be greater than 0x1000.
OnMessage(NotificationMsg, "ReceiveData")

; Set up the connection to notify this script via message whenever new data has arrived.
; This avoids the need to poll the connection and thus cuts down on resource usage.
FD_READ = 1     ; Received when data is available to be read.
FD_CLOSE = 32   ; Received when connection has been closed.
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}
return

ConnectToAddress(IPAddress, Port)
; This can connect to most types of TCP servers, not just WinLIRC.
; Returns -1 (INVALID_SOCKET) upon failure or the socket ID upon success.
{
    VarSetCapacity(wsaData, 32)  ; The struct is only about 14 in size, so 32 is conservative.
    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002)
    ; Since WSAStartup() will likely be the first Winsock function called by this script,
    ; check ErrorLevel to see if the OS has Winsock 2.0 available:
    if ErrorLevel
    {
        MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
        return -1
    }
    if result  ; Non-zero, which means it failed (most Winsock functions return 0 upon success).
    {
        MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }

    AF_INET = 2
    SOCK_STREAM = 1
    IPPROTO_TCP = 6
    socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
    if socket = -1
    {
        MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }

    ; Prepare for connection:
    SizeOfSocketAddress = 16
    VarSetCapacity(SocketAddress, SizeOfSocketAddress)
    InsertInteger(2, SocketAddress, 0, AF_INET)   ; sin_family
    InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)   ; sin_port
    InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)   ; sin_addr.s_addr

    ; Attempt connection:
    if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
    {
        MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . ". Is WinLIRC running?"
        return -1
    }
    return socket  ; Indicate success by returning a valid socket ID rather than -1.
}

ReceiveData(wParam, lParam)
; By means of OnMessage(), this function has been set up to be called automatically whenever new data
; arrives on the connection.  It reads the data from WinLIRC and takes appropriate action depending
; on the contents.
{
    Critical  ; Prevents another of the same message from being discarded due to thread-already-running.
    socket := wParam
    ReceivedDataSize = 4096  ; Large in case a lot of data gets buffered due to delay in processing previous data.

    VarSetCapacity(ReceivedData, ReceivedDataSize, 0)  ; 0 for last param terminates string for use with recv().
    ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
    if ReceivedDataLength = 0  ; The connection was gracefully closed, probably due to exiting WinLIRC.
        ExitApp  ; The OnExit routine will call WSACleanup() for us.
    if ReceivedDataLength = -1
    {
        WinsockError := DllCall("Ws2_32\WSAGetLastError")
        if WinsockError = 10035  ; WSAEWOULDBLOCK, which means "no more data to be read".
            return 1
        if WinsockError <> 10054 ; WSAECONNRESET, which happens when WinLIRC closes via system shutdown/logoff.
            ; Since it's an unexpected error, report it.  Also exit to avoid infinite loop.
            MsgBox % "recv() indicated Winsock error " . WinsockError
        ExitApp  ; The OnExit routine will call WSACleanup() for us.
    }
    ; Otherwise, process the data received. Testing shows that it's possible to get more than one line
    ; at a time (even for explicitly-sent IR signals), which the following method handles properly.
    ; Data received from WinLIRC looks like the following example (see the WinLIRC docs for details):
    ; 0000000000eab154 00 NameOfButton NameOfRemote
    Loop, parse, ReceivedData, `n, `r
    {
        if A_LoopField in ,BEGIN,SIGHUP,END  ; Ignore blank lines and WinLIRC's start-up messages.
            continue
        ButtonName =  ; Init to blank in case there are less than 3 fields found below.
        Loop, parse, A_LoopField, %A_Space%  ; Extract the button name, which is the third field.
            if A_Index = 3
                ButtonName := A_LoopField
        global DelayBetweenButtonRepeats  ; Declare globals to make them available to this function.
        static PrevButtonName, PrevButtonTime, RepeatCount  ; These variables remember their values between calls.
        if (ButtonName != PrevButtonName || A_TickCount - PrevButtonTime > DelayBetweenButtonRepeats)
        {
            if IsLabel(ButtonName)  ; There is a subroutine associated with this button.
                Gosub %ButtonName%  ; Launch the subroutine.
            else ; Since there is no associated subroutine, briefly display which button was pressed.
            {
                if (ButtonName == PrevButtonName)
                    RepeatCount += 1
                else
                    RepeatCount = 1
                SplashTextOn, 150, 20, Button from WinLIRC, %ButtonName% (%RepeatCount%)
                SetTimer, SplashOff, 3000  ; This allows more signals to be processed while displaying the window.
            }
            PrevButtonName := ButtonName
            PrevButtonTime := A_TickCount
        }
    }
    return 1  ; Tell the program that no further processing of this message is needed.
}

SplashOff:
SplashTextOff
SetTimer, SplashOff, Off
return

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
    Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

ExitSub:  ; This subroutine is called automatically when the script exits for any reason.
; MSDN: "Any sockets open when WSACleanup is called are reset and automatically
; deallocated as if closesocket was called."
DllCall("Ws2_32\WSACleanup")
ExitApp