ControlSend randomly sending wrong characters (modified and unmodified) when using SetKeyDelay, 0, 0

烈酒焚心 提交于 2019-12-19 11:54:13

问题


I'm self-answering this question because I've seen it asked all over the Internet, but with few helpful answers, and definitely no resolutions on Stack Overflow that I can find.

Example Code

Consider this code, which simply writes several lines of shell commands:

^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

I'm writing the commands to Notepad to show that it is not an issue limited to terminal applications like PuTTy or xterm. It's easy to think so, since these applications sometimes have laggy behavior.

Example Output

Specifically when using SetKeyDelay, 0, 0 for fast "typing," I get all kinds of weird behavior, like:

  • Double-quotes replaced by single-quotes. Parentheses replaced by 9's and 0's. Dollar signs replaced by 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
    
  • Dashes replaced by underscores. Case changes.

    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
    
  • Periods replaced by >'s. More case changes.

    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
    

It's obvious the issue has something to do with the Shift modifier, as if it's being randomly turned on or off.

Why is this happening, and how do we fix it?

Note that there are no problems when using Send and its variants. The issue specifically arises with ControlSend, which is needed to send inputs to specific controls or to an unfocused window.


回答1:


Solution

Copy this into your script (from user RHCP at AutoHotkey forums):

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
}

And use it like this:

^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

That's it.

Note that edit1 is Notepad's name for its text control. When using this script for PuTTy, I changed it to a blank string. Use AutoHotkey's WindowSpy program to find out the control you wish to write to.

Why

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.

- RHCP on 30 Sep 2013



来源:https://stackoverflow.com/questions/42588904/controlsend-randomly-sending-wrong-characters-modified-and-unmodified-when-usi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!