Directly sending keystrokes to another process via hooking
This is a little code that allows you to send message to a backgrounded application. To send the "A" char for example, simply call sendKeystroke(Keys.A), and don't forget to use namespace System.windows.forms to be able to use the Keys object.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace keybound
{
class WindowHook
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public static void sendKeystroke(ushort k)
{
const uint WM_KEYDOWN = 0x100;
const uint WM_SYSCOMMAND = 0x018;
const uint SC_CLOSE = 0x053;
IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");
IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, ((IntPtr)k), (IntPtr)0);
//IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
}
}
}
distinguish between different instances or windows of a process and find their PID instead of their owner PID to send input event in macOS?
This activates each window in TextEdit and sends a space keystroke.
activate application "TextEdit"
tell application "System Events"
tell application process "TextEdit"
repeat with theWindow in windows
perform action "AXRaise" of theWindow
keystroke " "
end repeat
end tell
end tell
But to note how this would work without pressing keys, the following appends "A" to all the currently open documents without bringing anything to the foreground or interfering with the user's input.
tell application "TextEdit"
repeat with theDocument in documents
set text of theDocument to (text of theDocument) & "A"
end repeat
end tell
Whenever possible, you want things like this rather than sending keystrokes.
Send keystrokes to a specific window (in background), but do something else in the meantime
In order to send Keystroke to any application window, without activating the application to get input focus. We must get the windows handler first. This requires Windows API FindWindow
and FindWindowsEx
. First, the handle of Top Level window of application is obtained by FindWindow
. Then use FindWindowsEx
to get the handle of the child window or control to receive keys.
Because the top window of the application is not always the window that accepts Keystroke (such as notepad.exe, the window that actually accepts Keystroke is the Edit control under the main window of Notepad), it can be found by ClassID or Caption.
Assuming that the handle of the target window has been got(hwnd), the key message will be sent to the window with PostMessage
.
For normal character keys, it is simplest to use WM_CHAR message directly, as follows:
PostMessage(hwnd, WM_CHAR, 'a', 0);
For un-normal character keys, such as function keys, direction keys, etc., WM_KEYDOWN
and WM_KEYUP
messages should be used as follows:
VirtualKey = MapVirtualKeyA(VK_RIGHT, 0);
PostMessage(hwnd, WM_KEYDOWN, VK_RIGHT, 0x0001|VirtualKey<<16);
PostMessage(hwnd, WM_KEYUP, VK_RIGHT, 0x0001|VirtualKey<<16|0xC0<<24);
The details for last parameter (lParam
) you can reference to msdn.
For the keys "Shift/Ctrl", sample:
keybd_event(VK_SHIFT, 0, 0, 0);
PostMessage(hwnd, WM_KEYDOWN, 0x41, 0x001E0001);
PostMessage(hwnd, WM_KEYUP, 0x41, 0xC01E0001);
keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
For the keys "Alt", It belongs to the system button, using WM_SYSKEYDOWN
/WM_SYSKEYUP
message. sample:
PostMessage(hwnd, WM_SYSKEYDOWN, VK_F4, 0x003E0001 |0x20000000);
PostMessage(hwnd, WM_SYSKEYUP, VK_F4, 0xC03E0001 | 0x20000000);
0x20000000
means context code, the value is 1 if the "Alt" key is down.
Send keystroke to application in c# (sendkeys, postmessage, sendmessage all not working)
There is lot of trial and error with that, to get it working
Here is a bit of code I posted before, you might wanna give a try (and there is some more info attached)...
Pinvoke SetFocus to a particular control
Try setting focus first (using the mechanism mentioned) - and then using SendKeys
or SendInput
.
Here is some detailed code for SendInput
...
How to send a string to other application including Microsoft Word
Send keypress to specific window on Mac
Demo in swift
, using
$ swift --version
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin17.7.0
simple example code sendspace.swift
import Foundation
let src = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
let kspd = CGEvent(keyboardEventSource: src, virtualKey: 0x31, keyDown: true) // space-down
let kspu = CGEvent(keyboardEventSource: src, virtualKey: 0x31, keyDown: false) // space-up
let pids = [ 24834, 24894, 24915 ]; // real PID-s from command 'ps -ax' - e.g. for example 3 different processes
for i in 0 ..< pids.count {
print("sending to pid: ", pids[i]);
kspd?.postToPid( pid_t(pids[i]) ); // convert int to pid_t
kspu?.postToPid( pid_t(pids[i]) );
}
After running the code: swift sendspace.swift
(from the Terminal) all 3 processes with defined PIDs will get the space keypress, while the Terminal is still the foreground app.
Related Topics
How to Convert [Any] to Nsarray
Spritekiit Swift: Touch a Moving Object
How to Execute Different Implementation of a Method of a Generic Struct Based on the Generic Type
How to Know When to Call a Closure with () or Without Parentheses in Handler:
How Assistant Model Works in Swift
Resizing Large Resolution Images Producing 1000X1000 Pixels Size When Size Is Set to 500X500 Pixels
Error "{ Expected After If Statement"
Can't Change Uiimageview Image in Function (Swift)
Swift - Pass JSON Data to Other Views
Why Won't My Collection View Cells Display in the iPhone Simulator
Uibutton Causing Unrecognized Selector Sent to Instance
Generate Labels and Align in Middle
How Does One Use Nsdateformatter's Islenient Option
How to Call Swiftui Navigationlink Conditionally
How to Procedurally Draw Rectangle/Lines in Swift Using Cgcontext