Bruce Button
Bruce Button

Reputation: 55

SendInput not working in certain apps - Windows with Delphi

Using Delphi, I'm trying to find a way of sending a string/series of characters or keystrokes to the active window. Using SendInput I have the following code:

uses
  System.SysUtils, Windows, System.Types, System.UITypes, System.Classes,
  System.Variants, VCL.Dialogs, VCL.ExtCtrls;

var
    input: array of TInput;
    s: String;
    i: Integer;

begin
    s := 'This is a longer string.' + 
          sLineBreak + 'This is the second string with unicode ασδλκφχωιοευα.';
    SetLength(input, Length(s));

    i := 1;
    while i <= Length(s) do
        if ord(s[i]) <> 13 then begin
            input[i-1].iType := INPUT_KEYBOARD;
            //input[i+5].ki.wVk := 0;
            input[i-1].ki.dwFlags := KEYEVENTF_UNICODE;
            input[i-1].ki.wScan := ord(s[i]);
            i := i+1;
        end
        else begin   //Type Enter key.
            //Key down
            input[i-1].iType := INPUT_KEYBOARD;
            input[i-1].ki.wVk := VK_RETURN;

            i := i+1;   //Assumes that chr(13) is followed by chr(10).
                        //Ignore the chr(10) and lift up the Enter key.

            input[i-1].iType := INPUT_KEYBOARD;
            input[i-1].ki.wVk := VK_RETURN;
            input[i-1].ki.dwFlags := KEYEVENTF_KEYUP;
            i:= i+1;
        end;
        //end;

    Windows.SendInput(Length(s), input[0], SizeOf(input[0]));

end.

I have compiled the exe and assigned it to a hotkey (F6) using Autohotkey so that I can trigger the program from any application. It works fine in most appplications - I've tested it in MS Excel, MS Word, Foxit Phantom pdf, Notepad++, etc. Word is a bit slow - you can see the characters appearing, almost one by one, but they are all there correctly.

However, in Opera mail (one of the applications where I most want to use the program), the input strings are always wrong in some way. Here is some sample input:

Tis is a longer string.. his is the second string with unicode ασδλκφχωιοευα.. Tis is a longer string.. his is the second string with unicode ασδλκφχωιοευα.. This is a longr srrig.. his is the second string with unicode ασδλκφχωιοευα.. his is a longer string.. his is the second string with unicode ασδλκφχωιοευα.. Thisis a longer string.. his is the second string with unicode ασδλκφχωιοευα..

In Kindle for PC (Add Note) everything except the '.' gets converted to 'T'.

Any ideas on what the problem is and how to fix it?

Thank you!

Upvotes: 2

Views: 1605

Answers (1)

David Heffernan
David Heffernan

Reputation: 612884

You are sending key down events, but not corresponding key up events. You typically need two input events per key stroke. One for key down, dwFlags = KEYEVENTF_UNICODE and one for key up, dwFlags = KEYEVENTF_UNICODE or KEYEVENTF_KEYUP.

You could code it along these lines:

procedure SendKeys(const Text: string);
var
  C: Char;
  Input: TInput;
  InputList: TList<TInput>;
begin
  InputList := TList<TInput>.Create;
  try
    for C in Text do begin
      if C = #10 then continue;
      Input := Default(TInput);
      Input.Itype := INPUT_KEYBOARD;
      Input.ki.dwFlags := KEYEVENTF_UNICODE;
      Input.ki.wScan := ord(C);
      InputList.Add(Input);
      Input.ki.dwFlags := KEYEVENTF_UNICODE or KEYEVENTF_KEYUP;
      InputList.Add(Input);
    end;
    SendInput(InputList.Count, InputList.List[0], SizeOf(TInput));
  finally
    InputList.Free;
  end;
end;

Finally, it's quite likely that you'd be able to do this using UI Automation without having to resort to input faking.

Upvotes: 4

Related Questions