import logging
# Information categories
[docs]
WTI_DEFCONTEXT = 3
# Hardware capabilities
[docs]
HWC_INTEGRATED = 0x0001
[docs]
HWC_PHYSID_CURSORS = 0x0008
# Unit specifiers
# Cursor capabilities
# System button assignment values
# for Pen Windows
# Context option values
[docs]
CXO_CSRMESSAGES = 0x0008
# Context status values
# Context lock values
[docs]
CXL_SENSITIVITY = 0x0004
# WTPKT bits
[docs]
PK_CONTEXT = 0x0001 # reporting context
[docs]
PK_STATUS = 0x0002 # status bits
[docs]
PK_TIME = 0x0004 # time stamp
[docs]
PK_CHANGED = 0x0008 # change bit vector
[docs]
PK_SERIAL_NUMBER = 0x0010 # packet serial number
[docs]
PK_CURSOR = 0x0020 # reporting cursor
[docs]
PK_NORMAL_PRESSURE = 0x0400 # normal or tip pressure
[docs]
PK_TANGENT_PRESSURE = 0x0800 # tangential or barrel pressure
[docs]
PK_ORIENTATION = 0x1000 # orientation info: tilts */
[docs]
PK_ROTATION = 0x2000 # rotation info; 1.1
# Packet status values
# Relative buttons
[docs]
class Wintab():
def __init__(self, hwnd):
import ctypes
from ctypes import wintypes, c_char, c_int, POINTER
from ctypes.wintypes import HWND, UINT, DWORD, LONG, HANDLE, BOOL, LPVOID
HCTX = HANDLE
WTPKT = DWORD
FIX32 = DWORD
class LOGCONTEXTA(ctypes.Structure):
_fields_ = [
('lcName', 40*c_char),
('lcOptions', UINT),
('lcStatus', UINT),
('lcLocks', UINT),
('lcMsgBase', UINT),
('lcDevice', UINT),
('lcPktRate', UINT),
('lcPktData', WTPKT),
('lcPktMode', WTPKT),
('lcMoveMask', WTPKT),
('lcBtnDnMask', DWORD),
('lcBtnUpMask', DWORD),
('lcInOrgX', LONG),
('lcInOrgY', LONG),
('lcInOrgZ', LONG),
('lcInExtX', LONG),
('lcInExtY', LONG),
('lcInExtZ', LONG),
('lcOutOrgX', LONG),
('lcOutOrgY', LONG),
('lcOutOrgZ', LONG),
('lcOutExtX', LONG),
('lcOutExtY', LONG),
('lcOutExtZ', LONG),
('lcSensX', FIX32),
('lcSensY', FIX32),
('lcSensZ', FIX32),
('lcSysMode', BOOL),
('lcSysOrgX', c_int),
('lcSysOrgY', c_int),
('lcSysExtX', c_int),
('lcSysExtY', c_int),
('lcSysSensX', FIX32),
('lcSysSensY', FIX32)
]
# PK_CONTEXT = 0x0001 # reporting context */
# PK_STATUS = 0x0002 # status bits */
# PK_TIME = 0x0004 # time stamp */
# PK_CHANGED = 0x0008 # change bit vector */
# PK_SERIAL_NUMBER = 0x0010 # packet serial number */
# PK_CURSOR = 0x0020 # reporting cursor */
# PK_BUTTONS = 0x0040 # button information */
# PK_X = 0x0080 # x axis */
# PK_Y = 0x0100 # y axis */
# PK_Z = 0x0200 # z axis */
# PK_NORMAL_PRESSURE = 0x0400 # normal or tip pressure */
# PK_TANGENT_PRESSURE = 0x0800 # tangential or barrel pressure */
# PK_ORIENTATION = 0x1000 # orientation info: tilts */
# PK_ROTATION = 0x2000 # rotation info; 1.1 */
lcPktData = (PK_CHANGED | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE)
lcPktMode = 0
class PACKET(ctypes.Structure):
_fields_ = [
('pkChanged', WTPKT),
('pkCursor', UINT),
('pkButtons', DWORD),
('pkX', LONG),
('pkY', LONG),
('pkNormalPressure', UINT)
]
# WTI_DEFCONTEXT = 3
# CXO_SYSTEM = 0x0001
# CXO_PEN = 0x0002
# CXO_MESSAGES = 0x0004
# CXO_MARGIN = 0x8000
try:
self.dll = ctypes.WinDLL("wintab32.dll")
self._wintab = True
self.dll.WTInfoA.argtypes = [UINT, UINT, POINTER(LOGCONTEXTA)]
self.dll.WTInfoA.restype = UINT
self.dll.WTOpenA.argtypes = [HWND, POINTER(LOGCONTEXTA), BOOL]
self.dll.WTOpenA.restype = HCTX
self.dll.WTClose.argtypes = [HCTX]
self.dll.WTClose.restype = BOOL
self.dll.WTPacketsGet.argtypes = [HCTX, c_int, POINTER(PACKET)]
self.dll.WTPacketsGet.restype = c_int
self.dll.WTPacket.argtypes = [HCTX, UINT, POINTER(PACKET)]
self.dll.WTPacket.restype = BOOL
self.lc = LOGCONTEXTA()
rslt = self.dll.WTInfoA(WTI_DEFCONTEXT, 0, self.lc)
# logging.info(self.lc.lcOptions)
self.lc.lcPktData = lcPktData
self.lc.lcPktMode = lcPktMode
self.lc.lcOptions = (CXO_SYSTEM | CXO_MESSAGES)
# logging.info(self.lc.lcOptions)
self.hctx = self.dll.WTOpenA(HWND(hwnd), self.lc, 1)
self.buf = (1*PACKET)()
except:
self._wintab = False
[docs]
def get_xypressure(self):
if self._wintab:
n = self.dll.WTPacketsGet(self.hctx, 1, self.buf)
if n > 0:
return self.buf[0].pkX, self.buf[0].pkY, self.buf[0].pkNormalPressure
else:
return None, None, None
else:
return None, None, None
if __name__ == "__main__":
while True:
x, y, p = loc.get_xypressure()
if x is not None:
print(x, y, p)
# else:
# print("No data")