如何实现类似 MacOS(EN Intl)的德语变音符号行为?

How to realize MacOS-like (EN Intl) german umlauts behavior?

我得到了一个新的 Windows 10 笔记本,而我 运行 一个 MBP 已经很久了。在 MacO 上,我使用 US Intl kezmap,我非常喜欢编写德语变音符号的快捷方式。

在 MacOS 上,我使用 {RAlt} + {u} 后跟 {a}、{o}、{u} 或 {s} 来编写相应的德语变音符号。要写大写变音符,我必须按 {Shift} + {a}、{o} 或 {u}。

我尝试编写一个 AHK 脚本来重现此行为,但不幸的是我没有成功。

我目前创建的是这个

;Umlaut
#Persistent

    RAlt & a::
        GetKeyState, state, Shift
        if state = U
        SendInput {ASC 0228}            ;RAlt+a = lower case a-umlaut
        else Send, {ASC 0196}           ;RAlt+Shift+a = UPPER CASE A-umlaut
    return

    RAlt & o:: 
        GetKeyState, state, Shift
        if state = U
        SendInput {ASC 0246}            ;RAlt+o = lower case o-umlaut
        else Send, {ASC 0214}           ;RAlt+Shift+o = UPPER CASE O-umlaut
    return

    RAlt & u:: 
        GetKeyState, state, Shift
        if state = U
        SendInput {ASC 0252}            ;RAlt+u = lower case u-umlaut
        else Send, {ASC 0220}           ;RAlt+Shift+u = UPPER CASE U-umlaut
    return

    RAlt & s:: Send, {ASC 0223}     ;RAlt+s = RAlt+s, Eszett
    return

它有效,但我真的想要上面描述的组合键。我怎样才能达到这个目标?

首先修复在原始 post 中看到的代码,它非常遗留并且使用了很多奇怪的方法。要列出并修复所有这些问题:

#Persistent 对我们没有任何作用。在这里没用。

RAlt & key:: 类型的热键标签应该使用修饰符,看起来像这样 >!key::
>! 修饰符表示正确的 alt.

遗留 GetKeyState command should be replaced by the GetKeyState() 函数的使用。
虽然,这实际上根本不需要。 shift 热键修饰符 + 应该像这样使用:

>!a::SendInput, ä
>!+a::SendInput, Ä
>!o::SendInput, ö
>!+o::SendInput, Ö
>!u::SendInput, ü
>!+u::SendInput, Ü
>!s::SendInput, ß

我也放弃了使用 ASC codes,因为我认为没有理由使用它们。
我想这会使脚本文件更灵活地保存在更原始的编码下,但是嗯。

所以您 post 中的代码是正确的。


现在要实现您实际想要做的事情:
RAlt + u 进入 变音输入模式

我能想到的最简单的方法就是使用 #If.
创建上下文相关的热键 通常我不建议在 AHK v1 中使用 #If,因为它有缺点(如文档中所述),但对于像这样的小脚本来说已经足够了。它使这一切变得更加简单和整洁。

所以首先让我们创建一个 RAlt + u 热键,将某个变量的状态设置为 true

>!u::UmlautTypingMode := true

Then we can create context sensitive hotkeys by always first checking the value of that variable:
>!u::UmlautTypingMode := true

#If, UmlautTypingMode ;start context sensitive hotkeys (if the variable value evaluates to true)
a::
    SendInput, ä
    UmlautTypingMode := false
return
+a::
    SendInput, Ä
    UmlautTypingMode := false
return
o::
    SendInput, ö
    UmlautTypingMode := false
return
+o::
    SendInput, Ö
    UmlautTypingMode := false
return
<!u::return
u::
    SendInput, ü
    UmlautTypingMode := false
return
+u::
    SendInput, Ü
    UmlautTypingMode := false
return
s::
    SendInput, ß
    UmlautTypingMode := false
return
#If ;end context sensitive hotkeys

如您所见,不幸的是,我们不得不摆脱那些甜美干净的单行热键,因为每次都是 false,并以 return.[=82= 结束代码执行] 当然这可以用一些更高级的 AHK 来压缩,但我会保持简单。
里面的小 <!u::return 行是为了让最初的 RAlt + u 按下不产生 ü.


应该就是这样。至少在我这边工作得很好。
不过,我现在才意识到 "{RAlt} + {u} 后跟 {a}、{o}、{u} 或 {s}" 你可能是说只要按住 RAlt,您就会一直输入变音符号。如果是这种情况,代码需要进行一些调整。
现在您按下 并释放 RAlt + u 以进入 变音输入模式 .


最后,作为一个奖励,这里是压缩到一行的代码。
我知道,这很愚蠢,我就是忍不住,我喜欢做这些哈哈。

>!u::UmlautTypingMode := true
#If, UmlautTypingMode
a::
+a::
o::
+o::
u::
+u::
s::SendInput, % ((A_ThisHotkey = "s"), UmlautTypingMode := false) ? "ß" : ("¨" ((A_ThisHotkey ~= "\+") ? Format("{:U}", SubStr(A_ThisHotkey, 0)) : SubStr(A_ThisHotkey, 0)))
>!u::return
#If

此外,不知道这是否适用于不同的键盘布局。
至少对我有用。


编辑:
请求的超时是评论。用 timer 做起来非常简单方便。 因此,我们将 >!u::UmlautTypingMode := true 热键更改为:

>!u::
    UmlautTypingMode := true
    SetTimer, Timeout, -2000
return

计时器周期中的负数表示它在 2000 毫秒后仅运行 一次

现在我们当然还必须创建名为 Timeout 的标签(或函数,我将在此处使用标签以使其更简单)(它不是内置的东西,我们可以'我在这里使用了任何名称)。

Timeout:
    UmlautTypingMode := false
return

这个标签可以放在例如脚本的底部。

我宁愿建议稍微不同的输入方法:输入字母,然后使用脚本替换光标左侧的最后一个字符。
当我使用德语文本进行了大量工作并且与您描述的方法相比更有效时,我已经这样做了。也可以通过将光标放在文本中并按相同的热键来替换文本中已有的字符。

这里是

dict := ComObjCreate("Scripting.Dictionary")
dict.Add("a", "ä")
dict.Add("A", "Ä")
dict.Add("o", "ö")
dict.Add("O", "Ö")
dict.Add("u", "ü")
dict.Add("U", "Ü")

>!u::
    temp :=  clipboard  ; backup clipboard
    send +{left}
    send ^{insert}
    sleep 100
    c :=  clipboard
    found := false
    for key in dict {
        if (key==c) {
            v := dict.item[key]
            found := true
            send %v%
        }
    }
    if (found=false) {
        send {right}
        ; tooltip key not found
    }
    clipboard = %temp%
return