使用Python将击键发送到Windows中的游戏吗? [英] Use Python to send keystrokes to games in Windows?

查看:177
本文介绍了使用Python将击键发送到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