# 热字串

## 目录

- 介绍和简单示例
- 终止符
- 选项
- 长替换
- 上下文相关的热字串
- 自动更正
- 备注
- 命名的函数热字串
- 热字串助手

## 介绍和简单示例

尽管热字串主要用于在您输入缩写时进行扩展(自动替换), 但是它们也可以用来启动任何脚本动作. 从这个角度看, 它们类似于热键, 除了它们通常由多个字符组成(即字符串).

要定义热字串, 请用两个双冒号包围用来触发的缩写, 例如:

    ::btw::by the way

在上面的例子中, 每当您输入 btw 时, 缩写 btw 会被自动替换为 "by the way"(不过, 默认情况下, 您必须在输入 btw 后输入终止符, 如 `Space`, `.` 或 `Enter`).

上面的 "by the way" 示例被称为自动替换热字串, 因为输入的文本被自动删除并替换为第二个双冒号后指定的字符串. 与之相比, 热字串还可以定义用来执行任何自定义动作, 如下例所示. 注意函数必须出现在热字串的 下面:

    ::btw::
    {
        MsgBox 'You typed "btw".'
    }

    :*:]d::  ; 此热串通过下面的函数用当前日期和时间替换 "]d".
    {
    SendInput FormatTime(, "M/d/yyyy h:mm tt")  ;  看起来会像 9/1/2005 3:53 PM 这样
    }

大括号的含义与热键中的相同.

尽管上面的两个例子不是自动替换热字串, 但默认情况下您输入的缩写也会被删除. 这是通过自动退格来实现的, 此特性可以通过 b0 选项来禁用.

## 终止符

除非使用了星号选项, 否则您必须在热字串的缩写后输入一个 终止符 才能触发它. 终止符最初由以下字符组成: -()[]{}':;"/\,.?!`n `t(注意 `n 是 `Enter`, `t 是 `Tab`, 且在它们之间还有一个普通的空格). 这个字符集可以通过编辑下列的示例进行更改, 该示例为 所有 热字串设置新的终止符, 而不仅是在它下面的那些:

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

终止符也可以在脚本运行时通过调用 Hotstring 函数来进行更改, 如下例所示:

    Hotstring("EndChars", "-()[]{}:;")

## 选项

热字串的默认行为可以使用下面的两种方式来改变:

1. #Hotstring 指令, 它会影响脚本中在它后面的所有热字串. 下列示例会让 C 和 R 选项生效: `#Hotstring c r`.
2. 把选项放在热字串的第一个双冒号之间. 下列示例会让 C 和 * 选项(区分大小写且 "不需要终止符") 对当前热字串生效: `:c*:j@::john@somedomain.com`.

下面列表对每个选项进行说明. 当使用上面的方法指定多个选项时, 可以在选项间包含空格.

* (星号): 不需要终止符(例如 `Space`, `.` 或 `Enter`) 来触发热字串. 例如:

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

上面的示例会在您输入 @ 字符时立即进行替换. 当使用 #Hotstring 指令时, 可以使用 *0 来关闭此选项.

? (问号): 即使热字串在另一个单词中也会被触发; 也就是说, 在它之前输入的字符是字母数字时. 例如, 如果 `:?:al::airline` 是热字串, 输入 "practical " 会产生 "practicairline ". 使用 ?0 来关闭此选项.

B0 (B 后跟着零): 不 自动退格来删除您输入的缩写. 关闭此选项后可以使用 B 来启用. 脚本还可以通过 {bs 5} 实现自己的退格, 这里发送 5 次 `Backspace`. 类似的, 可以通过 {left 5} 发送 `←` 键击. 例如, 下面的热字串产生 "<em></em>" 并把光标向左移动 5 个位置(这样光标就在标签之间了):

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

C: 区分大小写: 当您输入缩写时, 它必须准确匹配脚本中定义的大小写形式. 使用 C0 可以关闭区分大小写的特性.

C1: 不遵循输入的大小写形式. 使用此选项可以让自动替换热字串不区分大小写且阻止它们遵循您实际输入字符的大小写形式. 遵循大小写形式的热字串(这是默认状态) 会在您输入的缩写都为大写时产生大写形式的的替换文本. 如果您的输入的首字母为大写, 那么替换的首字母也会为标题格式(大写, 如果首个字符是字母). 您按其他任何大小写形式输入时, 替换会准确按照定义进行发送. 如果在 #Hotstring 指令中含有此选项, 那么可以使用 C0 来关闭它, 这样可以让热字串重新遵循大小写.

