Using SendMessage or Postmessage to simulate keyboard lazarus / 67-Windows ---------------------------------------------------------------------- ArminLinder · 2022-12-21 23:59 Hi all, Trying to send keystrokes to an application on Windows 11 I have this code ... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  wndMain: HWND;  r:LResult;  scanCode:UINT;  l:LPARAM;  w:WPARAM; begin  // wndMain := FindWindow(PChar(aClassName),nil);  wndMain := FindWindow('Notepad',nil);  DoShowStatus('Window Handle: ' + IntToStr(wndMain));  if wndMain <> 0 then    begin    l := 0;    // scanCode := MapVirtualKey(VK_A, 0);    // l := ($00000001 OR (scanCode SHL 16));    r := SendMessage(wndMain,WM_KEYDOWN,VK_A,l);    // l := l OR $C0000000;    r := SendMessage(wndMain,WM_KEYUP,VK_A,l);    end;end;   The objective is to send a specific keystroke (I choose VK_A for testing) to an application, to try I choose notepad. Finding the hwnd for notepad seems to work, a value is returned. Unfortunately there is no reaction in Notepad, no keystrokes show up, though SendMessage returns 0. I tried PostMessage too, same behaviour. Regarding the bitmask for lParam, I took it from the AutoIt source code, but using it (commented out) doesn't change anything. Can anyone provide a working code sample showing how I need to use SendMessage or PostMessage? From what I read I should prefer PostMessage. Thnx, Armin. ---------------------------------------------------------------------- balazsszekely · 2022-12-22 05:27 @Nimarl QuoteThe objective is to send a specific keystroke (I choose VK_A for testing) to an application, to try I choose notepad. Finding the hwnd for notepad seems to work, a value is returned. Unfortunately there is no reaction in Notepad, no keystrokes show up, though SendMessage returns 0. I tried PostMessage too, same behaviour. Regarding the bitmask for lParam, I took it from the AutoIt source code, but using it (commented out) doesn't change anything. Can anyone provide a working code sample showing how I need to use SendMessage or PostMessage? From what I read I should prefer PostMessage. 1. You are sending the keystroke to the wrong window, notepad has a child window named "Edit". Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses windows; procedure TForm1.Button1Click(Sender: TObject);var  wHandle: HWND;begin  wHandle := FindWindow('notepad', nil);  if wHandle = 0 then    Exit;  wHandle := FindWindowEx(wHandle, FindWindow('Edit', nil), nil, nil);  if wHandle = 0 then    Exit;  SendMessage(wHandle, WM_CHAR, Word('a'), 0);end;  2. Replace SendMessage with PostMessage, the later is an asynchronous function, it won't block the message queue ---------------------------------------------------------------------- Remy Lebeau · 2022-12-22 16:41 Quote from: Nimral on December 22, 2022, 12:59:50 amTrying to send keystrokes to an application You can't simulate keyboard input with PostMessage (or SendMessage, too) ---------------------------------------------------------------------- Thaddy · 2022-12-22 19:49 Alas, several consts and the INPUT struct are missing in Windows, so the SendInput() example from msdn won't work even if correctly translated to Pascal. Busy on it. Should be easy. [edit] progress, it compiles (but does not work yet):Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode delphiunicode}{$apptype console}uses jwawindows;//******************** **************************************************//// Sends Win + D to toggle to the desktop////****************************************** ****************************type  Tinputs = array[0..3] of INPUT; const  VK_D:word = $0044;procedure ShowDesktop;var  inputs:TInputs;  uSent:UINT;begin    writeln('Sending Win-D');    ZeroMemory(@inputs, length(inputs));     inputs[0].type_ := INPUT_KEYBOARD;    inputs[0].ki.wVk := VK_LWIN;       inputs[1].type_ := INPUT_KEYBOARD;    inputs[1].ki.wVk := VK_D;     inputs[2].type_ := INPUT_KEYBOARD;    inputs[2].ki.wVk := VK_D;    inputs[2].ki.dwFlags := KEYEVENTF_KEYUP;     inputs[3].type_ := INPUT_KEYBOARD;    inputs[3].ki.wVk := VK_LWIN;    inputs[3].ki.dwFlags := KEYEVENTF_KEYUP;    uSent := SendInput(SizeOf(inputs),inputs, sizeof(INPUT));    if (uSent <> length(inputs)) then        writeln(HRESULT_FROM_WIN32(GetLastError()));end;begin  ShowDeskTop;end. Note this code should also work from a console, tested with the C++ code. Probably an oversight, maybe someone can spot it? Maybe User Interface Privilege Isolation, a.k.a. UIPI? ---------------------------------------------------------------------- KodeZwerg · 2022-12-22 22:06 Quote from: GetMem on December 22, 2022, 06:27:42 amCode: [Select]  SendMessage(wHandle, WM_CHAR, Word('a'), 0);I am unsure what the OP try to do, maybe WM_SETTEXT is better. ---------------------------------------------------------------------- Thaddy · 2022-12-22 22:36 Quote from: KodeZwerg on December 22, 2022, 11:06:20 pmI am unsure what the OP try to do, maybe WM_SETTEXT is better. Note Remy's remark and Raymond Chen's column: they are right. (Now I only need to get my example to work, but al least it compiles) All that post/sendmessage stuff worked somewhat in very old Win versions (pre XP, WIN2000) and still may work, but is not reliable enough. ---------------------------------------------------------------------- KodeZwerg · 2022-12-22 23:24 I've read the remarks and need to think for a while, I guess when I do connect to the target thread I can attach to play a little. Here is something to send at least some Text if that is wanted  (based on GetMems version as source) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function SendTextAtToMsg(const AClassname, AControlClass, AMessage: WideString): Boolean;var  wHandle: HWND;  Len: DWORD;  s, z: WideString;begin  Result := False;  // get main window handle  wHandle := FindWindowW(PWideChar(AClassname), nil);  if (wHandle = 0) then    Exit;  // get control handle  wHandle := FindWindowExW(wHandle, FindWindowW(PWideChar(AControlClass), nil), nil, nil);  if (wHandle = 0) then    Exit;  // get current contant as proof of concept, i am sure its wrong somewhere :P  s := '';  Len := Succ(SendMessageW(wHandle, WM_GETTEXTLENGTH, 0, 0));  SetLength(s, (Succ(Len) * SizeOf(WideChar)));  SendMessageW(wHandle, WM_GETTEXT, WPARAM(Succ(Len)), LPARAM(@s[1]));  Form1.Memo1.Clear;  Form1.Memo1.Text := s;  // send to control a new string  z := AMessage;  Len := Succ((Length(z) * SizeOf(WideChar)));  SendMessageW(wHandle, WM_SETTEXT, WPARAM(Succ(Len)), LPARAM(@z[1]));  Result := True;end; procedure TForm1.Button1Click(Sender: TObject);begin  if SendTextAtToMsg('notepad', 'edit', 'Hacked') then  Memo1.Lines.Add('New Text Set')    else    Memo1.Lines.Add('Error at finding Notepad!');end; ---------------------------------------------------------------------- balazsszekely · 2022-12-23 09:20 Sending a simple English char like "A" will definitely work with PostMessage/SendMessage too. There is no contradiction with Raymond Chen's article. Keybd_Event is now superseded, the preferred method is SendInput, but in order to use it, first you have to activate the target window with SetForegroundWindow. Stackoverflow is full with examples on how to use SendInput. ---------------------------------------------------------------------- Remy Lebeau · 2022-12-23 16:43 Quote from: Thaddy on December 22, 2022, 08:49:17 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uSent := SendInput(SizeOf(inputs),inputs, sizeof(INPUT)); In the 1st parameter, you are passing in the byte size of the array, but the function wants the number of array elements instead, so you need to use Length() instead of SizeOf(): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uSent := SendInput(Length(inputs), inputs, sizeof(INPUT));