Около 12 лет назад я написал программу для Windows, которая сидела в трее и посылала нажатия клавиш на определенные окна, когда они получали фокус.У меня больше нет кода, и я забыл все детали.
Тем не менее, процесс будет работать примерно так:
Для вашего GUI, если вы используете Python, вы, вероятно, захотитеиспользуйте PyQT или wxPython.Обе библиотеки облегчают написание приложений с графическим интерфейсом (хотя вы можете напрямую использовать API-интерфейсы Windows).
Если бы это был я, я бы отложил программирование с использованием графического интерфейса и использовал бы PythonWin.Используйте инструменты GUI (множество примеров в исходном коде), чтобы создать простой диалог (также Window
) для обработки событий.
Возможно, для вашего приложения есть несколько подходов для выбора target
окно.Окно виртуальной клавиатуры, вероятно, будет нуждаться в краже фокуса (для получения событий мыши), но затем ему нужно будет знать, в какое окно отправлять нажатия клавиш.
- Вы можете иметь раскрывающийся элемент управления вдиалоговое окно, которое позволяет вам выбрать целевое окно (вы можете легко получить заголовок каждого окна для выбора цели), или
- Когда ваше окно получает фокус (есть событие, которое вы можете перехватить, что-то вроде
WM_FOCUS
), вы можете запросить последнее окно с фокусом или сохранить вкладки, на которых окна имеют фокус , и использовать последнее, которое вы заметили.
В любом случае,если у вас есть дескриптор целевого окна, вы можете использовать SendMessage
для отправки нажатий клавиш в целевое окно.Сначала я предлагаю просто передавать обычные нажатия клавиш, а потом беспокоиться о захвате щелчков мыши.
Редактировать Мне удалось объединить это для отправки нажатий клавиш в другое окно.
import win32ui
import win32con
import time
from ctypes import *
PUL = POINTER(c_ulong)
class KeyBdInput(Structure):
_fields_ = [("wVk", c_ushort),
("wScan", c_ushort),
("dwFlags", c_ulong),
("time", c_ulong),
("dwExtraInfo", PUL)]
class HardwareInput(Structure):
_fields_ = [("uMsg", c_ulong),
("wParamL", c_short),
("wParamH", c_ushort)]
class MouseInput(Structure):
_fields_ = [("dx", c_long),
("dy", c_long),
("mouseData", c_ulong),
("dwFlags", c_ulong),
("time",c_ulong),
("dwExtraInfo", PUL)]
class Input_I(Union):
_fields_ = [("ki", KeyBdInput),
("mi", MouseInput),
("hi", HardwareInput)]
class Input(Structure):
_fields_ = [("type", c_ulong),
("ii", Input_I)]
def send_char(char):
FInputs = Input * 1
extra = c_ulong(0)
ii_ = Input_I()
KEYEVENTF_UNICODE = 0x4
ii_.ki = KeyBdInput( 0, ord(char), KEYEVENTF_UNICODE, 0, pointer(extra) )
x = FInputs( ( 1, ii_ ) )
windll.user32.SendInput(1, pointer(x), sizeof(x[0]))
if __name__ == '__main__':
wnd = win32ui.FindWindow(None, '* Untitled - Notepad2 (Administrator)')
type_this = 'jaraco'
wnd.SetFocus()
wnd.SetForegroundWindow()
for char in type_this:
send_char(char)
Я обнаружил, что техника PostMessage не очень хорошо работала (у меня она вообще не работала).
Я также нашел эту статью о , идентифицирующую последнее активное окно .