Kn: 按键延迟: 这个较少使用的选项设置在自动退格或自动替换产生的键击之间的延迟. 通过 n 指定新的延迟; 例如, 指定 k10 来设置 10 ms 的延迟, 而 k-1 则取消延迟. 此选项的实际效果取决于当前生效的发送模式:

- SI (SendInput): 由于此模式是没有延迟的, 所以按键延迟会被忽略. 例外是当 SendInput 不可用时, 此时热字串会恢复到下面的 SendPlay 模式(它会遵循按键延迟).
- SP (SendPlay): 默认延迟为零, 这对于 SendPlay 相当于 -1(没有延迟). 此模式中, 这个延迟实际是按住时长, 而不是键击之间的延迟.
- SE (SendEvent): 默认延迟为零. 在大多情况下建议使用零的延迟, 因为这样快速且与其他进程配合比较好(由于会内部执行 Sleep 0). 指定 k-1 则不使用延迟, 这样可以在您 CPU 经常高负荷运行时让自动替换更快速地进行. 设置为 -1 时, 脚本的进程优先级会成为键击发送速度的重要因素. 要提升脚本的优先级, 请使用 `ProcessSetPriority "High"`.

O: 进行替换时忽略自动替换热字串的终止符. 它可以用于当您希望使用终止符让热字串保持清晰, 却不希望终止符显示在屏幕上的时候. 例如, 如果 `:o:ar::aristocrat` 为热字串, 那么输入 "ar" 后跟着空格键会产生不含尾随空格的 "aristocrat", 这样可以让您不需要按住 `Backspace` 的情况下补上单词的复数或所有格形式. 使用 O0(字母 O 后跟着零)) 来关闭此选项.

Pn: 字符串的优先级(例如 P1). 这个较少使用的选项对自动替换热字串没有效果.

R: 发送替换文本的原始文本; 即, 不把 {Enter} 转换成 `Enter`, ^c 转换成 `Ctrl`+`C`, 等等. 使用 R0 来关闭此选项, 或用 T 来覆盖.

注意: Text 文本模式可能更可靠. R 选项和 T 选项是互相排斥的.

S 或 S0: 指定字母 S 使热字串免于挂起. 指定 S0(S 与数字 0) 来移除豁免, 允许热字串被挂起. 当作为默认选项应用时, `S` 或 `#SuspendExempt` 将使热字串豁免; 也就是说, 要覆盖该指令, 必须在热字串中显式使用 `S0`.

SI, SP 或 SE: 设置自动替换热字串发送键击的方法. 这些选项是互相排斥的: 每次只有一个生效. 下面对每个选项进行说明:

- SI 代表 SendInput, 它通常比其他模式拥有较好的速度和可靠性. 另一个好处是和下面的 SendPlay 一样, SendInput 会在热字串 自动替换文本时延迟您输入的内容. 这样避免了您的键击穿插到替换的内容中. 当 SendInput 不可用时, 热字串会自动使用 SendPlay.
- SP 代表 SendPlay, 它可以让热字串在更大范围的游戏中运行.
- SE 代表 SendEvent.

如果未使用上面的任何一个选项, 则默认为 SendInput. 然而, 与 SI 选项不同的是, 在 SendInput 不可用时会使用 SendEvent 而不是 SendPlay.

T: 使用文本模式 发送替换文本. 也就是说, 按字符代码发送每个字符, 不转换 {Enter} 为 `Enter`, ^c 为 `Ctrl`+`C`, 等等. 不需要将每个字符转换为击键. 对于具有延续片段的热字符串, 此选项将自动生效. 使用 T0 或 R0 来关闭此选项, 或使用 R 来覆盖.

X: 执行. 取代替换文本, 热字串接受一个函数调用或表达式来执行. 例如, `:X:~mb::MsgBox` 会在用户输入 "~mb"时显示一个消息框, 而不是用 "MsgBox" 自动替换. 这在定义大量调用函数的热字符串时最有用, 否则每个热字串都需要三行.

当与热字串函数一起使用时, X 选项会把 Replacement 参数解释为函数名, 而不是替换文本. 但是, 只有在每次调用函数时指定 X 选项时才会有这种效果.

Z: 这个较少使用的选项会在每次热字串触发后重置热字串识别器. 换句话说, 脚本将开始等待一个全新的热字符串, 从而不考虑您之前键入的任何内容. 这可以防止触发不必要的热字串. 要说明这一点, 请参考以下热字串:

    :b0*?:11::
    {
        SendInput "xx"
    }

