使用SetKeyDelay,0,0时,ControlSend随机发送错误字符(已修改和未修改)

时间:2017-03-03 21:42:11

标签: windows autohotkey modifier

我自我回答这个问题,因为我已经看到它在互联网上问过,但几乎没有什么有用的答案,而且我找不到Stack Overflow的解决方案。

示例代码

考虑这段代码,它简单地写了几行shell命令:

^0::
    SetKeyDelay, 0, 0
    myWindow = ahk_exe Notepad.exe
    ControlSend, , set c=".cshrc-andrew.cheong"`n, %myWindow%
    ControlSend, , set v=".vimrc-andrew.cheong"`n, %myWindow%
    ControlSend, , foreach d ( /userhome/andrew.cheong /home/$USER /data/$USER )`n, %myWindow%
    ControlSend, , if ( -e $d/$c ) source $d/$c`n, %myWindow%
    ControlSend, , if ( -e $d/$v ) alias vim "vim -N -u $d/$v"`n, %myWindow%
    ControlSend, , end`n, %myWindow%
    Return

我将命令写入记事本,以表明它是一个仅限于PuTTy或xterm等终端应用程序的问题。这很容易想到,因为这些应用程序有时会出现滞后行为。

示例输出

特别是在使用SetKeyDelay, 0, 0进行快速"输入时,"我得到了各种奇怪的行为,比如:

  • 双引号替换为单引号。括号由9&0和0代替。美元符号由4&s代替。

    set c=".cshrc-andrew.cheong'
    set v=".vimrc-andrew.cheong"
    foreach d ( /userhome/andrew.cheong /home/$USER /data/$USER )
    if 9 -e 4d/4c 0 source 4d/4c
    if ( -e $d/$v ) alias vim 'vim -n -u 4d/4v'
    end
    
  • 用下划线代替破折号。案件变更。

    set c='.cshrc-andrew.cheong"
    set v='.vimrc-andrew.cheong'
    foreach d ( /userhome/andrew.cheong /home/4user /data/$USER )
    if 9 -e 4d/$C ) source 4d/$c
    if 9 _e $d/$v ) alias vim 'vim -N -u $d/$v"
    end
    
  • 期间被>'取代。更多案例变更。

    set c=".cshrc-andrew.cheong"
    set v=">VIMrc-andrew.cheong"
    foreach d ( /userhome/andrew.cheong /home/$USER /data/$USER )
    if 9 -e $d/$c ) source 4d/$c
    if ( -e $d/$V ) alias vim "vim -N -u $d/$v"
    end
    

显而易见,该问题与 Shift 修饰符有关,就好像它随机打开或关闭一样。

为什么会发生这种情况,我们该如何解决?

请注意,使用Send及其变体时没有问题。问题特别出现在ControlSend,这是将输入发送到特定控件或未聚焦窗口所需的。

1 个答案:

答案 0 :(得分:1)

解决方案

将其复制到您的脚本中(来自AutoHotkey论坛的用户RHCP):

pSendChars(string, control := "", WinTitle := "", WinText := "", ExcludeTitle := "", ExcludeText := "")
{
    for k, char in StrSplit(string)
        postmessage, WM_CHAR := 0x102, Asc(char),, %Control%, %WinTitle%, %WinText%, %ExcludeTitle%, %ExcludeText%
    return
}

并像这样使用它:

^0::
    myWindow = ahk_exe Notepad.exe
    line .= "set c="".cshrc-acheong""`n"
    line .= "set v="".vimrc-acheong""`n"
    line .= "foreach d ( /userhome/andrew.cheong /home/cama /home/$USER )`n"
    line .= "    if ( -e $d/$c ) source $d/$c`n"
    line .= "    if ( -e $d/$v ) alias vim ""vim -N -u $d/$v""`n"
    line .= "end`n"
    pSendChars(line, "edit1", myWindow)
    Return

就是这样。

请注意edit1是其文本控件的记事本名称。将此脚本用于PuTTy时,我将其更改为空白字符串。使用AutoHotkey的WindowSpy程序找出你想要写入的控件。

为什么

  

之前已经出现过几次。只是为了添加Lexikos   写道,问题是由于controlSend使用这两个帖子   message和sendInput / sendEvent发送击键。这是必需的   因为有些程序无法正确解释击键,除非   发送的修饰键在逻辑上是关闭的(通过sendInput / Event发送)。

     

发送修饰键(除非明确说明,例如{shitft down})   通过sendInput通过postMessage发送非修改器。密钥发送   通过postmessage直接发送到窗口,因此延迟较少   比其他键/消息。因此可以进行击键   消息不同步到达导致意外字符。在   在这种情况下,大写字母需要通过移位键发送   sendInput /活动。

     

除了使用keyDelays,您还可以尝试controlSetText和发布   WM_Char消息。如果您正在使用文本控件,我会   建议使用controlSetText。

     

- RHCP on 30 Sep 2013