我试图让user32.dll中的SendInput函数在python中使用ctypes.I am a noob but from what I read from the docs you have to create the structs the function requires in python and then pass it to the function.
import ctypes
import keyboard
from ctypes import *
lib = windll.user32
KEYEVENTF_SCANCODE = 0x8
KEYEVENTF_KEYUP = 0x2
SPACEBAR = 57 # 0x39
INPUT_KEYBOARD = 1
class KEYBDINPUT(Structure):
_fields_ = [('wVk' , c_ushort) , ('wScan' , c_ushort)
, ('dwFlags' , c_ulong) , ('time' , c_ulong) , ('dwExtraInfo' , c_ulong)]
class INPUT(Structure):
_fields_ = [('type' , c_ulong) ,('ki' , KEYBDINPUT)]
lib.SendInput.restype = c_uint
lib.SendInput.argtypes = [c_uint , INPUT , c_int]
keybdinput_obj = KEYBDINPUT(0 , SPACEBAR , KEYEVENTF_SCANCODE , 0 , 0)
input_obj = INPUT(INPUT_KEYBOARD , keybdinput_obj)
keyboard.wait('u')
lib.SendInput(1 , byref(input_obj) , sizeof(INPUT))
keybdinput_obj = KEYBDINPUT(0 , SPACEBAR , KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP , 0 , 0)
input_obj = INPUT(INPUT_KEYBOARD , keybdinput_obj)
lib.SendInput(1 , byref(input_obj) , sizeof(INPUT))
在microsoft的文档中,我指导自己从INPUT结构有一个工会,但我想,如果我只需要KEYBDINPUT,那么它是同样的事情,如果我有一个工会。
https:/docs.microsoft.comen-uswindowswin32apiwinuserns-winuser-input。
https:/docs.microsoft.comen-uswindowswin32apiwinuserns-winuser-keybdinput。
https:/docs.microsoft.comen-uswindowswin32apiwinusernf-winuser-sendinput。
我几乎被卡住了,因为我看不出这里出了什么问题,所以我请求帮助.程序应该在我按下键盘上的'u'后发送一个空格(这是为了调试目的),我这样做是因为我想把它作为一个扫描码发送,而不是一个虚拟的按键。
所以,如果有另一种方式在python中,你可以发送扫描码,这将工作,我将非常感谢它。
定义整个联盟,或者至少是MOUSEINPUT,它是联盟中最大的成员。你可以通过print(sizeof(INPUT))来测试你的定义是否正确,它应该与打印C程序中INPUT结构的大小一致。我得到的32位的大小是28,64位C结构的大小是40。
另外,你的SendInput的第二个参数是POINTER(INPUT),而不是INPUT,而且ULONG_PTR不一定是 c_ulong
因为它取决于运行32位或64位Python。
下面是一个经过测试的例子。
import ctypes
from ctypes import *
from ctypes import wintypes as w
KEYEVENTF_SCANCODE = 0x8
KEYEVENTF_UNICODE = 0x4
KEYEVENTF_KEYUP = 0x2
SPACE = 0x39
INPUT_KEYBOARD = 1
# not defined by wintypes
ULONG_PTR = c_ulong if sizeof(c_void_p) == 4 else c_ulonglong
class KEYBDINPUT(Structure):
_fields_ = [('wVk' ,w.WORD),
('wScan',w.WORD),
('dwFlags',w.DWORD),
('time',w.DWORD),
('dwExtraInfo',ULONG_PTR)]
class MOUSEINPUT(Structure):
_fields_ = [('dx' ,w.LONG),
('dy',w.LONG),
('mouseData',w.DWORD),
('dwFlags',w.DWORD),
('time',w.DWORD),
('dwExtraInfo',ULONG_PTR)]
class HARDWAREINPUT(Structure):
_fields_ = [('uMsg' ,w.DWORD),
('wParamL',w.WORD),
('wParamH',w.WORD)]
class DUMMYUNIONNAME(Union):
_fields_ = [('mi',MOUSEINPUT),
('ki',KEYBDINPUT),
('hi',HARDWAREINPUT)]
class INPUT(Structure):
_anonymous_ = ['u']
_fields_ = [('type',w.DWORD),
('u',DUMMYUNIONNAME)]
print(sizeof(INPUT))
lib = WinDLL('user32')
lib.SendInput.argtypes = w.UINT,POINTER(INPUT),c_int
lib.SendInput.restype = w.UINT
def send_scancode(code):
i = INPUT()
i.type = INPUT_KEYBOARD
i.ki = KEYBDINPUT(0,code,KEYEVENTF_SCANCODE,0,0)
lib.SendInput(1,byref(i),sizeof(INPUT))
i.ki.dwFlags |= KEYEVENTF_KEYUP
lib.SendInput(1,byref(i),sizeof(INPUT))
def send_unicode(s):
i = INPUT()
i.type = INPUT_KEYBOARD
for c in s:
i.ki = KEYBDINPUT(0,ord(c),KEYEVENTF_UNICODE,0,0)
lib.SendInput(1,byref(i),sizeof(INPUT))
i.ki.dwFlags |= KEYEVENTF_KEYUP
lib.SendInput(1,byref(i),sizeof(INPUT))
send_scancode(SPACE)
send_unicode('The quick brown fox jumped over the lazy dog')
运行64位Python 3.6的终端上的输出。
C:\>example
40
C:\> The quick brown fox jumped over the lazy dog