由于上面没有使用 Z 选项, 所以输入 111(三个连续的 1) 会触发热字串两次, 因为中间的 1 既是首次触发的 末尾 字符, 又是第二次触发的 起始 字符. 在 b0 前面加上字母 Z 后, 您必须输入四个 1 而不是三个才能触发热键两次. 使用 Z0 来关闭此选项.

## 长替换

通过使用延续片段的方法可以让产生大量替换文本的热字串更具有可读性和可维护性. 例如:

    ::text1::
    (
    顶部和底部括号之间的任何文本都按原义处理.
    默认情况下, 前一行和这一行之间的硬回车(Enter) 也会被保留下来.
        默认情况下, 这一行左边的缩进(tab) 被保留.
    )

有关如何更改这些默认行为的信息, 请参阅延续片段. 延续片段的存在也会使热字串默认为文本模式. 覆盖此特性的唯一方法是在每个具有延续片段的热字串中指定相反的选项(例如 `:t0:text1::` 或 `:r:text2::`).

## 上下文相关的热字串

使用 #HotIf 指令可以让选择的热字串产生上下文相关性. 这样的热字符串根据任意条件(比如活动窗口的类型) 来发送不同的替换, 执行不同的操作, 或者什么都不做. 例如:

    #HotIf WinActive("ahk_class Notepad")
    ::btw::This replacement text will appear only in Notepad.
    #HotIf
    ::btw::This replacement text appears in windows other than Notepad.

## 自动更正

下面的脚本使用热字串即时更正大约 4700 个常见的英文拼写错误. 它还包含了 `Win`+`H` 热键来方便地添加更多拼写错误:

下载: AutoCorrect.ahk (127 KB)

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

## 备注

目前不支持替换文本中使用表达式. 要解决此问题, 请不要让这样的热字串自动替换. 而是在缩写的下面使用 SendInput 函数, 后跟着仅包含单词 Return 的行.

要在替换文本后发送额外的空格或 tab, 可以把它们加在替换文本后, 但需要在末尾加上重音符/反引号(`). 例如:

    :*:btw::By the way `

对于一个不使用 Text 或 Raw 模式的自动替换热字符串, 单独发送 `{`, 或者只在前面加空格, 需要用一对大括号括起来, 例如 `:*:brace::{{}` 和 `:*:space_brace:: {{}`. 否则它将被解释为热字串函数的左大括号, 以支持 OTB(One True Brace) 样式.

默认情况下, 鼠标左键或右键的任何点击都会重置热字串识别器. 换句话说, 脚本将开始等待全新的热字串, 而不考虑您之前输入的任何内容(如果您不希望这样, 请在脚本的任意位置指定一行 `#Hotstring NoMouse`). "鼠标点击时重置" 的行为是默认的, 因为每次点击通常会移动插入点(光标) 或设置键盘焦点到新的控件/区域. 在这种情况下, 通常希望: 1) 即使没有问号选项也触发热键; 2) 防止您在点击鼠标后输入的一些内容与之前输入的内容意外形成有效的缩写从而触发热字串.

每次输入字符时, 热字串识别器会检查当前活动窗口, 并且如果活动窗口不同于之前, 则会重置. 如果活动窗口发生变化, 但在键入任何字符之前返回, 则不会检测到更改(但可能会由于其他原因重置热字串识别器). 热字串识别器也可以通过调用 `Hotstring "Reset"` 来重置.

内置变量 A_EndChar 包含了触发最近的非自动替换热字串时的终止符. 如果不需要终止符(使用了 * 选项), 那么它会被置空. 可以用于使用 Send 命令的热字串或根据您输入的不同终止符改变行为的那些热字串. 要发送终止符自身, 请使用 `SendText A_EndChar`(使用 SendText 是因为普通的 Send 函数无法正确发送类似 !{} 这样的字符).

虽然热字符串定义中的单冒号不需要转义, 除非它们位于双冒号分隔符之前, 但那些左边有空格或制表符的反引号和分号必须始终被转义. 有关完整列表, 请参阅转义序列.

