Emulate Pen using InjectSyntheticPointerInput function in Windows 10 using Python

0

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)
python
windows-10
touch
ctypes
pen
asked on Stack Overflow Oct 4, 2019 by Adil Malik

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0