修改的命令, 函数 & 指令
关于这一节的标题: v2 中没有命令, 只有函数. 标题涉及两个版本.
当使用 SendEvent 方法发送 Alt 事件时, BlockInput 不再临时禁用. 这最初是为了解决 Windows XP 某些版本中的一个 bug, 其中 BlockInput 阻止了人工 Alt 事件.
Chr(0)
返回一个长度为 1 的字符串, 包含一个二进制零. 这是改进了对字符串中二进制零的支持的结果.
如果等待期过了, ClipWait 现在返回 0(false), 否则返回 1(true). ErrorLevel 被删除. 指定 0 不再等同于指定 0.5; 相反, 它产生尽可能短的等待.
ComObj()
: 这个函数有一种通配符的名字, 允许许多不同的后缀. 有些名字通常用于特定类型的参数, 如 ComObjActive(CLSID)
, ComObjParameter(vt, value)
, ComObjEnwrap(dsp)
. 取而代之的是单独的函数/类, 不再有通配符名称. 有关详情, 请参阅 COM 对象(ComObject).
Control: 对 Control 函数, SendMessage 和 PostMessage 使用的 Control 参数做了一些修改:
它现在可以接受 HWND(必须是一个纯整数) 或具有 Hwnd 属性的对象, 如 GuiControl 对象. HWND 可以识别一个控件或一个顶级窗口, 尽管后者通常只对少数几个函数才有意义(见下文).
它不再是可选的, 除了可以操作顶级窗口的函数(ControlSend[Text], ControlClick, SendMessage, PostMessage) 或前面有其他可选的参数时(ListViewGetContent, ControlGetPos, ControlMove).
如果省略, 就会使用目标窗口来代替. 这与之前 SendMessage/PostMessage 的行为相匹配, 并取代了 ControlSend 之前使用的 ahk_parent
特殊值.
空白的值是无效的. 函数从不默认目标窗口的最顶层的控件.
ControlGetFocus 现在返回控件的 HWND, 而不是其 ClassNN, 并且当它成功确定窗口没有焦点控件时, 不再认为有错误.
ControlMove, ControlGetPos 和 ControlClick 现在使用客户端坐标(像 GuiControl) 而不是窗口坐标. 客户端坐标是相对于客户端区域的左上方而言的, 它不包括窗口的标题栏和边框. (控件只在客户端区域内渲染.)
ControlMove, ControlSend 和 ControlSetText 现在使用与其他 Control 函数一致的参数顺序; 即 Control, WinTitle, WinText, ExcludeTitle, ExcludeText 总是组合在一起(在参数列表的最后), 以帮助记忆.
CoordMode 不再接受 "Relative" 作为一种模式, 因为所有模式都是相对于某个东西的. 它与 "Window" 同义, 所以用它代替.
DllCall: 请参阅下面的 DllCall 部分.
如果没有被注册 "edit" shell 动词, Edit 以前有针对 .ini
文件类型的后备行为. 由于脚本文件不需要有 .ini
扩展名. AutoHotkey.ini
是旧版本 AutoHotkey 中的默认脚本名称.
如果脚本是从 stdin 中读取的, 那么现在 Edit 不会做任何事情, 而会尝试为 *
打开一个编辑器.
如果完全省略了 Value 参数, EnvSet 现在删除环境变量.
以前, 当脚本不是持续运行时, Exit 作为 ExitApp 使用, 即使有其他挂起的线程被调用 Exit 的线程打断. 现在它不再这样做了. 相反, 它总是正确地退出当前线程, 并且(如果不是持续运行的) 脚本只在最后一个线程退出后才终止. 这保证了 Finally 语句的执行和局部变量的释放, 这可能允许对局部变量所包含的任何对象调用 __delete
.
FileAppend 默认为没有行末转换, 与 FileRead 和 FileOpen 一致. FileAppend 和 FileRead 都有一个单独的 Options 参数, 它取代了选项前缀, 并可能包括一个可选的编码名称(取代 FileRead 的 *Pnnn
选项). FileAppend, FileRead 和 FileOpen 使用 "`n"
来实现行末转换. FileAppend 和 FileRead 支持 "RAW"
选项来禁用编码转换(读/写二进制数据); FileRead 在这种情况下返回一个 Buffer 对象
. 这取代了 *c
(请参阅 ClipboardAll). FileAppend 可以接受一个类 Buffer
对象, 在这种情况下不进行转换.
如果源路径不包含 *
或 ?
并且没有找到文件, FileCopy 和 FileMove 现在抛出异常. 然而, 当源路径包含通配符时, 复制或移动零个文件仍然不被视为错误.
FileOpen 现在如果它不能打开文件, 则抛出异常. 否则, 在第一次尝试访问对象时就会抛出异常(如果脚本没有检查失败), 而不是在实际的失败点抛出异常.
File.RawRead: 当一个变量被直接传递时, 该变量的内部字符串缓冲的地址不再被使用. 因此, 一个包含地址的变量可以直接传递(而在 v1 版中, 类似 var+0
的东西是必须的).
对于由脚本分配的缓冲, 新的 Buffer 对象
比变量更受欢迎; 可以使用任何对象, 但必须有 Ptr 和 Size 属性.
File.RawWrite: 和上面一样, 除了它可以接受一个字符串(或包含一个字符串的变量), 在这种情况下 Bytes 默认为字符串的字节大小. 字符串可以包含二进制的零.
File.ReadLine 现在总是支持 `r
, `n
和 `r`n
作为行尾, 并且不再在返回值中包括行尾. 如果没有启用 EOL 转换, File.Read 仍会按原样返回给脚本.
FileEncoding 现在允许用数字来指定代码页, 而不使用 CP
前缀. 其参数不再为可选, 但任然可以显式的指定为空值.
FileExist 现在忽略了每个目录列表中隐含的 .
和 ..
, 因此当目录存在但为空时, FileExist("dir\*")
现在是 false, 而不是 true.
FileGetAttrib 和 A_LoopFileAttrib 现在对解析点或符号链接包含字母 "L".
如果源文件和目标文件是同一路径, 非编译脚本中的 FileInstall 不再尝试复制文件(在解析了相对路径之后, 因为源文件相对于 A_ScriptDir, 而不是 A_WorkingDir). 在 v1 中, 这导致 ErrorLevel 被设置为 1, 这通常不会被注意到. 试图通过两个不同的路径将一个文件复制到自身仍然会导致错误.
FileSelectFile(现在名为 FileSelect) 有两种多选模式, 可以通过选项 4 和 M 来访问. 选项 4 和相应的模式已经被删除; 它们已经有一段时间没有记录了. 当使用多选模式时, FileSelect 现在会返回一个路径的数组, 而不是像 C:\Dir`nFile1`nFile2
这样的字符串. 每个数组元素都包含一个文件的完整路径. 如果用户取消了, 数组就是空的.
FileSelect 现在使用 Windows Vista 及以后版本中的 IFileDialog API, 而不是以前的 GetOpenFileName/GetSaveFileName API. 这样就不需要使用与对话框改变当前工作目录有关的(内置) 解决方法.
当省略 Filter 时, FileSelect 默认不再有一个多余的 "Text Documents (*.txt)"/"文本文档(*.txt)" 过滤器.
FileSelect 不再从过滤器模式中剥离空格, 例如 pattern with spaces*.ext
. 测试表明模式两侧的空格(例如 *.cpp; *.h
) 中分号后的空格) 已经被操作系统忽略, 所以应该不会有负面影响.
FileSelect 现在可以通过 D
选项字母在 "选择文件夹" 模式下使用.
FileSetAttrib 现在可以在没有 +, - 或 ^ 前缀的情况下覆盖属性, 而不是什么都不做. 例如, FileSetAttrib(FileGetAttrib(file2), file1)
将 file2 的属性复制到 file1 中(添加 file2 有的属性并删除其没有的属性).
FileSetAttrib 和 FileSetTime: OperateOnFolders 和 Recurse 参数已被一个与 Loop Files 相同的 Mode 参数所取代. 例如, FileSetAttrib("+a", "*.zip", "RF")
(只对 Files 进行递归操作).
GetKeyName 现在返回 VK 代码的非 Numpad 名称, 这些名称对应于 Numpad 和非 Numpad 键. 例如, GetKeyName("vk25")
返回 Left, 而不是 NumpadLeft.
GetKeyState 现在始终返回 1 或 0 来取代 On 和 Off.
GroupActivate 现在返回被选中激活的窗口的 HWND, 如果没有匹配的窗口(除了已经激活的窗口), 则返回 0, 而不是设置 ErrorLevel.
GroupAdd: 删除了 Label 参数和相关功能. 这是一种不直观的方式, 用于检测 GroupActivate 未能找到任何匹配的窗口; 应该改为使用 GroupActivate 的返回值来代替.
GroupDeactivate 现在以更接近 Alt+Esc 和 Alt+Shift+Esc 系统热键和任务栏的方式选择窗口. 具体而言,
不计算拥有的窗口. 如果所有者窗口符合条件(与组不匹配), 所有者窗口或其拥有的一个窗口被激活; 以最后激活的为准. 一个由组成员拥有的窗口将不再被激活, 但将拥有的窗口本身添加到组中现在没有任何影响. (以前的行为是循环浏览每个拥有的窗口, 而从不激活其所有者.)
任何被禁用的窗口都会被跳过, 除非其拥有的一个窗口最近比它更活跃.
具有 WS_EX_NOACTIVATE 风格的窗口被跳过, 因为它们可能不应该被激活. 它们也会被 Alt+Esc 和 Alt+Shift+Esc 系统热键跳过.
具有 WS_EX_TOOLWINDOW 但不具有 WS_EX_APPWINDOW 的窗口被从任务栏和 Alt-Tab 中省略, 因此被跳过.
Hotkey 不再默认为脚本中最底层 #HotIf(以前是 #If
). 热键/热字串和 HotIf 线程默认为与热键相同的条件, 因此 Hotkey A_ThisHotkey, "Off"
会关闭当前热键, 即使它是上下文相关的. 所有其他线程默认为自动执行部分使用的最后一个设置, 它本身默认为没有条件(全局热键).
Hotkey 的 Action 参数现在需要一个函数对象或热键名称. 不再支持标签和函数名称. 如果指定了一个热键名称, 则使用该热键的原始函数; 而且与以前不同的是, 这与 #HotIf(以前的 #If) 一起工作.
其他好处, 这消除了以下特殊字符串的歧义: On
, Off
, Toggle
, AltTab
, ShiftAltTab
, AltTabAndMenu
, AltTabMenuDismiss
. 以前的行为是使用该名称的标签/函数(如果存在的话), 但只有在 Label 参数不包含变量引用或表达式的情况下.
Hotkey 和 Hotstring 现在支持选项 S 以使热键/热串免于暂停 Suspend(相当于新的 #SuspendExempt 指令), 以及选项 S0 以禁止免于暂停.
"Hotkey If" 和其他 If 子命令被替换为单独的函数: HotIf, HotIfWinActive, HotIfWinExist, HotIfWinNotActive, HotIfWinNotExist.
HotIf(以前的 "Hotkey If") 现在可以识别使用 and
或 or
运算符的表达式. 这在 v1 中不起作用, 因为这些运算符在加载时被替换为 &&
或 ||
.
Hotkey 不再有 UseErrorLevel 选项, 也不再设置 ErrorLevel. 失败时将抛出异常. 错误信息被改为恒定的(而且更短), 在 Exception.Extra
中包含了按键或热键的名称, 而异常的类别则表示失败的原因.
#HotIf(以前的 #If) 现在隐式地创建了带有参数(ThisHotkey) 的函数. 如同所有函数的默认情况一样, 这个函数是假设-本地的. 该表达式可以创建局部变量和读取全局变量, 但不能直接赋值给全局变量, 因为该表达式不能包含声明.
#HotIf
已经被优化, 因此对 WinActive() 或 WinExist() 的简单调用可以由钩子线程直接计算(就像 #IfWin
在 v1 中一样, 而 HotIfWin
仍然是). 这提高了性能, 并减少了脚本繁忙/无响应时出现问题的风险. 该优化适用于包含对 WinActive() 或 WinExist() 的单次调用, 最多有两个参数的表达式, 其中每个参数是一个简单的带引号的字符串, 结果可以选择用 !
或 not
. 例如, #HotIf WinActive("Chrome")
或 #HotIf !WinExist("Popup")
. 在这些情况下, 具有任何给定标准组合的第一个表达式可以由表达式或窗口标准来确定. 例如, HotIf '!WinExist("Popup")'
和 HotIfWinNotExist "Popup"
指的是相同的热键变体.
KeyHistory N
调整按键历史缓冲的大小, 而不是显示按键历史. 这取代了 "#KeyHistory N".
ImageSearch 如果找到了图片, 则返回 1(true), 如果没有找到, 则返回 0(false), 如果不能进行搜索, 则抛出异常. 不设置 ErrorLevel.
IniDelete, IniRead 和 IniWrite 设置 A_LastError 为操作系统的 GetLastError() 函数的结果.
IniRead 抛出异常, 如果不能找到所请求的键, 段或文件, 并且省略了 Default 数. 如果 Default 被赋予一个值, 甚至是 ""
, 则不会抛出异常.
InputHook 将 Shift+Backspace 视为 Backspace, 而不是把它转录为 `b
.
InputBox 进行了语法上的革新, 使其更容易使用(参数更少). 使用方法, 请参阅 InputBox.
InStr 的 CaseSensitive 参数已被 CaseSense 替换, 它可以是 0, 1 或 "Locale".
现在, InStr 在 Occurrence 为负数时从右向左搜索(以前会导致结果为 0), 如果在 Occurrence 为正数时使用负的 StartingPos 则不再从右向左搜索. (然而, 如果 StartingPos 是负的, 而 Occurrence 是省略的, 它仍然从右向左搜索.) 这有利于在循环中进行从右到左的搜索, 并允许在使用负的 StartingPos 的同时仍然从左到右搜索.
例如, InStr(a, b,, -1, 2)
现在从左到右搜索. 如果要从右向左搜索, 请使用 InStr(a, b,, -1, -2)
.
注意 StartingPos 为 -1 意味着 v2 中的最后一个字符, v1 中的倒数第二个字符. 如果上面的例子来自 v1(而不是 v2.0-a033 - v2.0-a136), 新代码应该是 InStr(a, b, -2, -2)
.
KeyWait 现在如果等待期过了就返回 0(false), 否则返回 1(true). 删除了 ErrorLevel.
MouseClick 和 MouseClickDrag 不再受交换鼠标按钮的系统设置的影响; "Left" 始终是主按钮, 而 "Right" 是副按钮.
MsgBox 的语法发生了变化, 以优先考虑其最常用的参数, 并提高了易用性. 有关使用情况, 请参阅下面的 MsgBox.
NumPut/NumGet: 当直接传递变量时, 不再使用该变量的内部字符串缓冲的地址. 因此, 一个包含地址的变量可以直接传递(而在 v1 中, 类似 var+0
的东西是必须的). 对于由脚本分配的缓冲, 新的 Buffer 对象比变量更优先; 任何对象都可以使用, 但必须有 Ptr 和 Size 属性.
NumPut 的参数被重新排序, 以允许一连串的值, 每个数字前面都有(现在是强制性的) 类型字符串. 例如: NumPut("ptr", a, "int", b, "int", c, addrOrBuffer, offset)
. 类型现在对于 NumGet 也是必须的. (与 DllCall 相比, NumPut 的输入参数对应于 dll 函数的参数, 而 NumGet 的返回类型参数对应于 dll 函数的返回类型字符串.)
使用 Object(obj)
和 Object(ptr)
在引用和指针之间的转换被转移到单独的函数, ObjPtrAddRef(obj)
和 ObjFromPtrAddRef(ptr)
. 这些函数也有不增加引用计数的版本: ObjPtr(obj)
和 ObjFromPtr(ptr)
.
OnClipboardChange 标签不再被自动调用, 如果它存在的话. 使用在 v1.1.20 版本中添加的 OnClipboardChange 函数来代替. 现在它需要一个函数对象, 而不是一个名称.
OnError 现在需要一个函数对象, 而不是一个名称. 另请参阅下面的: 错误处理.
OnExit 命令已被移除; 请使用 v1.1.20 中添加的 OnExit 函数. 现在它需要一个函数对象, 而不是一个名称. A_ExitReason 也被删除了; 它的值可以作为 OnExit 回调函数的一个参数使用.
OnMessage 不再具有传递函数名(字符串) 时使用的单函数每条消息模式; 它现在只接受一个函数引用. 使用 OnMessage(x, MyFunc)
其中 MyFunc 是原义上的函数名称, 但请注意, V1 的等价物是 OnMessage(x, Func("MyFunc"))
, 允许其他函数继续监视消息 x, 这与 OnMessage(x, "MyFunc")
不同. 要停止监测消息, 请使用 OnMessage(x, MyFunc, 0)
, 因为 OnMessage(x, "")
和 OnMessage(x)
现在是错误的. 失败时, OnMessage 抛出异常.
当在热键的第一行使用时, Pause 不再豁免于 #MaxThreadsPerHotkey, 所以 #p::Pause
不再适用于切换暂停. 因此, Pause()
现在只暂停当前线程(对于像 ListVars/Pause 这样的组合), 而 Pause(Value)
现在始终在底层线程上操作. Value 必须是 0, 1 或 -1. 第二个参数被移除.
PixelSearch 和 PixelGetColor 使用 RGB 值而不是 BGR, 以便与其他函数保持一致. 如果出现问题, 这两个函数都会抛出异常, 并且不再设置 ErrorLevel. 如果找到了颜色, PixelSearch 返回 1(true). PixelSearch 的慢速模式已被删除, 因为它在大多数现代系统上是不可用的, 因为它与桌面合成不兼容.
PostMessage: 请参阅下面的 SendMessage.
Random 已被重做, 以利用操作系统的随机数生成器, 取消了一些限制, 并使其使用起来更加方便.
现在支持完整的 64 位有符号整数值范围(从 32 位增加).
浮点数由 53 位的随机整数生成, 而不是 32 位的随机整数, 并且应该大于或等于 Min 且小于 Max(但是浮点数的舍入误差理论上可以产生等于 Max 的结果).
这些参数已经可以以任何顺序指定, 但现在只指定第一个参数时, 会将其他边界默认为 0 而不是 2147483647. 例如, Random(9)
返回一个 0 到 9 之间的数字.
如果省略了两个参数, 则返回值是一个介于 0.0(包括) 和 1.0(一般不包括) 之间的浮点数, 而不是 0 和 2147483647(包括) 之间的整数.
系统会自动给随机数生成器播种, 不提供手动播种的方法, 所以无法替代 NewSeed 参数.
RegExMatch 选项 O 和 P 被删除; O(对象) 模式现在是强制性的. RegExMatch 对象现在支持枚举(for-loop). 匹配对象的语法已经改变:
__Get 被用来实现速记的 match.subpat
其中 subpat 是一个子模式/捕获组的名称. 因为如果一个属性被 inherited, __Get 不再被调用, 以下的子模式名称不能再使用速记语法: Pos, Len, Name, Count, Mark. (例如, match.Len
总是返回整个匹配的长度, 而不是一个捕获的字符串.)
最初, 匹配对象有方法而不是属性, 这样属性就可以保留给子模式名称, 由于新的语言行为意味着 match.name
默认会返回一个函数, 方法已经被替换为或补充为属性:
Pos, Len 和 Name 现在是属性和方法.
Name 现在需要一个参数以避免混淆(match.Name
抛出一个错误).
Count 和 Mark 现在只是属性.
Value 已被删除; 使用 match.0
或 match[]
而不是 match.Value()
, 和 match[N]
而不是 match.Value(N)
.
RegisterCallback 被重命名为 CallbackCreate 并被改为更好地利用闭包:
它现在支持函数对象(而不再支持函数名称).
删除了 EventInfo 参数(使用闭包或绑定函数代替).
删除了可变参回调函数的特殊行为, 并增加了 &
选项(传递参数列表的地址).
增加了 CallbackFree(Address)
, 以释放回调内存并释放关联的函数对象.
注册表函数(RegRead, RegWrite, RegDelete): 在 v1.1.21+ 中增加的新语法现在是唯一的语法. 根键和子键被合并. 不写 RootKey, SubKey
, 而写 RootKey\SubKey
. 要连接到一个远程注册表, 使用 \\ComputerName\RootKey\SubKey
而不是 \\ComputerName:RootKey, SubKey
.
RegWrite 的参数被重新排序, 像 IniWrite 一样把 Value 放在前面(但这并不影响单参数模式, 其中 Value 是唯一参数).
当 KeyName 被省略, 并且当前的循环注册项目是一个子键时; RegDelete, RegRead 和 RegWrite 现在对该子键内的值进行操作; 即在这种情况下, KeyName 默认为 A_LoopRegKey "\" A_LoopRegName
(注意, A_LoopRegKey 与 A_LoopRegSubKey 合并了). 以前它们的表现如下:
RegRead 读取一个与子键同名的值, 如果父键中存在这样的子键.
RegWrite 返回一个错误.
RegDelete 删除该子键.
RegDelete, RegRead 和 RegWrite 现在允许在省略 KeyName 时指定 ValueName:
如果当前循环注册表项是一个子键, ValueName 默认为空(子键的默认值) 并且必须指定 ValueType.
如果当前的循环注册表项是一个值, ValueName 和 ValueType 默认为该值的名称和类型, 但其中一个或两个可以被覆盖.
否则, 带有空白或省略 ValueName的 RegDelete 现在会删除键的默认值(而不是键本身), 以便与 RegWrite, RegRead 和 A_LoopRegName 一致. 短语 "AHK_DEFAULT" 不再有任何特殊含义. 要删除一个键, 请使用 RegDeleteKey(新).
RegRead 现在有一个 Default 参数, 像 IniRead 一样.
RegRead 有一个未记录的 5 参数模式, 即在输出变量之后指定值类型. 这已被删除.
如果脚本是从 stdin 读取的, 那么现在 Reload 将不做任何事情.
Run 和 RunWait 不再识别 UseErrorLevel 选项, 因为 ErrorLevel 已被删除. 使用 Try/Catch 代替. A_LastError 被无条件地设置, 并且可以在捕获/抑制异常后进行检查. RunWait 返回退出代码.
Send(及其变体) 现在以一种与热键和 Click 一致的方式解释 {LButton}
和 {RButton}
. 也就是说, LButton 是主按钮, RButton 是次按钮, 即使用户通过系统设置交换了这些按钮.
SendMessage 和 PostMessage 现在要求 wParam 和 lParam 是整数或具有 Ptr 属性的对象; 如果它们被赋予一个非数字的字符串或浮点, 则抛出异常. 以前, 如果表达式以 "
开头, 则通过地址传递字符串, 但其他字符串被强制为整数. 传递一个变量的地址(以前是 &var
, 现在是 StrPtr(var)
) 不再更新变量的长度(使用 VarSetStrCapacity(&var, -1)
).
SendMessage 和 PostMessage 现在在失败(或超时) 时抛出异常, 并且不设置 ErrorLevel. SendMessage 返回消息回复.
SetTimer 不再支持标签或函数名称, 但由于它现在接受表达式, 并且函数可以直接通过名称引用, 用法看起来非常相似: SetTimer MyFunc
. 与所有其他接受对象的函数一样, SetTimer 现在允许返回对象的表达式(以前它需要一个变量引用).
Sort 得到了以下变化:
VarName 参数已被分成独立的输入/输出参数, 以增加灵活性. 现在的用法是 Output := Sort(Input [, Options, Callback])
.
当任何两个项目比较相等时, 项目的原始顺序将自动作为决定顺序的因素, 以确保结果更加稳定.
C
选项现在也接受相当于其他函数的 CaseSense 参数的后缀(除 CL
外): CLocale CLogical COn C1 COff C0
. 特别是, 对 "logical" 比较模式的支持是新加入的.
Sound 函数: 修改了 SoundGet 和 SoundSet 以更好地匹配 Vista+ 声音 API 的功能, 放弃了对 XP 的支持.
删除了不支持的控制类型.
删除了传统的混音器组件类型.
让组件通过名称和/或索引来引用.
让设备通过名称-前缀和/或索引来引用.
分成独立的音量和静音功能.
增加了 SoundGetName 用于检索设备或组件名称.
增加了 SoundGetInterface 用于检索 COM 接口.
StrGet: 如果 Length 是负数, 它的绝对值表示要转换的确切字符数, 包括字符串可能包含的任何二进制零值 - 换句话说, 结果总是一个正好是这个长度的字符串. 如果 Length 是正数, 转换后的字符串在第一个二进制 0 处结束, 就像在 v1 中一样.
StrGet/StrPut: Address 参数可以是一个具有 Ptr 和 Size 属性的对象, 比如新的 Buffer 对象. 读/写会自动受到 Size(单位为字节) 的限制. 如果还指定了 Length 它不能超过 Size(对于 UTF-16 来说乘以 2).
StrPut 的返回值现在是以字节为单位, 所以它可以直接传递给 Buffer()
.
StrReplace 现在有一个 CaseSense 参数来代替 OutputVarCount, 它被移到了一个参数的右边, Limit 在它后面.
Suspend: 在热键或热串的第一行调用 Suspend 不再自动使其免于挂起. 相反, 使用 #SuspendExempt
或 S
选项. "Permit" 参数值不再有效.
Switch 现在默认对字符串进行区分大小写的比较, 并且有一个 CaseSense 参数, 可以覆盖区分大小写的模式, 强制进行字符串(而不是数字) 比较. 以前, 只有当 StringCaseSense 被改为 On 时, 它才区分大小写.
SysGet 现在只有数字子命令; 它的其他子命令已经被分割成函数. 有关详情, 请参阅子命令.
TrayTip 的用法已改为 TrayTip [Text, Title, Options]
. Options 是一个由零个或多个不区分大小写的选项组成的字符串, 以空格或制表符分隔. 选项是 Iconx
, Icon!
, Iconi
, Mute
和/或任何数值, 如以前一样. 即使省略了 Text 也会显示(现在比 V1 版更难意外地显示). Timeout 参数不再存在(它在 Windows Vista 或更高版本中没有作用). 脚本现在可以结合使用 NIIF_USER(0x4) 和 NIIF_LARGE_ICON(0x20) 标记 (0x24) 来在通知中包含大版本的托盘图标. NIIF_USER(0x4) 也可以单独用于小图标, 但无法在所有操作系统中产生一致的结果.
#Warn UseUnsetLocal 和 UseUnsetGlobal 已经被删除, 因为现在读取一个未设置的变量会抛出错误. 可以使用 IsSet 来避免错误, 也可以使用 Try/Catch 或 OnError 来处理它.
添加了 #Warn VarUnset 它默认为 MsgBox. 如果没有禁用, 在变量从未被用作直接的, 非动态的赋值或引用运算符(&) 的目标, 或直接传递给 IsSet 时, 对于每个变量的第一个非动态引用会给出警告.
#Warn Unreachable 不再认为 Exit 调用后的行是不可达的, 因为 Exit 现在是一个普通函数.
#Warn 已被删除, 因为顶级类不再被赋值所覆盖. (然而, 它们现在可以被一个局部变量隐式地覆盖; 这可以被 #Warn LocalSameAsGlobal 检测到.)
WinActivate 现在在第一次尝试激活一个窗口失败后会发送 {Alt up}
测试表明这减少了任务栏按钮闪烁的情况. 有关详情, 请参阅相关文档.
WinClose 和 WinKill: 对于 SecondsToWait, 指定 0 不再等同于指定 0.5; 相反, 它会产生最短的等待时间.
WinSetTitle 和 WinMove 现在使用与其他 Win 函数一致的参数顺序; 即 WinTitle, WinText, ExcludeTitle, ExcludeText 总是组合在一起(在参数列表的最后), 以帮助记忆.
各种函数的 WinTitle 参数现在可以接受一个 HWND(必须是纯整数) 或一个具有 Hwnd 属性的对象, 如一个 Gui 对象. 在这种情况下, DetectHiddenWindows 会被忽略, 除了当与 WinWait 或 WinWaitClose 一起使用时.
WinMove 不再对原义单词 DEFAULT
进行特殊处理. 省略该参数或指定一个空字符串代替(这适用于 v1 和 v2).
WinWait, WinWaitClose, WinWaitActive 和 WinWaitNotActive 在等待结束(超时未过) 时返回非零值). ErrorLevel 被删除. WinWait 和 WinWaitActive 返回找到的窗口的 HWND. WinWaitClose 现在设置了最后找到的窗口, 所以如果 WinWaitClose 超时, 它返回 0(false), WinExist()
返回最后找到的窗口. 对于 Timeout, 指定 0 不再等同于指定 0.5; 相反, 它产生了尽可能短的等待.
InStr, SubStr, RegExMatch 和 RegExReplace 的负的 StartingPos 被解释为从末尾开始的位置. 位置 -1 是最后一个字符, 位置 0 是无效的(而在 V1 中, 位置 0 是最后一个字符).
以前接受 On/Off 或 On/Off/Toggle(但不接受其他字符串) 的函数现在需要 1/0/-1 来代替. On 和 Off 通常会被替换成 True
和 False
. 原先返回 On/Off 的变量现在返回 1/0, 这在表达式中更加有用.
#UseHook 和 #MaxThreadsBuffer 允许 1
, 0
, True
和 False
.
(不像其他的, 它们实际上不支持表达式.)
ListLines 允许省略或布尔值.
ControlSetChecked, ControlSetEnabled, Pause, Suspend, WinSetAlwaysOnTop 和 WinSetEnabled 允许 1
, 0
和 -1
.
A_DetectHiddenWindows, A_DetectHiddenText 和 A_StoreCapsLockMode 使用布尔值(相应的函数也是如此).
以下函数返回一个纯整数, 而不是十六进制字符串:
ControlGetExStyle
ControlGetHwnd
ControlGetStyle
MouseGetPos
WinActive
WinExist
WinGetID
WinGetIDLast
WinGetList (在数组中)
WinGetStyle
WinGetStyleEx
WinGetControlsHwnd(在数组中)
A_ScriptHwnd 返回纯整数.
DllCall
如果类型参数是变量, 该变量的内容总是被使用, 而不是它的名称. 换句话说, 不再支持不加引号的类型名 - 类型名必须用引号括起来.
当 DllCall 更新以 Str 或 Str 形式传递的变量的长度时, 它现在会检测字符串是否正确地空终止(可能表明发生了缓冲溢出), 如果是这样, 会以错误消息终止程序, 因为不能保证安全执行.
AStr
(没有任何后缀) 现在是只输入的. 因为缓冲永远只和输入字符串一样大, 所以它通常对输出参数没有用. 如果 AutoHotkey 被编译为 ANSI, 这将适用于 WStr 而不是 AStr, 但官方的 v2 版本只被编译为 Unicode.
如果一个函数向 Str*
, AStr*
或 WStr*
参数写入一个新的地址, DllCall 现在会将新的字符串分配给相应的变量(如果有的话), 而不是仅仅更新原始字符串的长度(可能没有变化). 这种类型的参数通常不是用来修改输入的字符串, 而是在新的地址传回一个字符串.
DllCall 现在为任何 Ptr
参数和 Function 参数接受一个对象; 该对象必须有一个 Ptr 属性. 对于脚本分配的缓冲, 新的 Buffer 对象优先于变量. 对于 Ptr*
, 参数的新值被分配回对象的 Ptr 属性. 这允许诸如 DllCall(..., "Ptr*", unk := IUnknown())
这样的结构, 与 DllCall(..., "Ptr*", punk), unk := IUnknown(punk)
相比, 减少了重复, 并且可以用来确保函数的任何输出被正确释放(即使由于 HRESULT
返回类型而抛出异常, 尽管通常在这种情况下函数不会输出一个非空指针).
DllCall 现在要求数字型参数的值必须是数字, 如果给出的是非数字或空字符串, 则会抛出异常. 特别是, 如果输出参数使用了 * 或 P 的后缀, 输出变量需要被初始化.
如果脚本传递一个包含数字的普通变量, 那么带有 * 或 P 后缀的数字参数的输出值(如果有的话) 会被忽略. 要接收输出值, 请传递一个 VarRef, 如 &myVar
或一个具有 Ptr 属性的对象.
如果函数失败, 新的 HRESULT
返回类型会抛出异常(int < 0
或 uint & 0x80000000
). 这应该只用于实际返回 HRESULT
的函数.
Loop 子命令
子命令关键词必须按原义书写, 不能用引号括起来, 也不能是一个变量或表达式. 所有其他参数都是表达式. 所有循环子命令现在都支持 OTB.
已删除的:
Loop, FilePattern [, IncludeFolders, Recurse]
Loop, RootKey [, Key, IncludeSubkeys, Recurse]
使用下面的方法(在 v1.1.21 中添加) 来代替:
Loop Files, FilePattern [, Mode]
Loop Reg, KeyName [, Mode]
第二个单词后面的逗号现在是可选的.
A_LoopRegKey 现在包含根键和子键, 而 A_LoopRegSubKey 已被删除.
InputBoxObj := InputBox([Prompt, Title, Options, Default])
Options 参数接受零个或多个不区分大小写的选项的字符串, 以空格或制表符为界, 类似于 Gui 控件选项. 例如, 这包括所有支持的选项: "x0 y0 w100 h100 T10.0 Password*"
. T
是超时, 而 Password
的用法与同等的 Edit 控件选项相同.
宽度和高度选项现在可以设置客户端区域的大小(不包括标题栏和窗口框架的区域), 因此对主题的依赖性较小.
如果 Title 参数是一个空字符串, 标题将是空白的. 它只有在完全省略时才默认为 A_ScriptName 与用户定义函数的可选参数一致.
InputBoxObj 是一个对象, 其属性是 Result(包含 "OK", "Cancel" 或 "Timeout") 和 Value.
MsgBox
Result := MsgBox([Text, Title, Options])
Options 参数接受由零个或多个不区分大小写的选项组成的字符串, 以空格或制表符为界, 类似于 Gui 控件选项.
Iconx
, Icon?
, Icon!
和 Iconi
设置图标.
Default
后面紧跟一个整数, 设置第 n 个按钮为默认值.
T
后面紧跟一个整数或浮点数, 设置超时, 单位是秒.
Owner
后跟 HWND 设置所有者, 覆盖 +OwnDialogs
选项.
以下相互排斥的字符串之一设置按钮的选择: OK
, OKCancel
, AbortRetryIgnore
, YesNoCancel
, YesNo
, RetryCancel
, CancelTryAgainContinue
, 或者只是用斜线分隔的首字母(o/c
, y/n
, 等等.), 或者只是没有斜线的首字母.
任何数字值, 与 v1 中的相同. 数字值可以与字符串选项相结合, 或者 Options 可以是纯整数.
返回值是按钮的英语名称, 不带空格. 这些都是与 IfMsgBox 在 v1 中使用的字符串相同.
如果 Title 参数是一个空字符串, 标题将是空白. 只有当完全省略时, 它才默认为 A_ScriptName, 与用户定义的函数的可选参数一致.
Control, ControlGet, Drive, DriveGet, WinGet, WinSet 和 Process 的子命令已被替换为单独的函数, 而主命令已被删除. 一些函数的名称和用法已经改变. 新的用法如下所示:
; 其中 ... 表示可选的 Control, WinTitle, 等等.
Bool := ControlGetChecked(...)
Bool := ControlGetEnabled(...)
Bool := ControlGetVisible(...)
Int := ControlGetIndex(...) ; 适用于 Tab, LB, CB, DDL
Str := ControlGetChoice(...)
Arr := ControlGetItems(...)
Int := ControlGetStyle(...)
Int := ControlGetExStyle(...)
Int := ControlGetHwnd(...)
ControlSetChecked(TrueFalseToggle, ...)
ControlSetEnabled(TrueFalseToggle, ...)
ControlShow(...)
ControlHide(...)
ControlSetStyle(Value, ...)
ControlSetExStyle(Value, ...)
ControlShowDropDown(...)
ControlHideDropDown(...)
ControlChooseIndex(Index, ...) ; 同样涉及 Tab
Index := ControlChooseString(Str, ...)
Index := ControlFindItem(Str, ...)
Index := ControlAddItem(Str, ...)
ControlDeleteItem(Index, ...)
Int := EditGetLineCount(...)
Int := EditGetCurrentLine(...)
Int := EditGetCurrentCol(...)
Str := EditGetLine(N [, ...])
Str := EditGetSelectedText(...)
EditPaste(Str, ...)
Str := ListViewGetContent([Options, ...])
DriveEject([Drive])
DriveRetract([Drive])
DriveLock(Drive)
DriveUnlock(Drive)
DriveSetLabel(Drive [, Label])
Str := DriveGetList([Type])
Str := DriveGetFilesystem(Drive)
Str := DriveGetLabel(Drive)
Str := DriveGetSerial(Drive)
Str := DriveGetType(Path)
Str := DriveGetStatus(Path)
Str := DriveGetStatusCD(Drive)
Int := DriveGetCapacity(Path)
Int := DriveGetSpaceFree(Path)
; 其中 ... 表示可选的 WinTitle, 等等.
Int := WinGetID(...)
Int := WinGetIDLast(...)
Int := WinGetPID(...)
Str := WinGetProcessName(...)
Str := WinGetProcessPath(...)
Int := WinGetCount(...)
Array := WinGetList(...)
Int := WinGetMinMax(...)
Array := WinGetControls(...)
Array := WinGetControlsHwnd(...)
Int := WinGetTransparent(...)
Str := WinGetTransColor(...)
Int := WinGetStyle(...)
Int := WinGetExStyle(...)
WinSetTransparent(N [, ...])
WinSetTransColor("Color [N]" [, ...]),
WinSetAlwaysOnTop([TrueFalseToggle := 1, ...])
WinSetStyle(Value [, ...])
WinSetExStyle(Value [, ...])
WinSetEnabled(Value [, ...])
WinSetRegion(Value [, ...])
WinRedraw(...)
WinMoveBottom(...)
WinMoveTop(...)
PID := ProcessExist([PID_or_Name])
PID := ProcessClose(PID_or_Name)
PID := ProcessWait(PID_or_Name [, Timeout])
PID := ProcessWaitClose(PID_or_Name [, Timeout])
ProcessSetPriority(Priority [, PID_or_Name])
ProcessExist, ProcessClose, ProcessWait 和 ProcessWaitClose 不再设置 ErrorLevel; 相反, 它们返回 PID.
其他函数都不设置 ErrorLevel. 相反, 它们在失败时抛出异常. 在大多数情况下, 失败是因为没有找到目标窗口或控件.
HWND 和样式总是以纯整数形式返回, 而不是十六进制字符串.
ControlChooseIndex 允许 0 来取消对当前项目/所有项目的选择. 它取代了控件选择, 但也支持 Tab 控件.
ControlGet 被合并到 ControlGetIndex, 它也适用于 ListBox, ComboBox 和 DDL. 对于 Tab 控件, 如果没有选择 Tab, 它将返回 0(很少见, 但有效). ControlChooseIndex 不允许 Tab 控件使用 0, 因为应用程序往往不会处理它.
ControlGetItems 取代了 ListBox 和 ComboBox 的 ControlGet List. 它返回一个数组.
DriveEject 和 DriveRetract 现在使用 DeviceIoControl 而不是 mciSendString. DriveEject 能够弹出在资源管理器中有 "弹出" 选项的非 CD/DVD 驱动器(即可移动驱动器, 但不包括显示为固定磁盘的外部硬盘).
ListViewGetContent 取代了 ListView 的 ControlGet List, 目前的用法与以前相同.
WinGetList, WinGetControls 和 WinGetControlsHwnd 返回数组, 而不是以新行分隔的列表.
WinSetTransparent 将 "" 视为 "Off", 而不是 0(这将使窗口不可见且无法点击).
缩写的别名, 如 Topmost, Trans, FS 和 Cap 被删除.
以下函数以前是 SysGet 的子命令:
ActualN := MonitorGet([N, &Left, &Top, &Right, &Bottom])
ActualN := MonitorGetWorkArea([N, &Left, &Top, &Right, &Bottom])
Count := MonitorGetCount()
Primary := MonitorGetPrimary()
Name := MonitorGetName([N])
Buffer([ByteCount, FillByte])
(调用 Buffer 类) 创建并返回一个封装了 ByteCount 字节的内存块的 Buffer
对象, 只在 FillByte 被指定时才初始化. BufferObj.Ptr
返回地址, 而 BufferObj.Size
返回或设置字节大小(重新分配内存块). 任何具有 Ptr 和 Size 属性的对象都可以传递给 NumPut, NumGet, StrPut, StrGet, File.RawRead, File.RawWrite 和 FileAppend. 任何具有 Ptr 属性的对象都可以被传递给 DllCall 的 Ptr
类型, SendMessage 和 PostMessage 参数.
CaretGetPos([&OutputVarX, &OutputVarY])
检索光标(文本插入点) 的当前坐标. 这确保了 X 和 Y 坐标总是匹配的, 并且没有缓存导致意外的行为(比如 A_CaretX/Y 返回一个不在当前 CoordMode 中的值).
ClipboardAll([Data, Size])
创建一个包含剪贴板上所有内容的对象(可选择接受先前从剪贴板上获取的数据, 而不是使用剪贴板的当前内容). 读和写剪贴板文件数据的方法是不同的. 数据格式是一样的, 只是数据大小总是 32 位的, 这样数据就可以在 32 位和 64 位的构建之间移植. 详情见 v2 版文档.
ComCall(offset, comobj, ...)
等同于 DllCall(NumGet(NumGet(comobj.ptr) + offset * A_Index), "ptr", comobj.ptr, ...)
, 但返回类型默认为 HRESULT
, 而不是 Int
.
ComObject(以前是 ComObjCreate) 和 ComObjQuery 现在返回一个包装对象, 即使指定了一个 IID. ComObjQuery 允许第一个参数是任何具有 Ptr 属性的对象.
ControlGetClassNN 返回指定控件的 ClassNN.
ControlSendText 等同于 ControlSendRaw 但使用 Text 模式而不是 Raw 模式.
DirExist(FilePattern)
用法类似于 FileExist. 注意 通配符检查, 如 InStr(FileExist("MyFolder\*"), "D")
, 其中 MyFolder 包含文件和子文件夹, 只告诉你 第一个 匹配的文件是否是一个文件夹, 而不是一个文件夹是否存在.
Float(Value)
: 请参阅类型.
InstallKeybdHook([Install, Force])
和 InstallMouseHook([Install, Force])
替换相应的指令, 为了提高稳定性.
Integer(Value)
: 请参阅类型.
IsXXX: 传统的命令 "if Var is Type" 已经被一系列的函数取代: IsAlnum, IsAlpha, IsDigit, IsFloat, IsInteger, IsLower, IsNumber, IsSpace, IsUpper, IsXDigit. 除了 sFloat, IsInteger 和 IsNumber 外, 如果参数不是字符串, 则会抛出异常, 因为隐式转换为字符串可能会导致反直觉的结果.
IsSet(Var)
, IsSetRef(&Ref)
: 如果变量已经被分配了一个值(即使该值是一个空字符串), 则返回 1(true), 否则返回 0(false). 如果是 0(false), 试图在表达式中读取该变量会出现错误.
Menu()
/MenuBar()
返回一个新的 Menu/MenuBar 对象, 它有以下成员, 对应于 V1 Menu 子命令. 方法: Add, AddStandard, Check, Delete, Disable, Enable, Insert, Rename, SetColor, SetIcon, Show, ToggleCheck, ToggleEnable, Uncheck. 属性: ClickCount, Default, Handle(替换 MenuGetHandle). A_TrayMenu 也返回一个菜单对象. 没有 UseErrorLevel 模式, 没有全局菜单名称, 也没有显式删除菜单本身(当所有引用被释放时就会发生; Delete 等同于 v1 DeleteAll). 不支持标签, 只支持函数对象. AddStandard 方法添加了标准的菜单项, 并允许它们像自定义项一样被单独修改. 与 v1 不同, Win32 菜单只有在对象被删除时才会被销毁.
MenuFromHandle(Handle)
检索对应于 Win32 菜单句柄的菜单或 MenuBar 对象, 如果它是由 AutoHotkey 创建的.
Number(Value)
: 请参阅上面的类型.
Persistent([Persist])
替换相应的指令, 增加灵活性.
RegDeleteKey([KeyName])
删除一个注册表键. (RegDelete 现在只删除值, 除非在注册表循环中省略所有参数.)
SendText 等同于 SendRaw, 但使用 {Text} 模式而不是 {Raw} 模式.
StrCompare(String1, String2 [, CaseSense := false])
返回 -1(String1 小于 String2), 0(相等) 或 1(大于). CaseSense 可以是 "Locale".
String(Value)
: 请参阅上面的类型.
StrPtr(Value)
返回字符串的地址. 与 v1 中的取址不同, 它可以用于原义字符串和临时字符串.
SysGetIPAddresses()
返回一个 IP 地址的数组, 相当于已经被删除的 A_IPAddress 变量. 每个对 A_IPAddress%N%
的引用都会检索所有的地址, 但只返回一个, 所以检索多个地址所花费的时间是指数级的. 返回的数组可以有零个或多个元素.
TraySetIcon([FileName, IconNumber, Freeze])
替换 "Menu Tray, Icon".
VarSetStrCapacity(&TargetVar [, RequestedCapacity])
取代了 V1 的 VarSetCapacity, 但只用于 UTF-16 字符串(如优化重复连接); 因此 RequestedCapacity 和返回值的单位是字符而不是字节.
VerCompare(A, B)
使用与 #Requires 相同的算法对两个版本字符串进行比较.
WinGetClientPos([&OutX, &OutY, &OutWidth, &OutHeight, WinTitle, ...])
检索窗口客户端区域的位置和大小, 以屏幕坐标表示.
#DllLoad [FileOrDirName]
: 在脚本开始执行前加载一个 DLL 或 EXE 文件.
A_AhkPath 总是返回当前可执行文件/解释器的路径, 即使脚本已被编译. 以前, 如果使用 BIN 文件作为基础文件, 它会返回编译后的脚本的路径, 但 V2.0 版本不再包括 BIN 文件.
如果脚本没有被编译, A_IsCompiled 会返回 0 而不是 "".
A_OSVersion 总是返回格式为 major.minor.build
的字符串, 例如 6.1.7601
对应于 Windows 7 SP1. 由于只支持基于 NT 的系统, 因此删除了 A_OSType.
当 A_PriorHotkey 为 "" 时, A_TimeSincePriorHotkey 返回 "" 代替 -1 , 同样当 A_ThisHotkey 为空时, A_TimeSinceThisHotkey 返回空值.
所有内置的 "虚拟" 变量现在都有 A_
前缀(具体细节见下文). 任何没有这个前缀的预定义变量(比如 Object
) 都只是全局变量. 这种区别可能很重要, 因为目前不可能对一个虚拟变量进行引用(除非直接传递给一个内置函数); 然而, A_Args 不是一个虚拟变量.
返回数字的内置变量现在以整数, 而不是字符串的形式返回.
A_LoopFileFullPath → A_LoopFilePath (如果 Loop 的参数是相对的, 则返回相对路径, 所以 "full path" 会产生误解)
A_LoopFileLongPath → A_LoopFileFullPath
Clipboard → A_Clipboard
ClipboardAll(使用 ClipboardAll 函数代替)
ComSpec(使用 A_ComSpec)
ProgramFiles(使用 A_ProgramFiles)
A_AutoTrim
A_BatchLines
A_CaretX, A_CaretY(使用 CaretGetPos)
A_DefaultGui, A_DefaultListView, A_DefaultTreeView
A_ExitReason
A_FormatFloat
A_FormatInteger
A_Gui, A_GuiControl, A_GuiControlEvent, A_GuiEvent, A_GuiX, A_GuiY, A_GuiWidth, A_GuiHeight(全部替换为事件处理程序的参数)
A_IPAddress1, A_IPAddress2, A_IPAddress3, A_IPAddress4(使用 SysGetIPAddresses)
A_IsUnicode(v2 总是 Unicode; 它可以替换为 StrLen(Chr(0xFFFF))
或用 global A_IsUnicode := 1
重新定义)
A_StringCaseSense
A_ThisLabel
A_ThisMenu, A_ThisMenuItem, A_ThisMenuItemPos(使用菜单项回调的参数)
A_LoopRegSubKey(A_LoopRegKey 现在包含根键和子键)
True 和 False(仍然存在, 但现在只是关键字, 而不是变量)
A_AllowMainWindow(读/写; 替换 "Menu Tray, MainWindow/NoMainWindow")
A_HotkeyInterval(替换 #HotkeyInterval)
A_HotkeyModifierTimeout(替换 #HotkeyModifierTimeout)
A_InitialWorkingDir(请参阅下面的默认设置)
A_MaxHotkeysPerInterval(替换 #MaxHotkeysPerInterval)
A_MenuMaskKey(替换 #MenuMaskKey)
以下内置变量可以被赋值:
A_ControlDelay
A_CoordMode..
A_DefaultMouseSpeed
A_DetectHiddenText(同样, 它现在返回 1 或 0, 而不是 "On" 或 "Off")
A_DetectHiddenWindows(同样, 它现在返回 1 或 0, 而不是 "On" 或 "Off")
A_EventInfo
A_FileEncoding(同样, 它现在返回 "CP0" 代替 "", 并允许在赋值时省略 "CP" 前缀)
A_IconHidden
A_IconTip(同样, 它现在总是反映 tooltip, 即使它是默认的或空的)
A_Index: 对于计数的循环, 修改它将影响执行多少次迭代. (内置变量的全局性质意味着枚举器函数可以设置索引, 以便 For 循环查看.)
A_KeyDelay
A_KeyDelayPlay
A_KeyDuration
A_KeyDurationPlay
A_LastError: 调用 Win32 SetLastError() 函数. 同样, 它现在返回一个无符号值.
A_ListLines
A_MouseDelay
A_MouseDelayPlay
A_RegView
A_ScriptName: 更改默认的对话框标题.
A_SendLevel
A_SendMode
A_StoreCapsLockMode(同样, 它现在返回 1 或 0, 而不是 "On" 或 "Off")
A_TitleMatchMode
A_TitleMatchModeSpeed
A_WinDelay
A_WorkingDir: 等同于调用 SetWorkingDir.
现在, 文件对象在调用属性时严格要求使用属性语法, 在调用方法时严格要求使用方法语法. 例如, FileObj.Pos(n)
是无效的. 如果参数太少或太多, 或者只读属性被赋值, 则抛出异常.
File.Tell() 被删除.
Func.IsByRef() 现在可以与内置函数一起工作.
Gui, GuiControl 和 GuiControlGet 被 Gui() 和 Gui/GuiControl 对象所取代, 它们通常更灵活, 更一致, 更容易使用.
GUI 通常不是通过名字/数字编号来引用的(尽管它仍然可以用 GuiObj.Name
命名). 相反, GUI 对象(和窗口) 是通过实例化 Gui
类显式创建的, 如 GuiObj := Gui()
. 这个对象具有取代 Gui 子命令的方法和属性. Gui.Add() 返回一个 GuiControl 对象, 该对象具有替代 GuiControl 和 GuiControlGet 命令的方法和属性. 人们可以将这个对象存储在一个变量中, 或者使用 GuiObj["Name"]
或 GuiCtrlFromHwnd 来检索这个对象. 每当调用一个事件处理程序(g-label 的替换) 时, 它也会作为一个参数被传递.
这些方法和属性的用法不是 1:1. 许多部分已经被修改, 以使其更加一致和灵活, 并修复错误或限制.
没有 "默认" GUI, 因为目标 Gui 或控制对象总是被指定的. LV/TV/SB 函数被替换为(控件对象的) 方法, 使得使用多个 ListViews/TreeViews 更加容易.
没有包含事件信息的内置变量. 这些信息被作为参数传递给处理事件的函数/方法, 包括源 Gui 或控件.
控件仍然可以被命名, 并且可以通过名字来引用, 但它只是一个名称(与 GuiObj["Name"]
和 Gui.Submit() 一起使用), 而不是一个关联变量, 所以不需要声明或创建一个全局或静态变量. 该值绝不会自动存储在变量中, 而是通过 GuiControl.Value 进行访问. Gui.Submit() 返回一个以控件名称作为键的新关联数组.
vName
选项现在只是将控件的名称设置为 Name.
+HwndVarName
选项已被删除, 改为使用 GuiControl.Hwnd.
不再有 "g-labels" 或标签/函数来自动处理 GUI 事件. 脚本必须通过调用 Gui 或 GuiControl 的 OnEvent 方法来注册每个感兴趣的事件. 例如, 脚本不会在 g-label 中检查 if (A_GuiEvent = "I" && InStr(ErrorLevel, "F", true))
, 脚本将为 ItemFocus 事件注册处理程序: MyLV.OnEvent("ItemFocus", MyFunction)
. MyFunction 将仅为 ItemFocus 事件调用. 没有必要应用 AltSubmit
选项来启用其他事件.
数组被用于以前使用管道分隔的列表的地方, 例如在创建 ListBox 时, 在添加项目时, 或在检索选定的项目时, 为 ListBox 指定项目.
脚本可以定义一个 extends Gui
的类, 并处理它自己的事件, 使所有的 GUI 逻辑自成一体.
Gui 子命令
Gui New → Gui(). 传递空标题(不省略) 现在会导致空标题, 而不是默认标题.
Gui Add → Gui.Add() 或 Gui.AddControlType(); 例如 GuiObj.Add("Edit")
或 GuiObj.AddEdit()
.
Gui Show → Gui.Show(), 但它没有 Title 参数. 标题可以由 Gui() 的参数或通过 Gui.Title 属性来指定. 初始焦点仍然设置为具有 WS_TABSTOP 样式的第一个可输入控件(根据系统的默认消息处理), 除非是 Button 控件, 在这种情况下, 焦点现在转移到 Default(默认) 按钮上.
Gui Submit → Gui.Submit(). 除了 Submit() 创建并返回一个包含所有 "关联变量" 的新对象之外, 它的工作方式与以前类似.
Gui Destroy → Gui.Destroy(). 该对象仍然存在(直到脚本释放它), 但不能使用. 必须创建新的 GUI(如果需要). 删除对象时, 窗口也会被销毁, 但当窗口可见时, 该对象将 "保持活动状态".
Gui Font → Gui.SetFont(). 也可以使用 GuiControl.SetFont() 直接设置控件的字体.
Gui Color → Gui.BackColor 设置/返回背景颜色. 不支持 ControlColor(第二个参数), 但所有以前支持它的控件都可以使用 +Background
选项来设置背景. 与 Gui Color 不同, Gui.BackColor 不会影响 Progress 控件或禁用的/只读的 Edit, DDL, ComboBox 或 TreeView(带有 -Theme
) 控件.
Gui Margin → Gui.MarginX 和 Gui.MarginY 属性.
Gui Menu → Gui.MenuBar 设置/返回使用 MenuBar()
创建的 MenuBar 对象.
Gui Cancel/Hide/Minimize/Maximize/Restore → 使用同名的 Gui 方法.
Gui Flash → Gui.Flash(), 但使用 false
代替 Off
.
Gui Tab → GuiControl.UseTab(). 与以前一样, 默认匹配选项卡名称的前缀. 对于第二个参数传递 true 以匹配整个选项卡名称, 但与 v1 "Exact" 模式不同, 它不区分大小写.
关于所有显式支持的 GUI 和 GUI 控件事件的细节, 请参阅事件(OnEvent).
Size 事件传递 0, -1 或 1(与 WinGetMinMax 一致) 而不是 0, 1 或 2.
ContextMenu 事件可以为每个控件注册, 也可以为整个 GUI 注册.
DropFiles 事件交换了 FileArray 和 Ctrl 参数, 以便与 ContextMenu 一致.
ContextMenu 和 DropFiles 事件使用客户端坐标, 而不是窗口坐标(Client 也是 v2 中的默认的 CoordMode).
删除了以下控件事件, 但检测它们只需将适当的数字通知代码(在 Windows SDK 中定义) 传递给 GuiControl.OnNotify() 即可: K, D, d, A, S, s, M, C, E 和 MonthCal 的 1 和 2.
Control 事件不传递事件名称作为参数(GUI 事件从未传递过).
自定义的 N 和 Normal 事件被 GuiControl.OnNotify() 和 GuiControl.OnCommand() 取代, 它们可以用于任何控件.
Link 的 Click 事件传递 "Ctrl, ID 或 Index, HREF", 而不是 "Ctrl, Index, HREF 或 ID", 如果注册了 Click 回调, 则不会自动执行 HREF.
ListView 的 Click, DoubleClick 和 ContextMenu(当由右键触发时) 事件现在报告被点击的项目(如果没有则为 0), 而不是焦点项目.
ListView 的 I 事件被拆分为多个命名事件, 除了 f(取消焦点)事件, 因为它被 F(ItemFocus) 所隐含, 所以被排除.
ListView 的 e(ItemEdit) 事件在用户取消时被忽略.
Slider 的 Change 事件比 V1 的 g-label 事件更稳定地被引发; 也就是说, 它不再默认忽略鼠标滚轮的变化. 有关详情, 请参阅检测更改(Slider).
BS_NOTIFY 样式现在会根据需要自动添加到 Button, CheckBox 和 Radio 控件. 它不再被默认应用于 Radio 控件.
Focus(以前的 F) 和 LoseFocus(以前的 f) 支持更多的(但不是全部) 控件类型.
使用 Edit.Value 或 Edit.Text 设置 Edit 控件的文本不会触发该控件的 Change 事件, 而 GuiControl 会触发该控件的 g-label.
LV/TV.Add/Modify 现在抑制了项目变更事件, 所以这类事件只能由用户操作或 SendMessage 引发.
+Delimiter
+HwndOutputVar (使用 Gui.Hwnd 或 GuiControl.Hwnd 代替)
+Label
+LastFoundExist
Gui GuiName: Default
对 +/-Background 的解释和支持更加一致. 所有支持 "Gui Color" 的控件现在都支持 +BackgroundColor
和 +BackgroundDefault
(-Background
相同), 而不仅仅是 ListView/TreeView/StatusBar/Progress.
当使用 xp
/yp
或 xp+0
/yp+0
时, Gui.Add 默认为 y+m
/x+m
, 而不是 yp
/xp
. 换句话说, 控件被放置在前一个控件的下面/右边, 而不是在完全相同的位置. 如果使用非零偏移, 行为与 v1 相同. 要使用完全相同的位置, 请同时指定 xp yp
.
x+m
和 y+m
后面可以跟一个额外的偏移量, 如 x+m+10
(x+m10
也是有效的, 但可读性差).
Choose
不再是指定 MonthCal 值的一个多余的(无文档) 方式. 就像以前一样, 使用 Text 参数.
GuiControlGet
GuiControlGet 的空子命令有两种模式: 默认模式和文本模式, 其中第四个参数是单词 Text
. 如果控件类型没有单一的 "value", GuiControlGet 默认为返回 GetWindowText 的结果(不一定是可见文本). 有些控件没有可见文本, 或者不支持检索它, 所以完全忽略了第四个参数. 相比之下, GuiControl.Text 会返回显示文本, 隐藏文本(与 ControlGetText 返回的文本相同) 或者什么都没有.
下表显示了 GuiControlGet 的每种模式和控件类型的最接近的等价属性或函数.
控件默认文本注意
ActiveX.Value.Text文本处于隐藏状态. 见下文.
Button.Text
CheckBox.Value.Text
ComboBox.TextControlGetText()如果使用了 AltSubmit, 请使用 Value 而不是 Text(但如果 Text 与列表项目不匹配,则 Value 返回 0). Text 执行大小写更正, 而 ControlGetText 返回 Edit 区域的内容.
Custom.Text
DateTime.Value
DDL.Text如果使用了 AltSubmit, 请使用 Value 而不是 Text.
Edit.Value
GroupBox.Text
Hotkey.Value
Link.Text
ListBox.TextControlGetText()如果使用了 AltSubmit, 请使用 Value 而不是 Text. Text 返回所选项目的文本, 而 ControlGetText 返回隐藏文本. 见下文.
ListView.Text文本处于隐藏状态.
MonthCal.Value
Picture.Value
Progress.Value
Radio.Value.Text
Slider.Value
StatusBar.Text
Tab.TextControlGetText()如果使用了 AltSubmit, 请使用 Value 而不是 Text. Text 返回所选选项卡的文本, 而 ControlGetText 返回隐藏文本.
Text.Text
TreeView.Text文本处于隐藏状态.
UpDown.Value
ListBox: 对于多选 ListBox, Text 和 Value 返回数组, 而不是管道分隔的列表.
ActiveX: GuiControl.Value 每次都会返回相同的对象, 而 GuiControlGet 每次都会创建一个新的封装对象. 因此, 为了保持 ComObjConnect 连接处于活动状态, 不再需要保留对 ActiveX 对象的引用.
其他子命令
Pos → GuiControl.GetPos()
Focus → Gui.FocusedCtrl; 返回一个 GuiControl 对象而不是 ClassNN.
FocusV → GuiObj.FocusedCtrl.Name
Hwnd → GuiControl.Hwnd; 返回一个纯整数, 而不是十六进制的字符串.
Enabled/Visible/Name → 同名的 GuiCtrl 属性.
GuiControl
(空) 和 Text 子命令
下表显示了 GuiControl 的每种模式和控件类型的最接近的等效属性或方法.
控件(Blank)Text注意
ActiveXN/A命令没有效果.
Button.Text
CheckBox.Value.Text
ComboBox.Delete/Add/Choose.Text
Custom.Text
DateTime.Value.SetFormat()
DDL.Delete/Add/Choose
Edit.Value
GroupBox.Text
Hotkey.Value
Link.Text
ListBox.Delete/Add/Choose
ListViewN/A命令没有效果.
MonthCal.Value
Picture.Value
Progress.Value使用 +=
运算符代替 +
前缀.
Radio.Value.Text
Slider.Value使用 +=
运算符代替 +
前缀.
StatusBar.Text 或 SB.SetText()
Tab.Delete/Add/Choose
Text.Text
TreeViewN/A命令没有效果.
UpDown.Value使用 +=
运算符代替 +
前缀.
其他子命令
Move → GuiControl.Move(x, y, w, h)
MoveDraw → GuiControl.Move(x, y, w, h), GuiControl.Redraw()
Focus → GuiControl.Focus(), 现在使用 WM_NEXTDLGCTL 而不是 SetFocus, 因此聚焦 Button 可以暂时将其设置为默认值, 这与制表时的控件一致.
Enable/Disable → GuiControl.Enabled
Hide/Show → GuiControl.Visible
Choose → GuiControl.Choose(n), 其中 n 为纯整数. 不支持 |n
或 ||n
模式(如果需要, 使用 ControlChooseIndex 代替).
ChooseString → GuiControl.Choose(s), 其中 s 不是一个纯整数. 不支持 |n
或 ||n
模式(如果需要, 使用 ControlChooseString 代替). 如果字符串与多选列表框中的多个项目匹配, 这个方法将全部选择, 而不是只选择第一个.
Font → GuiControl.SetFont()
+/-Option → GuiControl.Opt("+/-Option")
Progress Gui 控件不再具有默认的 PBS_SMOOTH 样式, 因此它们现在是根据系统的视觉样式来设计的.
当 DPI 大于 100 % 时, 默认的边距和控件尺寸(尤其是 Button 控件) 可能与 v1 版略有不同.
当图片控件无法通过 GuiCtrl.Value := "new image.png"
设置新图片时, 不再删除当前图片. 但是, 允许通过 GuiCtrl.Value := ""
删除当前图像.
现在可以省略 ListView.InsertCol() 的 ColumnNumber 参数, 这与指定比控件中当前列数更大的列数具有相同的效果.
在退出脚本之前, OnError 现在被调用来处理关键性的错误. 尽管脚本可能不处于安全的执行状态, 但仍会进行尝试, 这与 OnExit 一致.
运行时错误不再将 Exception.What
设置为当前正在运行的用户定义的函数或子函数(但在调用 Error()
时仍会这样做, 但没有第二个参数). 这给了 What
一个更明确的目的: 函数名称表示该函数的失败(而不是调用该函数或计算其参数的失败). 对于表达式计算和控制流错误, What
是空白的(其他一些也可能是空白).
由运行时错误抛出的异常对象现在可以被识别为新的 Error 类或更具体的子类的实例. Error 对象有一个 Stack 属性, 包含一个堆栈跟踪. 如果 What 参数指定了一个正在运行的函数的名称, 那么现在会根据哪一行调用该函数来设置 File 和 Line .
Try-catch 语法已经改变, 允许脚本捕捉特定的错误类, 而不捕捉其他错误. 有关详情, 请参阅下文的 Catch 章节.
可继续错误(不中断脚本运行)
在大多数情况下, 错误对话框现在提供了继续当前线程的选项(而不是退出线程). COM 错误现在在选择不继续时退出线程(而不是退出整个脚本).
脚本不应依赖于此. 如果错误是由一个内置函数引发的, 继续会导致它返回 "". 如果错误是由表达式计算器引发的(比如无效的动态引用或除以 0), 表达式会被中止, 并返回 ""(如果用作控制流语句的参数).
在某些情况下, 代码不支持继续, 继续的选项不应该被显示. 对于旨在终止脚本的关键错误, 也不显示该选项.
OnError 回调现在接受第二个参数, 包含以下值之一:
Return: 返回 -1 将继续执行线程, 而 0 和 1 则和以前一样.
Exit: 不支持继续执行. 返回非零将停止进一步的处理, 但仍然退出线程.
ExitApp: 这是一个关键错误. 返回非零值会停止进一步的处理, 但脚本仍然被终止.
ErrorLevel
ErrorLevel 已经被删除. 脚本经常(也许通常) 是在没有错误检查的情况下编写的, 所以为错误设置 ErrorLevel 的策略经常让它们不被检测到. 即时的错误信息可能看起来有点对抗性, 但通常更有帮助.
在以前设置 ErrorLevel 以指示错误情况的地方, 会抛出异常, 并有一个(通常) 更有用的错误信息.
诸如 "Process Exist" 之类的命令使用它来返回一个值, 现在只是返回这个值(例如 pid := ProcessExist()
) 或更有用的东西(例如 hwnd := GroupActivate(group)
).
在某些情况下, ErrorLevel 被用于辅助返回值.
使用 U 选项的 Sort 不再返回删除的重复数.
Input 命令将被删除. 它被 InputHook 所取代. 几行代码可以做一个简单的替换, 返回一个包含结果的 InputHook 对象, 而不是使用 ErrorLevel 和一个 OutputVar.
InputBox 返回一个带有 Result(OK, Cancel 或 Timeout) 和 Value 属性的对象.
以前在 ErrorLevel 中存储失败次数的文件函数现在在抛出的异常对象的 Extra 属性中抛出它.
SendMessage 超时通常是一种异常情况, 所以会导致抛出 TimeoutError
. TargetError 和 OSError 可能会在其他条件下被抛出.
Run 和 Hotkey 函数的 UseErrorLevel
模式被移除. 这种模式早于 Try/Catch 添加到语言中. 菜单和 Gui 也有这种模式, 但被替换为对象(不使用 ErrorLevel).
与 v1 相比, 更多的语法错误会引发加载时错误, 如:
空括号(与函数名相邻的除外); 例如 x ()
前缀运算符使用错误或缺少操作数; 例如 x!
少于两个操作数的二元运算符.
少于三个操作数的三元运算符.
赋值的目标不是一个可写的变量或属性.
当发生以下任何故障时, 会抛出异常(而不是忽略该故障或产生一个空字符串):
试图对一个非数字值进行数学运算. (数字字符串是可以的.)
除以 0 或其他无效/不支持的输入, 如 (-1)**1.5
. 注意, 有些情况会被新检测为无效, 如 0**0
和 a<<b
或 a>>b
, 其中 b 的范围不在 0..63.
未能为内置函数的返回值, 串联或表达式的结果分配内存.
堆栈下溢(通常由语法错误引起).
试图向不是变量(或数组元素) 的东西赋值.
试图向一个只读变量赋值.
试图用一个空的名称进行双重解引, 如 fn(%empty%)
.
未能执行动态函数调用或方法调用.
一个方法/属性调用失败, 因为该值没有实现该方法/属性. (对于 v1 中的关联数组, 只有方法调用可以导致这种情况.)
由于内存分配失败而导致对象分配失败.
上面的一些条件在 v1 中被检测到, 但在表达式中间没有被检测到; 例如, A_AhkPath := x
在 v1 中检测到, 但在 v2 中仅在 y := x, A_AhkPath := x
检测到.
独立使用运算符 +=
, -=
, --
和 ++
不再将空变量视为 0. 这与 v1 不同, 在 v1 中, 独立使用运算符时将空变量视为 0, 但在表达式中间或与多语句逗号一起使用时则不会.
函数在失败时通常会抛出异常. 特别是:
由于 DllCall, RegExMatch 和 RegExReplace 的不正确使用导致的错误由于其复杂性而相当常见, 而且(像许多错误一样) 如果立即显示错误信息, 则更容易发现和调试.
如果数学函数的任何输入不是数字, 或者操作无效(如除以 0), 则抛出异常.
带有 WinTitle 参数的函数(有例外, 如 WinClose 的 ahk_group 模式), 如果没有找到目标窗口或控件就会抛出.
对一些以前没有检测到的错误抛出了异常, 一些被错误地标记为错误的情况(以前是通过设置 ErrorLevel) 被修复.
某些 error 消息已经发生变化.
Catch
Catch 的语法已经更改, 以提供一种方法来捕获特定的错误类, 而不捕获其他的错误(将控制权转移到调用堆栈更上层的另一个 Catch, 或报告错误并退出线程). 以前这需要捕捉所有类型的抛出值, 然后检查类型并重新抛出. 例如:
; 旧的(使用废弃的 v2.0-a 规则进行演示, 因为 v1 没有 `is` 或 Error 类)
SendMessage msg,,, "Control1", "The Window"
catch err
if err is TimeoutError
MsgBox "The Window is unresponsive"
throw err
SendMessage msg,,, "Control1", "The Window"
catch TimeoutError
MsgBox "The Window is unresponsive"
catch
捕获一个错误实例.
catch as err
捕捉一个 Error 实例, 它被分配给 err.
catch ValueError as err
捕捉一个 ValueError 实例, 它被分配给 err.
catch ValueError, TypeError
捕捉任一类型错误.
catch ValueError, TypeError as err
捕获任一类型错误并将实例分配给 err.
catch Any
捕捉 anything.
catch (MyError as err)
允许使用括号, 就像大多数其他控制流语句一样.
如果使用 Try 而不使用 Finally 或 Catch 它的行为就像有一个空块的 catch 虽然这听起来像 v1, 但现在 catch 本身只抓取 Error 的实例. 在大多数情况下, Try 本身就是为了抑制一个 Error, 所以不需要做任何改变. 然而, v2 中直接等价于 v1 的 try something()
的代码如下所示:
try something()
catch Any
优先考虑错误类型而不是输出变量名称可能会鼓励更好的代码; 按照预期处理预期的错误, 而不是压制或错误地处理本应报告的意外错误.
由于所有类型的值都可以被抛出, 任何类对过滤器来说都是有效的(例如 String
或 Map
). 然而, 类的原型在加载时被解析, 必须被指定为一个完整的类名, 而不是一个任意的表达式(类似于 class x extends y
中的 y
).
当 Catch 语句正在执行时, throw
(没有参数) 可以用来重新抛出异常(避免了为此目的指定一个输出变量的需要). 这甚至在嵌套的 Try-Finally 中也被支持, 但在嵌套的 Try-Catch 中不支持. throw
不需要被 Catch 语句的主体所包含; 它可以被一个被调用的函数所使用.
在最后一个 Catch 之后可以有一个 Else; 如果在 Try 中没有抛出异常, 就执行它.
键盘, 鼠标, 热键和热字串
更少的 VK 到 SC 和 SC 到 VK 的映射是硬编码的, 在理论上提高了与非常规的自定义键盘布局的兼容性.
删除了 "Return" 和 "Break" 键的名称. 使用 "Enter" 和 "Pause" 代替.
现在总是通过从键盘布局 DLL 读取 KLLF_ALTGR 标志来检测每个键盘布局上是否存在 AltGr. (v1.1.28+ 版本已经使用了这种方法.) 通过键盘钩子检测 AltGr 的后备方法已经被删除.
鼠标滚轮热键将 A_EventInfo 设置为由鼠标驱动程序报告的滚轮延迟, 而不是除以 120. 一般来说, 它是 120 的倍数, 但一些鼠标硬件/驱动程序可能会以更高的分辨率报告滚轮运动.
热串现在将 Shift+Backspace 视为 Backspace, 而不是在热串缓冲内将其转录为 `b
.
热字串使用第一对冒号(::
) 作为分隔符, 而不是在出现多对冒号时使用最后一对. 换句话说, 在 v2 中, 冒号(与另一个冒号相邻时) 必须在触发文本中转义, 而在 v1 中, 它们必须在替换中转义. 请注意, 对于奇数的连续冒号, 以前的行为不认为最后的冒号是一对冒号的一部分. 例如, 对于 ::1:::2
(1
→ :2
) 的行为没有变化, 但 ::3::::4
现在是 3
→ ::4
而不是 3::
→ 4
.
热字串不再成对转义冒号, 这意味着现在可以在热串触发器的末尾转义一个冒号. 例如, ::5`:::6
现在是 5:
→ 6
而不是一个错误, 而 ::7`::::8
现在是 7:
→ :8
而不是 7::
→ 8
. 在这些情况下, 最好转义每个原义的冒号, 以避免混淆(但单个孤立的冒号不需要转义).
带有延续片段的热字串现在默认为文本模式而不是原始模式.
热键现在只在 Win/Alt 键在逻辑上是向下的并且热键需要 Win/Alt 键(带 #
/!
或自定义前缀) 的情况下才会在释放时屏蔽. 也就是说, 不需要 Win/Alt 键的热键在 Win/Alt 键物理上处于关闭状态时不再掩盖 Win/Alt 向上. 这使得发送 {Blind}{LWin up}
的热键可以激活开始菜单(如果使用 AppsKey::RWin
这样的重映射键, 这已经是可能的).
已放弃对 Windows 2000 和 Windows XP 的支持.
AutoHotkey 不再在启动时覆盖系统的 ForegroundLockTimeout
设置.
这是通过调用带有 SPI_SETFOREGROUNDLOCKTIMEOUT
的 SystemParametersInfo
动作实现的, 它影响到当前用户会话的所有应用程序. 它在注销后不会持续存在, 但对一些用户来说仍是不受欢迎的.
用户的错误报告(和常识) 表明, 如果它起作用, 它允许焦点被那些没有专门设计的程序窃取.
在 Windows 10 上的一些测试表明, 它对任何事情都没有影响; 对 SetForegroundWindow
的调用总是失败的, 而 WinActivate 采用的其他变通方法是需要的, 并且无论超时与否都是有效的. SPI_GETFOREGROUNDLOCKTIMEOUT
是从一个单独的进程中使用的, 以验证该变化是否生效(它有时并不生效).
它可以很容易地在脚本中被复制:
DllCall("SystemParametersInfo", "int", 0x2001, "int", 0, "ptr", 0, "int", 2)
RegEx 换行匹配默认为 (*ANYCRLF) 和 (*BSR_ANYCRLF); `r 和 `n 被识别, 除了 `r`n 之外. `a 选项隐含地启用了 (*BSR_UNICODE).
正则调出现在可以是可变的. 通过 pcre_callout
变量指定的调出可以是任何可调用的对象, 或 pcre_callout
本身可以直接定义为函数(可能是嵌套函数). 随着函数和变量命名空间的合并, 诸如 (?C:fn)
这样的调出模式也可以指代包含函数对象的局部或全局变量, 而不仅仅是用户定义的函数.
从 stdin 读取的脚本(例如用 AutoHotkey.exe *
) 不再包括 A_ScriptFullPath 中的初始工作目录或主窗口的标题, 但它被用作 A_ScriptDir 和定位本地 Lib 文件夹.
由自动执行线程改变的设置现在会立即成为默认设置(对于在此后启动的线程), 而不是在 100 ms 后, 当自动执行线程结束时再变成默认设置.
通过利用动态分配, 以下限制已被取消:
行或延续片段最大长度为 16383 个字符.
每个表达式最大 512 个标记(MAX_TOKENS).
基于 MAX_TOKENS 确定大小的表达式计算器的内部数组现在是基于预先计算的所需大小的估计值, 因此性能应该是相似的, 但在大多数情况下堆栈的使用量会低一些. 这可能会增加用户定义的函数的最大递归深度.
每个参数最多可以引用 512 个 var 或函数(但无论如何, MAX_TOKENS 对表达式的限制更大).
每个函数最多可以调用 255 个指定的参数值(但无论如何 MAX_TOKENS 更有限制性).
ListVars 现在将静态变量与局部变量分开显示. 在函数中声明的全局变量也被列为静态变量(这是新的实现细节的副作用, 但被保留下来, 因为它在有许多全局变量的脚本中可能是有用的).
为了减少代码大小和维护成本, 删除了(未记录的) "lazy var". 这个优化改进了有超过 100,000 个变量的脚本的性能.
托盘菜单: 从 "Reload This Script" 和 "Edit This Script" 中删除了 "This", 以便与 "Pause Script" 和主窗口的菜单选项一致.
如果时间戳长度不是 4 到 14(包括) 之间的偶数, YYYYMMDDHH24MISS 时间戳值现在被认为是无效的.
当至少满足以下条件之一时, 脚本 "持续运行":
至少有一个热键或热字符串被脚本定义.
至少有一个 Gui(或脚本的主窗口) 可见.
至少有一个脚本的定时器目前是启用的.
至少有一个 OnClipboardChange 的回调函数已经被设置.
至少有一个 InputHook 是激活的.
调用了 Persistent()
或 Persistent(true)
并且没有通过调用 Persistent(false)
来反转.
如果出现以下情况之一, 并且没有满足以上条件, 那么脚本就会终止.
最后一个脚本线程结束了.
Gui 被关闭或销毁.
脚本的主窗口被关闭(但销毁它将导致脚本退出, 而不考虑持续运行, 如前所述).
一个没有 OnEnd 回调的 InputHook 结束.
为了灵活起见, OnMessage 并不能使脚本自动持续运行.
相比之下, 当以下情况中至少有一个为真时, v1 脚本就会 "持续运行":
至少有一个热键或热字串被脚本定义.
Gui 或 OnMessage() 出现在脚本的任何地方.
键盘钩子或鼠标钩子已被安装.
Input 已经被调用.
#Persistent 已经被使用.
线程开始时的不间断超时为 17 ms, 而不是 15 ms. 15 太短了, 因为系统的 tick 计数是以 15 或 16 为最小单位更新的; 也就是说, 如果 tick 计数正好在错误的时刻更新, 线程就可能成为可中断的, 尽管几乎没有时间过去.
线程在开始时是不可中断的, 现在则保持这种状态, 直到至少执行了一行, 即使不可中断的超时时间首先到期(例如, 如果系统在线程开始后立即暂停进程, 以便将 CPU 时间给另一个进程).
#MaxThreads 和 #MaxThreadsPerHotkey 不再对任何第一行是下列函数之一的子程序设置异常: ExitApp, Pause, Edit, Reload, KeyHistory, ListLines, ListVars 或 ListHotkeys.
#NoEnv 是默认行为, 所以该指令本身已经被删除. 如果等效的内置变量不可用, 请使用 EnvGet 代替.
SendMode 默认为输入(Input) 而不是事件(Event).
标题匹配模式默认为 2 而不是 1.
删除了 SetBatchLines, 因此所有脚本都以全速运行(等同于 v1 中的 SetBatchLines -1).
工作目录默认为 A_ScriptDir. A_InitialWorkingDir 包含由启动 AutoHotkey 的进程设置的工作目录.
#SingleInstance 提示行为对所有脚本来说都是默认的; #SingleInstance 本身就会激活强制模式. #SingleInstance Prompt
也可以显式地使用, 以达到清晰的目的, 或者覆盖之前的指令.
CoordMode 默认为 Client(在 v1.1.05 版中加入), 而不是 Window.
脚本文件(但不包括 由 脚本读取的文件) 的默认编码现在是 UTF-8 而不是 ANSI(CP0). 和以前一样, 这可以通过 /CP 命令行开关来覆盖.
#MaxMem 被移除, 并且不再限制变量的容量.
当启动 AutoHotkey 程序文件(如 AutoHotkey32.exe 或 AutoHotkey64.exe) 而没有指定脚本文件, 它不再搜索用户的文档文件夹中默认的脚本文件.
AutoHotkey 不计划通过直接启动程序文件来使用, 除非使用便携式副本. 通常不应该运行程序文件, 而应该运行 .ahk 文件.
如果要创建特定程序文件的快捷方式, 可以在快捷方式的目标后面附加一个空格和脚本的路径(通常用引号括起来).
命令行参数不再存储在一个编号化的伪数组全局变量中; 应该使用全局变量 A_Args(在 v1.1.27 中添加) 来代替.
删除了 /R 和 /F 开关. 使用 /restart 和 /force 代替.
当 AutoHotkey.exe 被用来检查脚本的语法错误时, 应该使用 /validate 来代替 /iLib, 因为函数库的自动包含机制被移除.
在以下任一情况下, /ErrorStdOut 现在被视为脚本的参数之一, 而不是内置的: