Hi,
I'm building a Python project to insert text into the currently focused Windows application at the caret position (triggered by a hotkey).
I'm using user32.SendMessageW with EM_REPLACESEL, but it only works with native apps like Notepad or Explorer, and fails with browsers, VS Code, and other modern apps.
Here is my current code:
import ctypes
from ctypes import wintypes
user32 = ctypes.WinDLL("user32", use_last_error=True)
kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
EM_REPLACESEL = 0x00C2
user32.GetForegroundWindow.restype = wintypes.HWND
user32.GetFocus.restype = wintypes.HWND
user32.AttachThreadInput.argtypes = [
wintypes.DWORD,
wintypes.DWORD,
wintypes.BOOL,
]
user32.GetWindowThreadProcessId.argtypes = [
wintypes.HWND,
ctypes.POINTER(wintypes.DWORD),
]
user32.GetWindowThreadProcessId.restype = wintypes.DWORD
kernel32.GetCurrentThreadId.restype = wintypes.DWORD
user32.SendMessageW.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPCWSTR,
]
user32.SendMessageW.restype = ctypes.c_ssize_t
def get_focused_hwnd():
foreground = user32.GetForegroundWindow()
current_thread = kernel32.GetCurrentThreadId()
foreground_thread = user32.GetWindowThreadProcessId(foreground, None)
user32.AttachThreadInput(current_thread, foreground_thread, True)
try:
focused = user32.GetFocus()
finally:
user32.AttachThreadInput(current_thread, foreground_thread, False)
return focused
def insert_text(text: str):
hwnd = get_focused_hwnd()
if not hwnd:
raise RuntimeError("No focused control found")
user32.SendMessageW(hwnd, EM_REPLACESEL, True, text)
if __name__ == "__main__":
insert_text("Hello, world!")
What's the recommended approach to support all apps (e.g., browsers, VS Code, Electron)?
Also, I don't want use clipboard paste.
Thanks.