Does anyone know how to programmatically press a key exactly the same as if it were pressed on a keyboard? PostMessage fails, SendInput fails, keybd_event fails, SendMessage fails and I even tried the unusual way of mimicing a key press using the Vcl.Touch.Keyboard. I even wrote a quick vb script file calling sendkeys which also failed. I have been have having trouble trying doing this on a program called Sellerdeck http://www.sellerdeck.com/
I have tried all of the following, they all work with notepad but fail on this program. The window is successfully brought to the forground by
procedure bringToForegroung;
Var
findhandle1 : cardinal;
begin
findhandle1 := FindWindow(NIL, 'Business Plus - Test site: Online Catalogue');
ShowWindow(findhandle1,SW_SHOW);
SetForegroundWindow(findhandle1);
end;
procedure SendF10;
Var
findhandle1 : cardinal;
begin
findhandle1 := FindWindow(NIL, 'Business Plus - Test site: Online Catalogue');
ShowWindow(findhandle1,SW_SHOW);
SetForegroundWindow(findhandle1);
PostMessage(findhandle1, WM_KEYDOWN, VK_F10, 0);
PostMessage(findhandle1, WM_KEYUP, VK_F10, 0);
end;
procedure SendAltF;
var
KeyInputs: array of TInput;
//--------------------------------------------
procedure KeybdInput(VKey: Byte; Flags: DWORD);
begin
SetLength(KeyInputs, Length(KeyInputs)+1);
KeyInputs[high(KeyInputs)].Itype := INPUT_KEYBOARD;
with KeyInputs[high(KeyInputs)].ki do
begin
wVk := VKey;
wScan := MapVirtualKey(wVk, 0);
dwFlags := Flags;
end;
end;
begin
KeybdInput(VK_MENU, 0); // Alt
KeybdInput(Ord('F'), 0);
KeybdInput(Ord('F'), KEYEVENTF_KEYUP);
KeybdInput(VK_MENU, KEYEVENTF_KEYUP); // Alt
SendInput(Length(KeyInputs), KeyInputs[0], SizeOf(KeyInputs[0]));
end;
procedure SendKey2(Wnd,VK : Cardinal; Ctrl,Alt,Shift : Boolean);
var
MC,MA,MS : Boolean;
begin
// Try to bring target window to foreground
ShowWindow(Wnd,SW_SHOW);
SetForegroundWindow(Wnd);
// Get current state of modifier keys
MC:=Hi(GetAsyncKeyState(VK_CONTROL))>127;
MA:=Hi(GetAsyncKeyState(VK_MENU))>127;
MS:=Hi(GetAsyncKeyState(VK_SHIFT))>127;
// Press modifier keys if necessary (unless already pressed by real user)
if Ctrl<>MC then keybd_event(VK_CONTROL,0,Byte(MC)*KEYEVENTF_KEYUP,0);
if Alt<>MA then keybd_event(VK_MENU,0,Byte(MA)*KEYEVENTF_KEYUP,0);
if Shift<>MS then keybd_event(VK_SHIFT,0,Byte(MS)*KEYEVENTF_KEYUP,0);
// Press key
keybd_event(VK,0,0,0);
keybd_event(VK,0,KEYEVENTF_KEYUP,0);
// Release modifier keys if necessary
if Ctrl<>MC then keybd_event(VK_CONTROL,0,Byte(Ctrl)*KEYEVENTF_KEYUP,0);
if Alt<>MA then keybd_event(VK_MENU,0,Byte(Alt)*KEYEVENTF_KEYUP,0);
if Shift<>MS then keybd_event(VK_SHIFT,0,Byte(Shift)*KEYEVENTF_KEYUP,0);
end;
procedure SendF10v2;
Var
findhandle1 : cardinal;
begin
findhandle1 := FindWindow(NIL, 'Business Plus - Test site: Online Catalogue');
ShowWindow(findhandle1,SW_SHOW);
SetForegroundWindow(findhandle1);
SendMessage(findhandle1, WM_KEYDOWN, VK_F10, 0);
SendMessage(findhandle1, WM_KEYUP, VK_F10, 0);
end;
uses
Vcl.Touch.Keyboard, Vcl.Touch.KeyboardTypes;
type
procedure FormCreate(Sender: TObject);
protected {i.e. dont make form active}
procedure CreateParams(var Params: TCreateParams); override; {i.e. dont make keyboard form active}
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
ExStyle := ExStyle or WS_EX_NOACTIVATE;
WndParent := GetDesktopwindow;
end;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
KeyData: TKeyData;
begin
KeyData := VKey(VK_F10, -1);
SendKey(KeyData, ksDown);
SendKey(KeyData, ksUp);
end;
Option Explicit
Dim objShell
Set objShell = CreateObject("WScript.Shell")
objShell.Run """C:\Program Files (x86)\SellerDeck 2013\Catalog.exe"" /s ""Test site"" /n Administrator /w Administrator", 0, True
Wscript.Sleep 10000
objShell.SendKeys "%F"
Wscript.Sleep 1000
objShell.SendKeys "%F"
Wscript.Sleep 1000
objShell.SendKeys "%F"
Wscript.Sleep 1000
objShell.SendKeys "%F"
Wscript.Sleep 1000
objShell.SendKeys "%F"
Wscript.Sleep 1000
objShell.SendKeys "%F"
WScript.Quit
As I said all, of these work in notepad, otherwise I would think it was my PC that was the problem. I am trying to automate some basic tasks on this Sellerdeck program. Is there anyway to exactly mimic a key press? I hope it is just that I am missing something really basic.
My guess is that you are sending the commands to the wrong Window handle. Perhaps the main application window, returned by FindWindow(), is not the one handle keystokes.
Try to use a debug tool, like WinSight (ws32.exe - which was shipped in older versions of Delphi), to guess the right handle...
The following code works fine for me:
procedure TForm1.Button1Click(Sender: TObject);
begin
keybd_event(VK_MENU, $b8, 0, 0);
keybd_event(VK_F4, $8f, 0, 0);
keybd_event(VK_F4, $8f, KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, $b8, KEYEVENTF_KEYUP, 0);
end;
The required function is the following:
void keybd_event(BYTE bVirtualKey, BYTE bScanCode, DWORD dwFlags, DWORD dwExtraInfo);
This syntax must be used:
The following link summarizes all information on the function together in detail: http://www.codeproject.com/Articles/7305/Keyboard-Events-Simulation-using-keybd-event-funct
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With