【问题标题】:SendInput not working in certain apps - Windows with DelphiSendInput 在某些应用程序中不起作用 - 带有 Delphi 的 Windows
【发布时间】:2014-11-07 13:00:01
【问题描述】:

使用 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++ 等中测试过它。Word 有点慢 - 你可以看到字符出现,几乎一个一个,但它们都在那里正确。

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

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

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

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

谢谢!

【问题讨论】:

    标签: delphi unicode sendinput


    【解决方案1】:

    您正在发送按键按下事件,但未发送相应的按键按下事件。每次击键通常需要两个输入事件。一个用于按键,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 自动化来做到这一点,而不必诉诸输入伪造。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 1970-01-01
      相关资源
      最近更新 更多