我会尝试发布一个最小的工作示例,但不幸的是这个问题只需要很多部分,所以我已尽我所能将其剥离。
首先,我使用一个简单的脚本来通过函数调用模拟按键。这是调整自here https://stackoverflow.com/a/13290031/2924421.
import ctypes
SendInput = ctypes.windll.user32.SendInput
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)]
def getKeyCode(unicodeKey):
k = unicodeKey
curKeyCode = 0
if k == "up": curKeyCode = 0x26
elif k == "down": curKeyCode = 0x28
elif k == "left": curKeyCode = 0x25
elif k == "right": curKeyCode = 0x27
elif k == "home": curKeyCode = 0x24
elif k == "end": curKeyCode = 0x23
elif k == "insert": curKeyCode = 0x2D
elif k == "pgup": curKeyCode = 0x21
elif k == "pgdn": curKeyCode = 0x22
elif k == "delete": curKeyCode = 0x2E
elif k == "\n": curKeyCode = 0x0D
if curKeyCode == 0:
return 0, int(unicodeKey.encode("hex"), 16), 0x0004
else:
return curKeyCode, 0, 0
def PressKey(unicodeKey):
key, unikey, uniflag = getKeyCode(unicodeKey)
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput( key, unikey, uniflag, 0, ctypes.pointer(extra) )
x = Input( ctypes.c_ulong(1), ii_ )
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))
def ReleaseKey(unicodeKey):
key, unikey, uniflag = getKeyCode(unicodeKey)
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput( key, unikey, uniflag + 0x0002, 0, ctypes.pointer(extra) )
x = Input( ctypes.c_ulong(1), ii_ )
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))
我将其存储在名为 keyPress.py 的文件中。
使用这个,我想制作一个简单的程序,可以检测用户在 python shell 中输入的内容。我的想法是,我将使用 msvcrt.getch() 来按下按键,然后使用上面的脚本使其看起来仍然被按下(并且在某种意义上“回显”按键”)
这是代码:
import keyPress
import msvcrt
import threading
def getKey():
k = msvcrt.getch()
# Escaped Key: 224 is on the keyboard, 0 is on the numpad
if int(k.encode("hex"), 16) == 224 or int(k.encode("hex"), 16) == 0:
k = msvcrt.getch()
if k == "H": k = "up"
elif k == "P": k = "down"
elif k == "K": k = "left"
elif k == "M": k = "right"
elif k == "G": k = "home"
elif k == "O": k = "end"
elif k == "R": k = "insert"
elif k == "I": k = "pgup"
elif k == "Q": k = "pgdn"
elif k == "S": k = "delete"
# Fix weird linebreak
if k == "\r":
k = "\n"
return k
def actualGetKeys():
while True:
k = getKey()
keyPress.PressKey(k)
keyPress.ReleaseKey(k)
def getKeys():
p = threading.Thread(target=actualGetKeys)
p.daemon = True
p.start()
我将其存储在名为 keyGet.py 的文件中。
这一切都工作得很好,除了每当用户按下 Enter 时,第一个键不会显示在屏幕上。控制台仍然知道您输入了它,只是没有显示在那里。像这样的东西:
怎么了?我已经尝试了很多很多事情,但我似乎无法改变这种行为。
我现在能够使其基本上正常工作,因为它可以在脚本运行时异步捕获按键输入,并使用您在命令提示符中键入的每个命令的文本执行(因此您可以将这些存储到数组中) )。我遇到的唯一问题是这样的:
我知道这是因为基本上必须让机器人在输入后重新输入输入,我只是想知道是否有办法做到这一点,以防止机器人在输入时实际显示输入,因此它会起作用正如用户所期望的那样。