delphirules
delphirules

Reputation: 7390

Simulate keypresses but only to specific window?

There are lots of examples of how to use the Windows API to simulate pressing of keys. One option would be something like the code below.

However what i'm trying to achieve is one step further. The code below requires the app you want to send the keys, to be always the foreground window. I'm trying to sending keys to a window that is NOT in focus, so i can automate tasks / macros with this window minimized.

Is there any alternative ?

Thanks

procedure PostKeyEx32(key: Word; const shift: TShiftState;
  specialkey: Boolean);
type
    TShiftKeyInfo = record
      shift: Byte ;
      vkey: Byte ;
    end;
    ByteSet = set of 0..7 ;
 const
    shiftkeys: array [1..3] of TShiftKeyInfo =
      ((shift: Ord(ssCtrl) ; vkey: VK_CONTROL),
      (shift: Ord(ssShift) ; vkey: VK_SHIFT),
      (shift: Ord(ssAlt) ; vkey: VK_MENU)) ;
 var
    flag: DWORD;
    bShift: ByteSet absolute shift;
    j: Integer;
 begin
    for j := 1 to 3 do
    begin
      if shiftkeys[j].shift in bShift then
        keybd_event(shiftkeys[j].vkey, MapVirtualKey(shiftkeys[j].vkey, 0), 0, 0) ;
    end;
    if specialkey then
      flag := KEYEVENTF_EXTENDEDKEY
    else
      flag := 0;

    if key = 47 then
      begin
      keybd_event(VkKeyScan('/'), 1, 0, 0);
      end
      else
      begin
      keybd_event(key, MapvirtualKey(key, 0), flag, 0) ;
      flag := flag or KEYEVENTF_KEYUP;
      keybd_event(key, MapvirtualKey(key, 0), flag, 0) ;
      end;

    for j := 3 downto 1 do
    begin
      if shiftkeys[j].shift in bShift then
        keybd_event(shiftkeys[j].vkey, MapVirtualKey(shiftkeys[j].vkey, 0), KEYEVENTF_KEYUP, 0) ;
    end;
 end;

Upvotes: 1

Views: 1397

Answers (2)

User007
User007

Reputation: 187

This is an example to send/handle WM_KEYUP messages by a specific window. But it is the same for any other message types (custom ones as well, just the params depends on its type) The destination window have to implement the message handler procedure.

procedure onKeyPressed( var message_ : TWMKeyUp ); message WM_KEYUP;

To send the messages, you have to use sendMessage with the right parameters. The first parameter is the handle of the window, the second one is the message ID, the 3rd and 4th ones depends on the message type defined by the message ID.

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure onKeyPressed( var message_ : TWMKeyUp ); message WM_KEYUP;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  if ( edit1.text <> '' ) then
    sendMessage( handle, WM_KEYUP, cardinal( edit1.text[1] ), 0 );
end;

procedure TForm1.onKeyPressed( var message_ : TWMKeyUp );
var
  c : char;
begin
  c := char( message_.CharCode );
  label1.caption := label1.caption + c;
end;

Upvotes: 3

Torbins
Torbins

Reputation: 2216

For most apps WM_KEYDOWN and WM_KEYUP will be enough: http://www.delphigroups.info/2/80/324746.html

But for some apps you will require API hooks on functions like GetAsyncKeyState plus a way to load your dll into a target process: https://progamercity.net/delphi/647-delphi-dll-injection-functions.html. All that will be very suspicious from Antivirus software point of view.

Upvotes: 1

Related Questions