I've been trying to resolve this for weeks now. I'm trying to create an app in Delphi that runs in the background and catches any hot key and executes Ctrl + c. So what I did is I catch the hot key for example ALT + right arrow then simulate Ctrl + c and throw the command to the current window.
What I noticed is that when I try sending commands to Firefox like below:
SendMessage(FireFoxHandle, WM_COPY, 0, 0);
sleep(250);
CopiedText := ClipBoard.AsText;
Copying was successful and I get the expected text. But once I used the same line of codes to other windows like chrome(chrome_widget_1) or notepad, I can't get anything. So what I tried is get the child window of the chrome and notepad and try to send the command to the child window.
Got "Chrome Legacy Window" as child of "chrome_widget_1" window but when i try to select a text in the tab, simulate the Ctrl + c, still not working.
Found an example here in stackoverflow for sending wm_copy to notepad's child window which is an edit like the code below:
ParentWindw := FindWindow('Notepad',nil);
if ParentWindow <> 0 then
begin
ChildWindow := FindWindowEx(ParentWindow, 0, 'Edit', nil);
SendMessage(ChildWindow, WM_COPY, 0, 0);
sleep(250);
CopiedText := ClipBoard.AsText;
end;
The code works but is there any dynamic way to determine the child window that i need to use for the wm_copy command? I'm asking not only for the notepad window but for all possible window that can be used.
Or is there anyway where I can copy the highlighted text in any window Programmatically in Delphi specifically in xe2?
I already researched already like sendinput, keyevents and tried them but no luck. I'm running out of option how to make it work.
Thanks for any help in advance.
The MouseAndKeyInput
code you presented in your accepted answer is just a wrapper for SendInput()
on Windows, which I told you in comments to use 3 days ago. You can (and should) get rid of those 5 .pas
files completely and replace those 3 separate KeyInput
method calls with 1 call to SendInput()
. It can send all 4 key inputs (Ctrl down, C down, C up, Ctrl up) atomically at 1 time (which is important to ensure other events don't get inter-mixed with your events), eg:
var
Inputs: array[0..3] of TInput;
begin
ZeroMemory(@Inputs, SizeOf(Inputs));
Sleep(250);
Inputs[0].type := INPUT_KEYBOARD;
Inputs[0].ki.wVk := VK_CONTROL;
Inputs[1].type := INPUT_KEYBOARD;
Inputs[1].ki.wVk := Ord('C');
Inputs[2].type := INPUT_KEYBOARD;
Inputs[2].ki.wVk := Ord('C');
Inputs[2].ki.dwFlags := KEYEVENTF_KEYUP;
Inputs[3].type := INPUT_KEYBOARD;
Inputs[3].ki.wVk := VK_CONTROL;
Inputs[3].ki.dwFlags := KEYEVENTF_KEYUP;
SendInput(4, Inputs, SizeOf(TInput));
Sleep(250);
Memo1.Lines.Add(Clipboard.AsText);
end;
Calling SendInput()
with its cInputs
parameter set to 1 (as KeyInput
and MouseInput
do) is almost always a bug in practice, and should only be done in rare situations.