我有下面的脚本,它每xx秒发送一个键盘键(默认情况下是F15),灵感来自于在线找到的一些代码
我想删除与鼠标事件相关的类型和联合,但无法使其工作。尤其是,我不知道如何删除类MOUSEINPUT
和类型的联合_INPUTunion
(删除它们将停止发送键盘键)。在
关于如何将脚本缩减到最小值(即只保留与键盘相关的代码)的建议吗?在
下面的代码将发送键“C”,以便能够进行调试。在
#!/python
import ctypes
import sys
import time
LONG = ctypes.c_long
DWORD = ctypes.c_ulong
ULONG_PTR = ctypes.POINTER(DWORD)
WORD = ctypes.c_ushort
class MOUSEINPUT(ctypes.Structure):
_fields_ = (
('dx', LONG), ('dy', LONG), ('mouseData', DWORD),
('dwFlags', DWORD), ('time', DWORD),
('dwExtraInfo', ULONG_PTR)
)
class KEYBDINPUT(ctypes.Structure):
_fields_ = (
('wVk', WORD), ('wScan', WORD),
('dwFlags', DWORD), ('time', DWORD),
('dwExtraInfo', ULONG_PTR)
)
class _INPUTunion(ctypes.Union):
_fields_ = (('mi', MOUSEINPUT), ('ki', KEYBDINPUT))
class INPUT(ctypes.Structure):
_fields_ = (('type', DWORD), ('union', _INPUTunion))
def SendInput(*inputs):
print(inputs[0].union.mi)
nInputs = len(inputs)
LPINPUT = INPUT * nInputs
pInputs = LPINPUT(*inputs)
cbSize = ctypes.c_int(ctypes.sizeof(INPUT))
return ctypes.windll.user32.SendInput(nInputs, pInputs, cbSize)
INPUT_keyboard = 1
def Input(structure):
if isinstance(structure, KEYBDINPUT):
return INPUT(INPUT_KEYBOARD, _INPUTunion(ki=structure))
else:
raise TypeError('Cannot create INPUT structure (keyboard)!')
def Keyboard(code, flags=0):
return Input(KEYBDINPUT(code, code, flags, 0, None))
if __name__ == '__main__':
nb_cycles = 10
while nb_cycles != 0:
time.sleep(2) # 3 seconds
# Key "c" for debug, but ideally use 0x7E for "F15"
SendInput(Keyboard(ord("C")))
sys.stdout.write(".")
nb_cycles -= 1
像这样任务的“圣经”:[Python 3]: ctypes - A foreign function library for Python。
我修改了你的代码(发现了一堆问题,其中一些是关键问题)。在
代码.py:
注意事项:
最初,我定义了只有1st2个成员的INPUT结构,但是查看了[MS.Docs]: INPUT structure,并注意到该联合包括:
做了一些测试并注意到MOUSEINPUT的大小在3struct中是最大的,而且它的8字节大于KEYBDINPUT(对于两个32位和64位),所以我添加了(dummy)(padding)成员。通常,当接收到一个type设置为INPUT峈KEYBOARD的INPUT结构时,我不会期望SendInput超过KEYBDINPUT大小,但是INPUT大小是[MS.Docs]: SendInput function的cbSizearg
def SendInput(*inputs):
-在Python中,*之前,参数所做的事情与C中完全不同。检查[SO]: Expanding tuples into arguments(我没有找到官方文件)。我修改了函数,使它只发送一个这样的结构始终为通过ctypes调用的函数定义argtypes(和restype)。否则它们将默认为
ctypes.c_int
(这可能会导致一些严重的错误,特别是在64位:[SO]: Python ctypes cdll.LoadLibrary, instantiate an object, execute its method, private variable address truncated (@CristiFati's answer))将
ctypes.wintypes
用于Win的特定类型,不要重新设计轮子。更不用说有时会出现不匹配(我最近看到的一个例子是ctypes.c_bool
与wintypes.BOOL
)我将您的函数重命名为[Python]: PEP 8 Style Guide for Python Code兼容。我还删除了一些不再需要的文件
其他不值得单独提及的小变化
至于测试,我使用了一个记事本窗口(或任何其他对用户输入“敏感”的窗口):
time.sleep(2)
),只是为了给用户时间切换窗口),然后注意到cs“神奇地”出现了。。。或者只需从控制台启动脚本,按Ctrl,注意它被取消了。在
相关问题 更多 >
编程相关推荐