他のアプリケーションにキー入力情報を送りつける

ソフトウェアキーボードのメイン機能ですね。SendInputを使います。今回は次のクラスを作りました。

unit USendInput;

interface

uses
  Windows;

type
  TSendInput = class
  private
    FKeyInputs: array of TInput;
    FKeyInputCount: integer;
    procedure Initialize;
  public
    constructor Create;

    procedure KeyDown(Key: Byte);
    procedure KeyUp(Key: Byte);

    procedure Input(Key: Byte; Flags: DWord);
    procedure Send;
  end;

implementation

{ TSendInput }

constructor TSendInput.Create;
begin
  Initialize;
end;

procedure TSendInput.Initialize;
begin
  FKeyInputCount := 0;
  SetLength(FKeyInputs, FKeyInputCount);
end;

procedure TSendInput.Input(Key: Byte; Flags: DWord);
begin
  Inc(FKeyInputCount);
  SetLength(FKeyInputs, FKeyInputCount);
  FKeyInputs[FKeyInputCount - 1].Itype := INPUT_KEYBOARD;
  with FKeyInputs[FKeyInputCount - 1].ki do begin
    wVk := Key;
    wScan := MapVirtualKey(wVk, 0);
    dwFlags := KEYEVENTF_EXTENDEDKEY;
    dwFlags := dwFlags or Flags;
    time := 0;
    dwExtraInfo := 0;
  end;
end;

procedure TSendInput.KeyDown(Key: Byte);
begin
  Input(Key, 0);
end;

procedure TSendInput.KeyUp(Key: Byte);
begin
  Input(Key, KEYEVENTF_KEYUP);
end;

procedure TSendInput.Send;
begin
  SendInput(FKeyInputCount, FKeyInputs[0], SizeOf(FKeyInputs[0]));
  Initialize;
end;

end.

使い方はこんな感じ。

// 実際に使うときはCreateとFreeはそれぞれFormCreateと
// FormDestroyでやっています
FSendInput := TSendInput.Createはあらかじめやっておく
FSendInput.KeyDown(VK_MENU);
FSendInput.KeyDown(VK_LEFT);
FSendInput.KeyUp(VK_LEFT);
FSendInput.KeyUp(VK_MENU);
FSendInput.Send;
FSendInput.Free;

KEYEVENTF_EXTENDEDKEYは設定しなくても一部のキー以外は送信できますが、常に設定しておいても問題なさそうなので勝手に設定することにしています。