使用Python将击键发送到Windows中的游戏吗? [英] Use Python to send keystrokes to games in Windows?
问题描述
我一直在Windows环境中使用Python,并且编写了脚本来自动执行已知游戏中的某些任务。
该任务涉及大量使用鼠标和键盘输入。
I've been working with Python in a Windows environment and I wrote a script to automate some tasks in a known game. The task involves heavy use of both mouse and keyboard inputs.
上述脚本只有一个问题:无法将击键发送到应用程序。我尝试了至少3种不同的方法,下面将在其中进行一些发布(另请参见十分之一的类似问题/答案,无济于事)
Said script, however, has only one issue: it cannot send keystrokes to the application. I've tried at least 3 different methods that I shall post below and some variations (also read tenths of similar questions/answers, to no avail)
第一种,使用 win32api
模块:
f = 0x46 # VirtualKey Code of the letter "F", see http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
win32api.keybd_event(f,0,0,0) # holds the "F" key down
time.sleep(2) # waits 2 seconds
win32api.keybd_event(f,0,win32con.KEYEVENTF_KEYUP,0) # releases the key
没什么特别的,可以在任何文本编辑器,浏览器中完美地工作(键入 f) ...但是,如果我打开 Counter-Strike之类的游戏,则击键会丢失-因为什么也没有发生。另一方面,如果我打开Counter-Strike的控制台,则击键会获取(就像在记事本中一样)。
在另一个游戏《英雄联盟》中进行了测试,其行为完全相同。在实际的游戏中,没有检测到任何击键。但是,如果我打开聊天(仍然 ingame )并重新运行脚本,则该脚本将被聊天注册。
Nothing special about it, works perfectly (a "f" is typed) in any text editor, browser... However, if I open a game like, say, Counter-Strike, then the keystroke gets "lost" - as in, nothing occurs. On the other hand, if I open Counter-Strike's console, then the keystroke gets registered (like in notepad). Tested in another game, League of Legends, exactly the same behaviour. In the actual game, no keystroke is detected. If, however, I open the chat (still ingame) and re-run the script then it gets registered by the chat.
第二种方法:
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys("F")
与上述行为完全相同。
Exactly the same behaviour as above. Works fine in everything but the game, and in it only works in chats.
第三种方法(无论将其发布到另一个stackoverflow线程中的对象,都归功于它),更高级(调用 SendInput()
)和 ctypes
模块。从理论上讲,这三者中,最接近的是模拟实际的物理按键:
Third method (credit goes to whoever posted it in another stackoverflow thread), more advanced (calling SendInput()
) with the ctypes
module. In theory, of the three, this one is the closest to simulate an actual, physical key press:
SendInput = ctypes.windll.user32.SendInput
# C struct redefinitions
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
_fields_ = [("wVk", ctypes.c_ushort),
("wScan", ctypes.c_ushort),
("dwFlags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", PUL)]
class HardwareInput(ctypes.Structure):
_fields_ = [("uMsg", ctypes.c_ulong),
("wParamL", ctypes.c_short),
("wParamH", ctypes.c_ushort)]
class MouseInput(ctypes.Structure):
_fields_ = [("dx", ctypes.c_long),
("dy", ctypes.c_long),
("mouseData", ctypes.c_ulong),
("dwFlags", ctypes.c_ulong),
("time",ctypes.c_ulong),
("dwExtraInfo", PUL)]
class Input_I(ctypes.Union):
_fields_ = [("ki", KeyBdInput),
("mi", MouseInput),
("hi", HardwareInput)]
class Input(ctypes.Structure):
_fields_ = [("type", ctypes.c_ulong),
("ii", Input_I)]
# Actuals Functions
def PressKey(hexKeyCode):
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput( hexKeyCode, 0x48, 0, 0, ctypes.pointer(extra) )
x = Input( ctypes.c_ulong(1), ii_ )
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))
def ReleaseKey(hexKeyCode):
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput( hexKeyCode, 0x48, 0x0002, 0, ctypes.pointer(extra) )
x = Input( ctypes.c_ulong(1), ii_ )
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))
def KeyPress():
PressKey(0x46) # press F
time.sleep(.5)
ReleaseKey(0x46) #release F
...也不起作用。奇怪的是,它显示出与前三个相同的完全行为:可在任何文本编辑器/简单应用程序中使用,被游戏忽略或仅在游戏聊天区域中注册。
... it does not work either. Oddly enough, it displays the exact same behaviour as the previous three: works in any text editor/simple application, gets ignored by games or is only registered in the game chat section.
如果我猜我会说这些游戏以其他某种方式来获取其键盘事件,而我没有涉及这3种方法中的任何一种,因此将其忽略。
If I were to guess I'd say these games are getting their keyboard events in some other way that I've not covered with any of these 3 methods, thus ignoring these ones.
我将不胜感激。如果可能的话,结合在CS,LoL或类似游戏中工作的具体代码示例,让我有个起点。
I'd appreciate any help. If possible, with concrete examples of code working in either CS, LoL or similar games so that I have a starting point.
推荐答案
您的游戏可能使用DirectInput。使用这些方法之一尝试DirectInput扫描代码。快速浏览可以访问以下网站: http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
Your games probably use DirectInput. Try DirectInput scancodes with either of those methods. A quick googling gives this website: http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
这篇关于使用Python将击键发送到Windows中的游戏吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!