使用 SetKeyDelay, 0, 0 时 ControlSend 随机发送错误字符(修改和未修改)
ControlSend randomly sending wrong characters (modified and unmodified) when using SetKeyDelay, 0, 0
我正在自己回答这个问题,因为我在整个 Internet 上都看到过这个问题,但几乎没有有用的答案,而且我在 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
快速 "typing," 时,我会遇到各种奇怪的行为,例如:
双引号替换为单引号。括号由 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
用 > 替换句点。更多大小写更改。
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
中,需要将输入发送到特定控件或未聚焦的 window。
解决方案
将此复制到您的脚本中(来自 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 程序找出您要写入的控件。
为什么
This has come up a few times before. Just to add to what Lexikos
wrote, the issue is due to the fact that controlSend uses both post
message and sendInput/sendEvent to send keystrokes. This is required
as some programs will not correctly interpret the keystrokes unless
the sent modifier keys are logically down (sent via sendInput/Event).
Modifier keys (unless explicitly stated e.g. {shitft down}) are sent
via sendInput while non-modifers are sent via postMessage. Keys sent
via postmessage are sent directly to the window and so have less delay
than the other keys/messages. Consequently it's possible for keystroke
messages to arrive out of synch resulting in unexpected characters. In
your case the capitalised letters require the shift key to be sent via
sendInput/Event.
In addition to using keyDelays, you can try controlSetText and posting
WM_Char messages. If you're working with a text control i would
recommend using controlSetText.
我正在自己回答这个问题,因为我在整个 Internet 上都看到过这个问题,但几乎没有有用的答案,而且我在 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
快速 "typing," 时,我会遇到各种奇怪的行为,例如:
双引号替换为单引号。括号由 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
用 > 替换句点。更多大小写更改。
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
中,需要将输入发送到特定控件或未聚焦的 window。
解决方案
将此复制到您的脚本中(来自 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 程序找出您要写入的控件。
为什么
This has come up a few times before. Just to add to what Lexikos wrote, the issue is due to the fact that controlSend uses both post message and sendInput/sendEvent to send keystrokes. This is required as some programs will not correctly interpret the keystrokes unless the sent modifier keys are logically down (sent via sendInput/Event).
Modifier keys (unless explicitly stated e.g. {shitft down}) are sent via sendInput while non-modifers are sent via postMessage. Keys sent via postmessage are sent directly to the window and so have less delay than the other keys/messages. Consequently it's possible for keystroke messages to arrive out of synch resulting in unexpected characters. In your case the capitalised letters require the shift key to be sent via sendInput/Event.
In addition to using keyDelays, you can try controlSetText and posting WM_Char messages. If you're working with a text control i would recommend using controlSetText.