发送键盘输入到后台运行的游戏



我想发送键盘输入到一个游戏运行在后台(游戏:骑士在线),但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_KEYDOWNWM_KEYUP

  • TranslateMessage合成WM_CHAR(和/或WM_UNICHAR)并将它们发送到窗口(就在允许键盘消息被处理之前)。这些消息告诉程序用户输入了一个字符(例如,一个大写的带有重音的E),而这只能通过一系列的键盘消息来完成。

同时,部分系统在不同时间点跟踪整个键盘的状态。

其中之一是异步键盘状态,它监视那个输入队列以便它知道现在键盘上发生了什么。游戏可以使用GetAsyncKeyState(也许还有旧的DirectInput API)来查询这个。快速的电子游戏可能依赖于此(在检查它们是否"活跃"之后)。窗口)。还有一个同步键盘状态,当线程从它们的队列中提取键盘消息时,跟踪每个GUI线程。想象一下,如果一个线程落后了,并且大量的键盘消息仍然在排队。同步键盘状态(来自GetKeyState或GetKeyboardState)将指示最近处理的窗口消息发布时的键盘状态,这可能与已经反映队列中所有消息的异步状态不同。

字符输入消息,如WM_CHAR,对于文本编辑器、文字处理器等非常有用。但是,即使是他们也必须更早地点击管道,以便进行Page Up和Page Down等按键。

许多应用程序主要使用WM_KEYDOWNWM_KEYUP消息。

快速电子游戏可能使用异步键盘状态或同步键盘状态。当它们在后台时,它们可能故意不处理任何键盘输入。

你可以试试

最简单的尝试是发送(或者更好的是发布)WM_KEYDOWNWM_KEYUP消息而不是WM_CHAR。那不能保证成功。

Windows有SendInput API用于将事件放入输入队列(键盘驱动程序的方式)。我不知道是否有Python库涵盖了这个。即使有,它也不太可能有帮助,因为系统不会将你注入的键盘输入事件发送到后台窗口。

最新更新