问题
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!
回答1:
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.
来源:https://stackoverflow.com/questions/25823685/sendinput-not-working-in-certain-apps-windows-with-delphi