尽管 Send 函数的特殊字符(如 {Enter}) 在自动替换文本中受到支持(除非使用 raw 选项), 但是热字串缩写本身并不使用此功能. 相反, 指定 `n 表示 `Enter` 键和 `t(或原义制表符) 表示 `Tab`(有关完整列表, 请参阅转义序列). 例如, 当您输入 "ab" 后跟着 tab 时, 会触发热字串 `:*:ab`t::`.

热字串会原义地处理在它的定义中的空格和 tab. 例如, 后面的热字串会产生两种不同的效果: `::btw::by the way` 和 `::btw:: by the way`.

每个热字串缩写的长度不能超过 40 个字符. 超出此长度后程序会向您发出警告. 相比之下, 当发送模式默认为 SendInput 时, 热字串的替换文本的长度限制在 5000 个字符左右. 通过切换到其他发送模式可以把此限制增加到 16,383 个字符. 此外, 在热字串的主体使用 `SendPlay MyVariable`, 可以发送不限数量的文本.

热字串的定义顺序决定了它们之间的优先级. 换句话说, 如果多个热字串匹配您输入的内容, 那么只有脚本中首先列出的那个会生效. 相关主题: 上下文相关的热字串.

为了识别热字串, 您输入的所有退格都会被考虑在内. 但是, 使用 `↑`, `→`, `↓`, `←`, `PgUp`, `PgDn`, `Home` 和 `End` 在编辑器中导航会重置热字串识别进程. 换句话说, 它将开始等待一个全新的热字串.

即使当前活动窗口忽略您的键击时也可以输入热字串. 换句话说, 即使触发的缩略词不可见时热字串仍会被触发. 此外, 您还可以使用 `Backspace` 键撤销最近输入的键击(尽管您无法看到效果).

只有在函数被命名的情况下, 脚本才能显式调用热字串的函数. 请参阅命名的热字串函数.

当输入被一个不可见的Input 钩子阻塞时, 热字串不受监控, 也不会被触发.

默认情况下, 由任何 AutoHotkey 脚本生成的键击永远不会触发热字串. 这避免了热字串彼此反复地触发而形成的无限循环的可能性. 此行为可以使用 #InputLevel 和 SendLevel. 进行控制. 然而, 自动替换型热字串的发送级别总为 0, 因此永远不会触发钩子热键或热字串.

热字串可以通过 Hotstring 函数动态创建, 它还可以单独修改, 禁用, 或启用脚本的现有的热字串.

在某些时候 InputHook 函数比热字串更灵活. 例如, 它可以对活动窗口(例如游戏) 隐藏您的键击. 它还支持非字符型的终止键, 如 `Esc`.

任何包含热字串的脚本会自动使用键盘钩子.

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

- 它们都受 Suspend 函数影响.
- 它们都遵循 #MaxThreads 和 #MaxThreadsPerHotkey 的设置(但不遵循 #MaxThreadsBuffer).
- 包含热字串的脚本会自动变为持续运行的.
- 非自动替换热字串在运行时会创建新的线程. 此外, 它们会更新内置热键变量(如 A_ThisHotkey).

已知限制: 在某些系统的 Java 应用程序中, 热字串可能会干扰用户输入变音符字母(通过 dead 键). 为了解决此问题, 可以临时打开 Suspend(这样禁用了所有热字串).

## 命名的函数热字串

如果需要在不触发热字串本身的情况下调用热字串的函数, 可以通过简单地在热键的双冒号后定义一个或多个热键来指定一个命名的函数, 如此例所示:

    ; 此示例还演示了在脚本中实现大小写一致性的一种方法.
    :C:BTW::  ; 输入所有大写字母.
    :C:Btw::  ; 只有第一个字母输入大写字母.
    : :btw::  ; 输入任何其他组合.
        case_conform_btw(hs) ; hs 将保存触发该函数的热字符串的名称.
        {
            if (hs == ":C:BTW")
                Send "BY THE WAY"
            else if (hs == ":C:Btw")
                Send "By the way"
            else
                Send "by the way"
        }

如果函数 case_conform_btw 被脚本显式调用, 第一个参数(hs) 必须传递一个值.

有关其他细节, 请参阅函数热键.

Hotstring 函数也可以关联函数或函数对象到一个热字串.

## 热字串助手

看看 Hotstring 函数页面的示例部分中的第一个示例, 如果您是深度的热字串用户, 那么它会很有用. 通过按下 `Win`+`H`(或您选择的其他热键), 可以把当前选择的文本转变成热字串. 例如, 如果您在文字处理软件中选择了 "by the way", 按下 `Win`+`H` 会提示您输入其缩写(例如 btw), 添加新热字串到脚本中并激活它.

dftg