Create ctypes array to send extended scancodes with sendinput

Viewed 114

I'd like to do the same as this : How to use extended scancodes in SendInput in Python, using ctypes.

I can send regular scancodes with Sendinput, but I can't seem to send arrays of Input, thus failing to send extended scancodes. So far, here's what I'm doing. Can anyone point me in the right direction ? This does nothing at all, I'd like it to press Right CTRL.

import ctypes
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 InputI(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                ("mi", MouseInput),
                ("hi", HardwareInput)]


class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", InputI)]


Inputx = Input * 2  # to create an array of Input, as mentionned in ctypes documentation


def press(scan_code):
    extra1 = ctypes.c_ulong(0)
    ii1_ = InputI()
    ii1_.ki = KeyBdInput(0, 0xE0, 0x0008, 0, ctypes.pointer(extra1))
    x1 = Input(ctypes.c_ulong(1), ii1_)
    extra2 = ctypes.c_ulong(0)
    ii_2 = InputI()
    ii_2.ki = KeyBdInput(1, scan_code, 0x0008, 0, ctypes.pointer(extra2))
    x2 = Input(ctypes.c_ulong(1), ii_2)
    x = Inputx(x1, x2)
    ctypes.windll.user32.SendInput(2, ctypes.pointer(x), ctypes.sizeof(x))

press(0x1D)

1 Answers

I just read the SendInput documentation on MSDN and found the solution :

Right Control has a scan code of 0xE0 0x1D, so the scan code to use in KeyBdInput must be 0x1D, and to specify it is prefixed by 0xE0, the flag parameter must have its bit #0 set to 1, leading to this :

def press_ext(scan_code):
    extra = ctypes.c_ulong(0)
    ii_ = InputI()
    ii_.ki = KeyBdInput(0, scan_code, 0x0008 | 0x0001, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


def release_ext(scan_code):
    extra = ctypes.c_ulong(0)
    ii_ = InputI()
    ii_.ki = KeyBdInput(0, scan_code, 0x0008 | 0x0002 | 0x0001, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


press_ext(0x1D) # press RIGHT CTRL

release_ext(0x1D) #release it
Related