# Hotstring() [v1.1.28+]

在脚本运行时创建, 修改, 启用或禁用热字串.

    Hotstring(String , Replacement, OnOffToggle)
    Hotstring(NewOptions)
    OldValue := Hotstring("EndChars" , NewValue)
    OldValue := Hotstring("MouseReset" , NewValue)
    Hotstring("Reset")

## 参数

String

  热字串的触发字符串, 前面是通常的冒号和选项字符. 例如, `"::btw"` 或 `":*:]d"`.

  String 可以通过考虑通过区分大小写(C), 单词敏感性(?), 激活条件(如 #If, #IfWin 或 Hotkey, If) 和触发字符串来匹配现有的热字符串. 例如, `"::btw"` 和 `"::BTW"` 只有在区分大小写模式作为默认值开启时才匹配, 而 `":C:btw"` 和 `":C:BTW"` 永远不匹配. `C` 和 `?` 选项可能包含在 String 中或者通过 #Hotstring 指令或之前对此函数的调用设为默认值.

  如果热字串已经存在, 那么在 String 中指定的所有选项都会生效, 而其他所有选项都保持原样. 但是, 由于带有 `C` 或 `?` 的热字串被认为是与其他热字串不一样的, 所以不可能添加或删除这些选项. 作为代替, 关闭现有热字串并创建一个新的.

  当热字串第一次被创建时 -- 无论是通过热字串函数还是脚本中的双冒号标签 -- 其触发字符串和选项字符序列都将成为热字串的固定名称, 如 A_ThisHotkey 中显示的名称. 即使热字串函数稍后使用不同的选项字符访问热字串, 这个名称也不会改变.

  如果 X (执行) 选项存在于 String 中(不只是设置为默认值), Replacement 参数将被解释为一个标签或函数名而不是替换文本. 如果 Replacement 是对象, 则没有效果.

Replacement

  当热字串触发时, 替换字符串或标签, 调用的函数或函数对象(作为新线程).

  默认情况下, 所有字符串都作为替换文本处理. 要按名称指定标签或函数, 请在 String 中包含 X (execute) 选项. 普通标签和热键/热字串标签都能使用, 并且不应该包含尾部冒号. 如果一个函数和一个标签具有相同的名称, 则该标签优先. 要使用函数代替时, 传递函数引用.

  如果热字串已经存在, 则该参数可以留空, 在这种情况下, 它的替换不会被改变. 这对于只更改热字串的选项, 或打开或关闭热字串它是有用的.

  注意: 如果指定了这个参数, 但是由于之前使用此函数而禁用了热字串, 那么热字串将继续禁用. 为了避免这种情况, 请在 OnOffToggle 中包含单词 `"On"`.

OnOffToggle

  以下字符串之一(如果使用原义, 用引号括起来):

  On: 启用热字串.

  Off: 禁用热字串.

  Toggle: 将热字串设为相反的状态(启用或禁用).

  [v1.1.30+]: 值 1(或 `true`), 0(或 `false`) 和 -1 可以分别用来代替 On, Off 和 Toggle.

## 错误处理

如果参数无效或内存分配失败, 此函数将抛出异常. 这不会影响 ErrorLevel.

如果省略了 Replacement 并且 String 有效但无法匹配到一个存在的热字串, 则也会抛出异常. 这可以用来测试热字串的存在. 例如:

    try
        Hotstring("::btw")
    catch
        MsgBox The hotstring does not exist or it has no variant for the current IfWin criteria.

## 备注

当前 IfWin 设置决定了哪一个热字串函数的变体将会运行.

一个给定的标签或函数可以是多个热字串的目标. 如果知道一个标签或函数被热字串调用, 您可以通过检查内置变量 A_ThisHotkey 来确定是哪个热字串.

如果该脚本被挂起, 新添加/启用的热字串也将挂起, 直到挂起关闭(除了在 Suspend 部分中描述的例外).

如果通过此函数所做的更改, 将安装或删除键盘和/或鼠标钩子.

此函数不能直接启用或禁用除其本身之外的脚本中的热字串.

一旦脚本至少有一个热字符串, 他将持续运行, 这意味着应该使用 ExitApp 而不是 Exit 来退出(终止) 脚本. 除非指定了 `#SingleInstance Off`, 否则热字串脚本也会自动执行 #SingleInstance.

## 变体(副本) 热字串

如果每个定义具有不同的 IfWin 条件, 区分大小写(`C` vs. `C0`/`C1`) 或单词敏感性(`?`), 则可以多次创建特定热点字符串. 这些被称为 热字串变体. 例如:

    Hotkey, IfWinActive, ahk_group CarForums
    Hotstring("::btw", "behind the wheel")
    Hotkey, IfWinActive, Inter-Office Chat
    Hotstring("::btw", "back to work")
    Hotkey, IfWinActive
    Hotstring("::btw", "by the way")

如果一个热字串的多个变体能被触发, 那么只有最早创建的将会触发.

有关 IfWin 的更多信息, 请参见 #IfWin 的一般说明.

## EndChars

    OldValue := Hotstring("EndChars" , NewValue)

获取或修改由热字串识别器用作终止符的字符集. 例如:

    prev_chars := Hotstring("EndChars", "-()[]{}':;""/\,.?!`n `t")
    MsgBox The previous value was: %prev_chars%

#Hotstring EndChars 也会影响这个设置.

目前不可能为每个热字串指定不同的终止符字符集.

## MouseReset

    OldValue := Hotstring("MouseReset" , NewValue)

获取或修改全局设置, 该设置控制鼠标单击是否重置热字串识别器, 如这里所描述的那样. NewValue 为 1(true), 以启用鼠标点击检测和重置热字串识别器, 或者 0(false) 来禁用. 返回值是在调用函数之前生效的设置.

如果通过此函数所做的更改, 将安装或删除鼠标钩子.

#Hotstring NoMouse 也会影响此设置, 等同于将 NewValue 指定为 `false`.

## Reset [v1.1.28.01+]

    Hotstring("Reset")

立即重置热字串识别器. 换句话说, 该脚本将开始等待一个全新热字串, 不再考虑之前键入的任何内容.

## 设置默认选项

    Hotstring(NewOptions)

要为随后创建的热字串设置新的默认选项, 请将选项传递给热字串函数, 而不使用任何前导或尾随冒号. 例如: `Hotstring("T")`.

启用大小写敏感(C) 或单词敏感性(?) 也会影响到任何后续的对热字串函数的调用将匹配哪些现有的热字串. 例如, 默认情况下, `Hotstring(":T:btw")` 将会匹配 `::BTW`, 但是如果 `Hotstring("C")` 或 `#Hotstring C` 生效时, 则不会. 这可以通过传递互斥的选项来撤销或覆盖; 例如, `C0` 和 `C1` 将覆盖 `C`.

## 相关

热字串, #IfWinActive/Exist, #MaxThreadsPerHotkey, Suspend, 线程, Thread, Critical

## 示例

热字串助手. 如果您是一个热字串重度用户, 下面的脚本可能会很有用. 它基于 Andreas Borutta 创建的脚本. 通过按下 `Win`+`H`(或您选择的其他热键), 可以将当前选定的文本转换为热字串. 例如, 如果您在文字处理软件中选择了 "by the way", 按下 `Win`+`H` 会提示您输入其缩写(例如 btw), 然后把新热字串添加到脚本中. 之后会重新载入脚本来激活热字串. 热字串将被激活而无需重新加载脚本.

    #h::  ; Win+H 热键
    ; 获取当前选择的文本. 使用剪贴板代替
    ; "ControlGet Selected" 是因为它可以工作于更大范围的编辑器
    ; (即文字处理软件).  保存剪贴板当前的内容
    ; 以便在后面恢复. 尽管这里只能处理纯文本,
    ; 但总比没有好:
    ClipboardOld := Clipboard
    Clipboard := "" ; 必须清空, 才能检测是否有效.
    Send ^c
    ClipWait 1
    if ErrorLevel  ; ClipWait 超时.
        return
    ; 替换 CRLF 和/或 LF 为 `n 以便用于 "发送原始模式的" 热字串:
    ; 对其他任何在原始模式下可能出现问题
    ; 的字符进行相同的处理:
    ClipContent := StrReplace(Clipboard, "``", "````")  ; 首先进行此替换以避免和后面的操作冲突.
    ClipContent := StrReplace(ClipContent, "`r`n", "``r")  ; 在 MS Word 等软件中中使用 `r 会比 `n 工作的更好.
    ClipContent := StrReplace(ClipContent, "`n", "``r")
    ClipContent := StrReplace(ClipContent, "`t", "``t")
    ClipContent := StrReplace(ClipContent, "`;", "```;")
    Clipboard := ClipboardOld  ; 恢复剪贴板之前的内容.
    ShowInputBox(":T:`::" ClipContent)
    return

    ShowInputBox(DefaultValue)
    {
        ; 这里会移动输入框的光标到更人性化的位置:
        SetTimer, MoveCaret, 10
        ; 显示输入框, 提供默认的热字串:
        InputBox, UserInput, New Hotstring,
        (
        Type your abreviation at the indicated insertion point. You can also edit the replacement text if you wish.

        Example entry: :R:btw`::by the way
        ),,,,,,,, %DefaultValue%
        if ErrorLevel  ; 用户选择了取消.
            return

        if RegExMatch(UserInput, "O)(?P<Label>:.*?:(?P<Abbreviation>.*?))::(?P<Replacement>.*)", Hotstring)
        {
            if !Hotstring.Abbreviation
                MsgText := "You didn't provide an abbreviation"
            else if !Hotstring.Replacement
                MsgText := "You didn't provide a replacement"
            else
            {
                Hotstring(Hotstring.Label, Hotstring.Replacement)  ; 现在激活热字串.
                FileAppend, `n%UserInput%, %A_ScriptFullPath%  ; 保存热字串以备以后使用.
            }
        }
        else
            MsgText := "The hotstring appears to be improperly formatted"

        if MsgText
        {
            MsgBox, 4,, %MsgText%. Would you like to try again?
            IfMsgBox, Yes
                ShowInputBox(DefaultValue)
        }
        return

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

dftg