我想发送键盘输入到一个游戏运行在后台(游戏:骑士在线),但win32api。SendMessage, PostMessage方法不工作。我该怎么做呢
我试过这个链接中的代码
代码:
from time import sleep
import win32gui
import win32con
def callback(handle, param):
s = win32gui.GetClassName(handle)
try:
print(f'Sending key to {handle}, {s}')
win32gui.SendMessage(handle, 0x0102, 0x5A, 0)
sleep(.5)
except Exception:
print('Exception sending to {handle}, {s}')
window_id = win32gui.FindWindow(None, "Knight OnLine Client")
win32gui.EnumChildWindows(window_id, callback, 0)
输出:
Sending key to 23004754, Edit
Sending key to 1639850, Edit
Sending key to 10421696, Edit
输入在游戏中不起作用
为什么不工作
从按下一个键到一个应用程序,在整个过程中有很多次停止。应用程序可以选择在管道的哪个位置接收键盘输入。
发送的是0x0102
,也就是WM_CHAR
。这是你能走到的最远的管道。很可能是游戏提前点击了管道。
-
当你按下一个物理键时,键盘驱动程序在输入队列中放置一个输入事件。
-
当操作系统从输入队列中取出该事件时,它将
WM_KEYDOWN
消息放置在拥有输入焦点窗口的线程的消息队列中。 -
当应用程序的GUI线程从队列中提取消息时,它可以选择通过一个名为TranslateMessage的API将其路由,该API监视低级键盘消息,如
WM_KEYDOWN
和WM_KEYUP
。 -
TranslateMessage合成
WM_CHAR
(和/或WM_UNICHAR
)并将它们发送到窗口(就在允许键盘消息被处理之前)。这些消息告诉程序用户输入了一个字符(例如,一个大写的带有重音的E),而这只能通过一系列的键盘消息来完成。
同时,部分系统在不同时间点跟踪整个键盘的状态。
其中之一是异步键盘状态,它监视那个输入队列以便它知道现在键盘上发生了什么。游戏可以使用GetAsyncKeyState(也许还有旧的DirectInput API)来查询这个。快速的电子游戏可能依赖于此(在检查它们是否"活跃"之后)。窗口)。还有一个同步键盘状态,当线程从它们的队列中提取键盘消息时,跟踪每个GUI线程。想象一下,如果一个线程落后了,并且大量的键盘消息仍然在排队。同步键盘状态(来自GetKeyState或GetKeyboardState)将指示最近处理的窗口消息发布时的键盘状态,这可能与已经反映队列中所有消息的异步状态不同。
字符输入消息,如WM_CHAR
,对于文本编辑器、文字处理器等非常有用。但是,即使是他们也必须更早地点击管道,以便进行Page Up和Page Down等按键。
许多应用程序主要使用WM_KEYDOWN
和WM_KEYUP
消息。
你可以试试
最简单的尝试是发送(或者更好的是发布)WM_KEYDOWN
和WM_KEYUP
消息而不是WM_CHAR
。那不能保证成功。
Windows有SendInput API用于将事件放入输入队列(键盘驱动程序的方式)。我不知道是否有Python库涵盖了这个。即使有,它也不太可能有帮助,因为系统不会将你注入的键盘输入事件发送到后台窗口。