SendInput在某些应用程序中不起作用 - 带Delphi的Windows

时间:2014-09-13 13:26:30

标签: delphi unicode sendinput

使用Delphi,我正在尝试找到一种向活动窗口发送字符串/字符串或键击的方法。使用SendInput我有以下代码:

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.

我编译了exe并使用Autohotkey将其分配给热键(F6),以便我可以从任何应用程序触发程序。它在大多数应用程序中运行良好 - 我已经在MS Excel,MS Word,Foxit Phantom pdf,Notepad ++等中进行了测试。字有点慢 - 你可以看到几乎一个一个地出现的字符,但它们都在那里正确。

但是,在Opera邮件(我最想使用该程序的应用程序之一)中,输入字符串在某种程度上总是错误的。以下是一些示例输入:

这是一个更长的字符串.. 他的第二个字符串是unicodeασδλκφχωιοευα.. 这是一个更长的字符串.. 他的第二个字符串是unicodeασδλκφχωιοευα.. 这是一个更长的srrig .. 他的第二个字符串是unicodeασδλκφχωιοευα.. 他是一个更长的字符串.. 他的第二个字符串是unicodeασδλκφχωιοευα.. 这是一个更长的字符串.. 他是第二个带有unicodeασδλκφχωιοευα的字符串..

在Kindle for PC(添加注释)中除了'。'之外的所有内容。转换为'T'。

关于问题是什么以及如何解决问题的任何想法?

谢谢!

1 个答案:

答案 0 :(得分:3)

您正在发送按键事件,但不会发送相应的按键事件。每个键击通常需要两个输入事件。一个用于按键,dwFlags = KEYEVENTF_UNICODE和一个用于按键,dwFlags = KEYEVENTF_UNICODE or KEYEVENTF_KEYUP

您可以按以下方式对其进行编码:

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;

最后,您很可能使用UI自动化执行此操作,而无需借助输入伪装。