So I am trying to emulate a pen input event using the windows API using ctypes in Python. In particular, I am trying to use the function InjectSyntheticPointerInput
.
I found this old SE post, asking something similar but with Touch. The code posted in the answer still works on Windows 10 but only supports touch. Since then the API has been updated to support more generic inputs such as pen and I am trying to adapt that code to support Pen.
To support Pen, it seems a few new Structs (and flags) had to be created namely POINTER_PEN_INFO
and POINTER_TYPE_INFO
. Lastly, injection is initiated using CreateSyntheticPointerDevice
and carried out using InjectSyntheticPointerInput
I made the changes, adhering to the new API but the code just does not work. It does not give me any errors, rather says it was successful despite no Pen input being visible.
I suspect the error might have to do with the fact that InjectSyntheticPointerInput
expects a handle returned by CreateSyntheticPointerDevice
, which I am not sure I am doing correctly in Python.
Here is my code:
from ctypes import *
from ctypes.wintypes import *
#Constants
#For touchMask
TOUCH_MASK_NONE= 0x00000000 #Default
TOUCH_MASK_CONTACTAREA= 0x00000001
TOUCH_MASK_ORIENTATION= 0x00000002
TOUCH_MASK_PRESSURE= 0x00000004
TOUCH_MASK_ALL= 0x00000007
#For touchFlag
TOUCH_FLAG_NONE= 0x00000000
#For pointerType
PT_POINTER= 0x00000001#All
PT_TOUCH= 0x00000002
PT_PEN= 0x00000003
PT_MOUSE= 0x00000004
#For pointerFlags
POINTER_FLAG_NONE= 0x00000000#Default
POINTER_FLAG_NEW= 0x00000001
POINTER_FLAG_INRANGE= 0x00000002
POINTER_FLAG_INCONTACT= 0x00000004
POINTER_FLAG_FIRSTBUTTON= 0x00000010
POINTER_FLAG_SECONDBUTTON=0x00000020
POINTER_FLAG_THIRDBUTTON= 0x00000040
POINTER_FLAG_FOURTHBUTTON=0x00000080
POINTER_FLAG_FIFTHBUTTON= 0x00000100
POINTER_FLAG_PRIMARY= 0x00002000
POINTER_FLAG_CONFIDENCE= 0x00004000
POINTER_FLAG_CANCELED= 0x00008000
POINTER_FLAG_DOWN= 0x00010000
POINTER_FLAG_UPDATE= 0x00020000
POINTER_FLAG_UP= 0x00040000
POINTER_FLAG_WHEEL= 0x00080000
POINTER_FLAG_HWHEEL= 0x00100000
POINTER_FLAG_CAPTURECHANGED=0x00200000
#For Synthetic input init
POINTER_FEEDBACK_DEFAULT= 0x00000001
POINTER_FEEDBACK_INDIRECT=0x00000002
POINTER_FEEDBACK_NONE=0x00000003
#Pen flags
PEN_FLAG_NONE = 0x00000000
PEN_FLAG_BARREL = 0x00000001
PEN_FLAG_INVERTED = 0x00000002
PEN_FLAG_ERASER = 0x00000004
#Pen masks
PEN_MASK_NONE = 0x00000000
PEN_MASK_PRESSURE = 0x00000001
PEN_MASK_ROTATION = 0x00000002
PEN_MASK_TILT_X = 0x00000004
PEN_MASK_TILT_Y = 0x00000008
#Structs Needed
class POINTER_INFO(Structure):
_fields_=[("pointerType",c_uint32),
("pointerId",c_uint32),
("frameId",c_uint32),
("pointerFlags",c_int),
("sourceDevice",HANDLE),
("hwndTarget",HWND),
("ptPixelLocation",POINT),
("ptHimetricLocation",POINT),
("ptPixelLocationRaw",POINT),
("ptHimetricLocationRaw",POINT),
("dwTime",DWORD),
("historyCount",c_uint32),
("inputData",c_int32),
("dwKeyStates",DWORD),
("PerformanceCount",c_uint64),
("ButtonChangeType",c_int)
]
class POINTER_TOUCH_INFO(Structure):
_fields_=[("pointerInfo",POINTER_INFO),
("touchFlags",c_int),
("touchMask",c_int),
("rcContact", RECT),
("rcContactRaw",RECT),
("orientation", c_uint32),
("pressure", c_uint32)]
class POINTER_PEN_INFO(Structure):
_fields_=[("pointerInfo",POINTER_INFO),
("penFlags",c_int),
("penMask",c_int),
("pressure",c_uint32),
("rotation", c_uint32),
("tiltX", c_int32),
("tiltY", c_int32)]
class PEN_TOUCH_UNION(Union):
_fields_=[("touchInfo",POINTER_TOUCH_INFO),("penInfo",POINTER_PEN_INFO )]
class POINTER_TYPE_INFO(Structure):
_fields_=[("type",c_uint32),
("DUMMYUNIONNAME",PEN_TOUCH_UNION),
]
# #Initialize Pointer and Touch info
pointerInfo_pen=POINTER_INFO(pointerType=PT_PEN,
pointerId=0,
ptPixelLocation=POINT(950,540))
pointerInfo_touch=POINTER_INFO(pointerType=PT_TOUCH,
pointerId=0,
ptPixelLocation=POINT(950,540))
touchInfo=POINTER_TOUCH_INFO(pointerInfo=pointerInfo_touch,
touchFlags=TOUCH_FLAG_NONE,
touchMask=TOUCH_MASK_ALL,
rcContact=RECT(pointerInfo_touch.ptPixelLocation.x-5,
pointerInfo_touch.ptPixelLocation.y-5,
pointerInfo_touch.ptPixelLocation.x+5,
pointerInfo_touch.ptPixelLocation.y+5),
orientation=90,
pressure=1000)
penInfo=POINTER_PEN_INFO(pointerInfo=pointerInfo_pen,penFlags=PEN_FLAG_NONE,penMask=PEN_MASK_PRESSURE,pressure=1000, rotation=0,tiltX=0,tiltY=0)
dmyUnion = PEN_TOUCH_UNION ( touchInfo = touchInfo,penInfo = penInfo)
pointerTypeInfo = POINTER_TYPE_INFO(type = PT_PEN, DUMMYUNIONNAME = dmyUnion)
def pen(x,y,pressure,earse):
if(earse == 1):
penInfo.penFlags = PEN_FLAG_ERASER
else:
penInfo.penFlags = PEN_FLAG_NONE
penInfo.pointerInfo.ptPixelLocation.x=x
penInfo.pointerInfo.ptPixelLocation.y=y
penInfo.pressure = pressure
penInfo.penMask = PEN_MASK_PRESSURE
# #Press Down
penInfo.pointerInfo.pointerFlags=(POINTER_FLAG_DOWN|
POINTER_FLAG_INRANGE|
POINTER_FLAG_INCONTACT)
# #Initialize Touch Injection
dev = windll.user32.CreateSyntheticPointerDevice(PT_PEN,1,POINTER_FEEDBACK_INDIRECT)
if( dev!=0):
print "Initialized Successfully!"
if (windll.user32.InjectSyntheticPointerInput (dev , byref(pointerTypeInfo),1)==0):
print "Failed with Error: "+ FormatError()
else:
print "Pen Down Succeeded!"
# #Ex:
pen(950,270,1000,0)
User contributions licensed under CC BY-SA 3.0