我一直在Windows环境中使用Python,我编写了一个脚本来自动执行已知游戏中的某些任务.该任务涉及大量使用鼠标和键盘输入.
但是,所述脚本只有一个问题:它无法向应用程序发送击键.我尝试了至少3种不同的方法,我将在下面发布和一些变化(也读取类似问题/答案的十分之一,无济于事)
第一个,使用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
Run Code Online (Sandbox Code Playgroud)
没有什么特别之处,在任何文本编辑器,浏览器中都可以完美地工作(键入"f")......但是,如果我打开像反恐精英这样的游戏,那么击键就会"丢失" - 就像在,什么都没发生 另一方面,如果我打开Counter-Strike的控制台,那么按键就会被注册(就像在记事本中一样).在另一款游戏"英雄联盟"中进行了测试,行为完全相同.在实际游戏中,没有检测到击键.但是,如果我打开聊天(仍然是游戏)并重新运行脚本,那么聊天就会注册.
在第二种方法上:
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys("F")
Run Code Online (Sandbox Code Playgroud)
与上面的行为完全相同.除了游戏之外的所有东西都可以正常工作,并且它只适用于聊天.
第三种方法(功劳归于谁在另一个stackoverflow线程中发布),更高级(调用SendInput()
)与ctypes
模块.理论上,在这三者中,这一个最接近于模拟实际的物理按键:
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_ …
Run Code Online (Sandbox Code Playgroud) 我创建了一个简单的 Python 脚本,只要特定程序运行,它就会被激活。该程序将信息发送到屏幕,脚本需要抓取和分析这些信息。
脚本的部分逻辑可以表示如下:
while a certain condition is met:
function to continuously check pixel information on a fixed area of the screen()
if pixel data (e.g. RGB) changes:
do something
else:
continues to check
Run Code Online (Sandbox Code Playgroud)
我已经找到了可以做到这一点的东西,但没有我想要的那么快。这是使用具有任意值的 Python 成像库 (PIL) 的解决方案:
import ImageGrab
box = (0,0,100,100) # 100x100 screen area to capture (0x0 is top left corner)
pixel = (60,20) #target pixel coordenates (must be within the box's boundaries)
im = ImageGrab.grab(box) #grabs the image area (aka printscreen) -> source of …
Run Code Online (Sandbox Code Playgroud)