1

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 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

The function works very well. Speed and more importantly reliability increased substantially. I had to upgrade from an older version of AHK to get it to work on one computer. I didn't check the old version before upgrading but it was one with the smaller Spy Window. Thanks for the tip. More tips like this would be appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.