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

我自我回答这个问题,因为我已经看到它在互联网上的问题,但几乎没有有用的答案,而且我肯定没有堆栈溢出的决议。

示例代码

考虑这个代码,它只是写几行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这样的terminal应用程序的问题。 很容易这样想,因为这些应用程序有时会有滞后行为。

示例输出

特别是当使用SetKeyDelay, 0, 0为快速“打字”,我得到各种奇怪的行为,如:

  • 双引号replace为单引号。 括号用9和0代替。 美元符号被4代替。

     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 
  • 期间由>的replace。 更多的案例变化。

     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修饰符有关,就像随机打开或closures一样。

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

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

Solutions Collecting From Web of "ControlSend使用SetKeyDelay时,随机发送错误字符(修改和未修改),0,0"

将其复制到您的脚本(从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同时使用post消息和sendInput / sendEvent来发送击键。 这是必需的,因为有些程序不能正确解释按键,除非发送的修改键被逻辑关闭(通过sendInput / Event发送)。

修改键(除非明确指出,例如{shitft down})通过sendInput发送,而非修饰符通过postMessage发送。 通过postmessage发送的密钥直接发送到窗口,所以比其他密钥/消息具有更少的延迟。 因此,击键消息可能不同步,从而导致意外的字符。 在你的情况下,大写字母要求shift键通过sendInput / Event发送。

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

– RHCP于2013年9月30日