Tablet.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. unit Tablet;
  2. {$IFDEF FPC}
  3. {$MODE Delphi}
  4. {$ENDIF}
  5. {********************************************}
  6. { This unit is a part of TTablet component }
  7. { Copyright (C) 2001-2002 Mattias Andersson }
  8. { See COPYING.txt for license information }
  9. { Last modified: 2003-10-25; version 1.24 }
  10. {********************************************}
  11. { Modified by Nelson Chu in 2013 to work }
  12. { with Lazarus. }
  13. {********************************************}
  14. interface
  15. uses
  16. Windows, SysUtils, Messages, Classes, WintabConsts, Win32Int;
  17. type
  18. HCtx = type Integer;
  19. TFixed = type Integer;
  20. TWTPkt = type Integer;
  21. PAxis = ^TAxis;
  22. TAxis = record
  23. Min: Integer;
  24. Max: Integer;
  25. Units: Cardinal;
  26. Resolution: TFixed;
  27. end;
  28. POrientation = ^TOrientation;
  29. TOrientation = record
  30. Azimuth: Integer;
  31. Altitude: Integer;
  32. Twist: Integer;
  33. end;
  34. PRotation = ^TRotation;
  35. TRotation = record
  36. Pitch: Integer;
  37. Roll: Integer;
  38. Yaw: Integer;
  39. end;
  40. PLogContext = ^TLogContext;
  41. TLogContext = record
  42. Name: string[39];
  43. Options: Cardinal;
  44. Status: Cardinal;
  45. Locks: Cardinal;
  46. MsgBase: Cardinal;
  47. Device: Cardinal;
  48. PktRate: Cardinal;
  49. PktData: TWTPkt;
  50. PktMode: TWTPkt;
  51. MoveMask: TWTPkt;
  52. BtnDnMask: Integer;
  53. BtnUpMask: Integer;
  54. InOrgX: Integer;
  55. InOrgY: Integer;
  56. InOrgZ: Integer;
  57. InExtX: Integer;
  58. InExtY: Integer;
  59. InExtZ: Integer;
  60. OutOrgX: Integer;
  61. OutOrgY: Integer;
  62. OutOrgZ: Integer;
  63. OutExtX: Integer;
  64. OutExtY: Integer;
  65. OutExtZ: Integer;
  66. SensX: TFixed;
  67. SensY: TFixed;
  68. SensZ: TFixed;
  69. SysMode: Boolean;
  70. SysOrgX: Integer;
  71. SysOrgY: Integer;
  72. SysExtX: Integer;
  73. SysExtY: Integer;
  74. SysSensX: TFixed;
  75. SysSensY: TFixed;
  76. end;
  77. TPacketEvent = procedure(Sender: TObject; PacketNumber, ContextHandle: HCtx;
  78. pPacket: Pointer) of object;
  79. TProximityEvent = procedure(Sender: TObject; ContextHandle: HCtx;
  80. Entering: Boolean) of object;
  81. TInfoChangedEvent = procedure(Sender: TObject; Manager: THandle;
  82. Category, Index: Word) of object;
  83. TContextEvent = procedure(Sender: TObject; ContextHandle, StatusFlags: Integer) of object;
  84. { TCustomTablet}
  85. { This component provides access to digitizer hardware }
  86. TCustomTablet = class(TComponent)
  87. private
  88. FOnPacket: TPacketEvent;
  89. FOnCursorChanged: TPacketEvent;
  90. FOnProximity: TProximityEvent;
  91. FOnInfoChanged: TInfoChangedEvent;
  92. FOnOpenContext: TContextEvent;
  93. FOnCloseContext: TContextEvent;
  94. FOnOverlapContext: TContextEvent;
  95. FOnUpdateContext: TContextEvent;
  96. FPacketSize: Byte;
  97. FPresent: Boolean;
  98. FPPacket: Pointer;
  99. FWindowHandle: THandle;
  100. FWin32WidgetSet: TWin32WidgetSet;
  101. WTHandle: THandle;
  102. procedure WndProc(var Msg: TMessage);
  103. procedure SetPacketSize(Size: Byte);
  104. public
  105. constructor Create(AOwner: TComponent); override;
  106. destructor Destroy; override;
  107. property Present: Boolean read FPresent;
  108. property PacketSize: Byte read FPacketSize write SetPacketSize;
  109. published
  110. property OnContextClose: TContextEvent read FOnCloseContext write FOnCloseContext;
  111. property OnContextOpen: TContextEvent read FOnOpenContext write FOnOpenContext;
  112. property OnContextOverlap: TContextEvent read FOnOverlapContext write FOnOverlapContext;
  113. property OnContextUpdate: TContextEvent read FOnUpdateContext write FOnUpdateContext;
  114. property OnCursorChanged: TPacketEvent read FOnCursorChanged write FOnCursorChanged;
  115. property OnInfoChanged: TInfoChangedEvent read FOnInfoChanged write FOnInfoChanged;
  116. property OnPacket: TPacketEvent read FOnPacket write FOnPacket;
  117. property OnProximity: TProximityEvent read FOnProximity write FOnProximity;
  118. end;
  119. { TTablet }
  120. TTablet = class(TCustomTablet)
  121. private
  122. FContextHandle: HCtx;
  123. FEnabled: Boolean;
  124. function GetDeviceName: string;
  125. function GetWintabID: string;
  126. function GetPressure: TAxis;
  127. function GetPacketRate: Integer;
  128. function GetContext: TLogContext;
  129. procedure SetContext(Context: TLogContext);
  130. procedure SetEnabled(Value: Boolean);
  131. public
  132. constructor Create(AOwner: TComponent); override;
  133. procedure Open(Context: TLogContext);
  134. procedure Close;
  135. property Context: TLogContext read GetContext write SetContext;
  136. property ContextHandle: HCtx read FContextHandle write FContextHandle;
  137. property Enabled: Boolean read FEnabled write SetEnabled;
  138. property Pressure: TAxis read GetPressure;
  139. published
  140. property DeviceName: string read GetDeviceName;
  141. property WintabID: string read GetWintabID;
  142. property PacketRate: Integer read GetPacketRate;
  143. end;
  144. { Aliased functions (Can change these to unicode by changing the A to W in Alias name) }
  145. tWTInfo = function (wCategory: Cardinal; nIndex: Cardinal; lpOutput: Pointer): Cardinal; stdcall;
  146. { Used to read dispidious pieces of information about the tablet. }
  147. tWTOpen = function (hWnd: HWnd; var LPLogContext: TLogContext; fEnable: LongBool): Integer; stdcall;
  148. { Used to begin accessing the Tablet. }
  149. tWTGet = function (hCtx: HCtx; var LPLogContext: TLogContext): LongBool; stdcall;
  150. { Fills the supplied structure with the current context attributes for the passed handle. }
  151. tWTSet = function (hCtx: HCtx; var LPLogContext: TLogContext): LongBool; stdcall;
  152. { Allows some of the context's attributes to be changed on the fly. }
  153. { Basic functions }
  154. tWTClose = function (hCtx: HCtx): LongBool; stdcall;
  155. { Used to end accessing the Tablet. }
  156. tWTPacketsGet = function (hCtx: HCtx; cMaxPackets: Integer; lpPkts: Pointer): Integer; stdcall;
  157. { Used to poll the Tablet for input. }
  158. tWTPacket = function (hCtx: HCtx; wSerial: Cardinal; lpPkts: Pointer): LongBool; stdcall;
  159. { Similar to WTPacketsGet but is used in a window function. }
  160. { Visibility functions }
  161. tWTEnable = function (hCtx: HCtx; fEnable: LongBool): LongBool; stdcall;
  162. { Enables and Disables a Tablet Context; temporarily turning on or off the processing of packets. }
  163. tWTOverlap = function (hCtx: HCtx; fToTop: LongBool): LongBool; stdcall;
  164. { Sends a tablet context to the top or bottom of the order of overlapping tablet contexts. }
  165. { Context Editing functions }
  166. tWTConfig = function (hCtx: HCtx; hWnd: HWnd): LongBool; stdcall;
  167. { Used to call a requestor which aids in configuring the Tablet }
  168. tWTExtGet = function (hCtx: HCtx; wExt: Cardinal; lpData: Pointer): Integer; stdcall;
  169. tWTExtSet = function (hCtx: HCtx; wExt: Cardinal; lpData: Pointer): Integer; stdcall;
  170. tWTSave = function (hCtx: HCtx; lpSaveInfo: Pointer): Integer; stdcall;
  171. { Fills the supplied buffer with binary save information that can be used to restore the equivalent context in a subsequent Windows session. }
  172. tWTRestore = function (hWnd: HWnd; lpSaveInfo: Pointer; fEnable: Integer): Integer; stdcall;
  173. { Creates a tablet context from the save information returned from the WTSave function. }
  174. { Advanced Packet and Queue functions }
  175. tWTPacketsPeek = function (hCtx: HCtx; cMaxPackets: Integer; lpPkts: Pointer): Integer; stdcall;
  176. tWTDataGet = function (hCtx: HCtx; wBegin: Cardinal; wEnding: Cardinal;
  177. cMaxPackets: Integer; lpPkts: Pointer; lpNPkts: Pointer): Integer; stdcall;
  178. tWTDataPeek = function (hCtx: HCtx; wBegin: Cardinal; wEnding: Cardinal;
  179. cMaxPackets: Integer; lpPkts: Pointer; lpNPkts: Pointer): Integer; stdcall;
  180. tWTQueuePacketsEx = function (hCtx: HCtx; var lpOld: Pointer; var lpNew: Pointer): Integer; stdcall;
  181. { Returns the serial numbers of the oldest and newest packets currently in the queue. }
  182. tWTQueueSizeGet = function (hCtx: Integer): Integer; stdcall;
  183. tWTQueueSizeSet = function (hCtx: Integer; nPkts: Integer): Integer; stdcall;
  184. { Manager functions }
  185. { Manager Handle functions }
  186. tWTMgrOpen = function (HWnd: Integer; wMsgBase: Cardinal): Integer; stdcall;
  187. tWTMgrClose = function (hMgr: Integer): LongBool; stdcall;
  188. { Manager Context functions }
  189. tWTMgrContextEnum = function (hMgr: Integer; lpEnumFunc: Pointer; lParam: Pointer): Integer; stdcall;
  190. tWTMgrContextOwner = function (hMgr: Integer; hCtx: HCtx): Integer; stdcall;
  191. tWTMgrDefContext = function (hMgr: Integer; fSystem: LongBool): Integer; stdcall;
  192. tWTMgrDefContextEx = function (hMgr: Integer; wDevice: Cardinal; fSystem: LongBool): Integer; stdcall;
  193. { Manager Configuration functions }
  194. tWTMgrDeviceConfig = function (hMgr: Integer; var wDevice: Cardinal; HWnd: Integer): Cardinal; stdcall;
  195. tWTMgrConfigReplaceExA = function (hMgr: Integer; fInstall: LongBool; lpszModule: Pointer; lpszCfgProc: Pointer): Integer; stdcall;
  196. tWTMgrConfigReplaceExW = function (hMgr: Integer; fInstall: LongBool; lpszModule: Pointer; lpszCfgProc: Pointer): Integer; stdcall;
  197. { Manager Packet Hook functions }
  198. tWTMgrPacketHookExA = function (hMgr: Integer; nType: Integer; lpszModule: Pointer; lpszHookProc: Pointer): Integer; stdcall;
  199. tWTMgrPacketHookExW = function (hMgr: Integer; nType: Integer; lpszModule: Pointer; lpszHookProc: Pointer): Integer; stdcall;
  200. tWTMgrPacketUnHook = function (hHook: Integer): Integer; stdcall;
  201. tWTMgrPacketHookNext = function (hHook: Integer; nCode: Integer; wParam: Pointer; var lParam: Pointer): Integer; stdcall;
  202. { Manager Preference Data functions }
  203. tWTMgrExt = function (hMgr: Integer; wExt: Cardinal; lpData: Pointer): LongBool; stdcall;
  204. tWTMgrCsrEnable = function (hMgr: Integer; wCursor: Cardinal; fEnable: LongBool): Integer; stdcall;
  205. tWTMgrCsrButtonMap = function (hMgr: Integer; wCursor: Cardinal; lpLogBtns: Pointer; lpSysBtns: Pointer): Integer; stdcall;
  206. tWTMgrCsrPressureBtnMarksEx = function (hMgr: Integer; wCursor: Cardinal; lpNMarks: Pointer; lpTMarks: Pointer): Integer; stdcall;
  207. tWTMgrCsrPressureResponse = function (hMgr: Integer; wCursor: Cardinal; lpNResp: Pointer; lpTResp: Pointer): Integer; stdcall;
  208. tWTMgrCsrExt = function (hMgr: Integer; wCursor: Cardinal; wExt: Cardinal; var lpData: Pointer): Integer; stdcall;
  209. procedure DefaultContext(var Context: TLogContext);
  210. function GetInfoAsString(Category, Index: Cardinal): string;
  211. function GetInfoAsInteger(Category, Index: Cardinal): Integer;
  212. procedure Register;
  213. resourcestring
  214. OpenFailed = 'Tablet context failed to open.';
  215. GetProcFailed = 'Procedure %s failed to load properly.';
  216. { Procedural Variable Definitions }
  217. var
  218. WTInfo: tWTInfo;
  219. WTOpen: tWTOpen;
  220. WTGet: tWTGet;
  221. WTSet: tWTSet;
  222. WTClose: tWTClose;
  223. WTPacketsGet: tWTPacketsGet;
  224. WTPacket: tWTPacket;
  225. WTEnable: tWTEnable;
  226. WTOverlap: tWTOverlap;
  227. WTConfig: tWTConfig;
  228. WTExtGet: tWTExtGet;
  229. WTExtSet: tWTExtSet;
  230. WTSave: tWTSave;
  231. WTRestore: tWTRestore;
  232. WTPacketsPeek: tWTPacketsPeek;
  233. WTDataGet: tWTDataGet;
  234. WTDataPeek: tWTDataPeek;
  235. WTQueuePacketsEx: tWTQueuePacketsEx;
  236. WTQueueSizeGet: tWTQueueSizeGet;
  237. WTQueueSizeSet: tWTQueueSizeSet;
  238. WTMgrOpen: tWTMgrOpen;
  239. WTMgrClose: tWTMgrClose;
  240. WTMgrContextEnum: tWTMgrContextEnum;
  241. WTMgrContextOwner: tWTMgrContextOwner;
  242. WTMgrDefContext: tWTMgrDefContext;
  243. WTMgrDefContextEx: tWTMgrDefContextEx;
  244. WTMgrDeviceConfig: tWTMgrDeviceConfig;
  245. WTMgrConfigReplaceExA: tWTMgrConfigReplaceExA;
  246. WTMgrConfigReplaceExW: tWTMgrConfigReplaceExW;
  247. WTMgrPacketHookExA: tWTMgrPacketHookExA;
  248. WTMgrPacketHookExW: tWTMgrPacketHookExW;
  249. WTMgrPacketUnHook: tWTMgrPacketUnHook;
  250. WTMgrPacketHookNext: tWTMgrPacketHookNext;
  251. WTMgrExt: tWTMgrExt;
  252. WTMgrCsrEnable: tWTMgrCsrEnable;
  253. WTMgrCsrButtonMap: tWTMgrCsrButtonMap;
  254. WTMgrCsrPressureBtnMarksEx: tWTMgrCsrPressureBtnMarksEx;
  255. WTMgrCsrPressureResponse: tWTMgrCsrPressureResponse;
  256. WTMgrCsrExt: tWTMgrCsrExt;
  257. implementation
  258. procedure Register;
  259. begin
  260. RegisterComponents('System', [TTablet]);
  261. end;
  262. function GetInfoAsString(Category, Index: Cardinal): string;
  263. var
  264. P: PChar;
  265. begin
  266. GetMem(P, WTInfo(Category, Index, nil));
  267. WTInfo(Category, Index, P);
  268. Result := StrPas(P);
  269. FreeMem(P);
  270. end;
  271. function GetInfoAsInteger(Category, Index: Cardinal): Integer;
  272. begin
  273. WTInfo(Category, Index, @Result);
  274. end;
  275. procedure DefaultContext(var Context: TLogContext);
  276. { Establish contact and fill context with defaults }
  277. begin
  278. WTInfo(WTI_DEFCONTEXT, 0, @Context);
  279. end;
  280. //----------------------------------------------------------------------------//
  281. { TCustomTablet }
  282. procedure TCustomTablet.WndProc(var Msg: TMessage);
  283. begin
  284. with Msg do
  285. begin
  286. case Msg of
  287. WT_CTXCLOSE:
  288. if Assigned(FOnCloseContext) then
  289. FOnCloseContext(Self, WParam, LParam);
  290. WT_CTXOPEN:
  291. if Assigned(FOnOpenContext) then
  292. FOnOpenContext(Self, WParam, LParam);
  293. WT_CTXOVERLAP:
  294. if Assigned(FOnOverlapContext) then
  295. FOnOverlapContext(Self, WParam, LParam);
  296. WT_CTXUPDATE:
  297. if Assigned(FOnUpdateContext) then
  298. FOnUpdateContext(Self, WParam, LParam);
  299. WT_CSRCHANGE:
  300. if Assigned(FOnCursorChanged) then
  301. if WTPacket(LParam, WParam, FPPacket) then
  302. FOnCursorChanged(Self, WParam, LParam, FPPacket);
  303. WT_INFOCHANGE:
  304. if Assigned(FOnInfoChanged) then
  305. FOnInfoChanged(Self, WParam, LParamLo, LParamHi);
  306. WT_PACKET:
  307. if Assigned(FOnPacket) then
  308. if WTPacket(LParam, WParam, FPPacket) then
  309. FOnPacket(Self, WParam, LParam, FPPacket);
  310. WT_PROXIMITY:
  311. if Assigned(FOnProximity) then
  312. FOnProximity(Self, WParam, LParamLo <> 0);
  313. else
  314. { Pass any other messages to DefWindowProc }
  315. Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  316. end;
  317. end;
  318. end;
  319. constructor TCustomTablet.Create(AOwner: TComponent);
  320. procedure ValidateProc(var ProcPtr: Pointer; const ProcName: string);
  321. begin
  322. ProcPtr := GetProcAddress(wtHandle, PChar(ProcName));
  323. if not Assigned(ProcPtr) then
  324. raise Exception.CreateFmt(GetProcFailed, [ProcName]);
  325. end;
  326. var
  327. r : Cardinal;
  328. begin
  329. inherited Create(AOwner);
  330. if csDesigning in ComponentState then Exit;
  331. wtHandle := LoadLibrary('wintab32.dll');
  332. FPresent := wtHandle <> 0;
  333. if not FPresent then Exit;
  334. ValidateProc(@WTInfo, 'WTInfoA');
  335. ValidateProc(@WTOpen, 'WTOpenA');
  336. ValidateProc(@WTGet, 'WTGetA');
  337. ValidateProc(@WTSet, 'WTSetA');
  338. ValidateProc(@WTClose, 'WTClose');
  339. ValidateProc(@WTPacketsGet, 'WTPacketsGet');
  340. ValidateProc(@WTPacket, 'WTPacket');
  341. ValidateProc(@WTEnable, 'WTEnable');
  342. ValidateProc(@WTOverlap, 'WTOverlap');
  343. ValidateProc(@WTConfig, 'WTConfig');
  344. ValidateProc(@WTExtGet, 'WTExtGet');
  345. ValidateProc(@WTExtSet, 'WTExtSet');
  346. ValidateProc(@WTSave, 'WTSave');
  347. ValidateProc(@WTRestore, 'WTRestore');
  348. ValidateProc(@WTPacketsPeek, 'WTPacketsPeek');
  349. ValidateProc(@WTDataGet, 'WTDataGet');
  350. ValidateProc(@WTDataPeek, 'WTDataPeek');
  351. ValidateProc(@WTQueuePacketsEx, 'WTQueuePacketsEx');
  352. ValidateProc(@WTQueueSizeGet, 'WTQueueSizeGet');
  353. ValidateProc(@WTQueueSizeSet, 'WTQueueSizeSet');
  354. ValidateProc(@WTMgrOpen, 'WTMgrOpen');
  355. ValidateProc(@WTMgrClose, 'WTMgrClose');
  356. ValidateProc(@WTMgrContextEnum, 'WTMgrContextEnum');
  357. ValidateProc(@WTMgrContextOwner, 'WTMgrContextOwner');
  358. ValidateProc(@WTMgrDefContext, 'WTMgrDefContext');
  359. ValidateProc(@WTMgrDefContextEx, 'WTMgrDefContextEx');
  360. ValidateProc(@WTMgrDeviceConfig, 'WTMgrDeviceConfig');
  361. ValidateProc(@WTMgrConfigReplaceExA, 'WTMgrConfigReplaceExA');
  362. ValidateProc(@WTMgrConfigReplaceExW, 'WTMgrConfigReplaceExW');
  363. ValidateProc(@WTMgrPacketHookExA, 'WTMgrPacketHookExA');
  364. ValidateProc(@WTMgrPacketHookExW, 'WTMgrPacketHookExW');
  365. ValidateProc(@WTMgrPacketUnhook, 'WTMgrPacketUnhook');
  366. ValidateProc(@WTMgrPacketHookNext, 'WTMgrPacketHookNext');
  367. ValidateProc(@WTMgrExt, 'WTMgrExt');
  368. ValidateProc(@WTMgrCsrEnable, 'WTMgrCsrEnable');
  369. ValidateProc(@WTMgrCsrButtonMap, 'WTMgrCsrButtonMap');
  370. ValidateProc(@WTMgrCsrPressureBtnMarksEx, 'WTMgrCsrPressureBtnMarksEx');
  371. ValidateProc(@WTMgrCsrPressureResponse, 'WTMgrCsrPressureResponse');
  372. ValidateProc(@WTMgrCsrExt, 'WTMgrCsrExt');
  373. r := WTInfo(0, 0, nil);
  374. FPresent := r <> 0;
  375. if FPresent then
  376. begin
  377. FWin32WidgetSet := TWin32WidgetSet.Create;
  378. FWindowHandle := FWin32WidgetSet.AllocateHWnd(WndProc);
  379. end;
  380. end;
  381. destructor TCustomTablet.Destroy;
  382. begin
  383. if FPresent then
  384. begin
  385. FWin32WidgetSet.DeallocateHWnd(FWindowHandle);
  386. FreeMem(FPPacket, FPacketSize + 1);
  387. FreeLibrary(wtHandle);
  388. // FWin32WidgetSet.Free; // this call causes an exception. What is the proper way to use TWin32WidgetSet?
  389. end;
  390. inherited;
  391. end;
  392. procedure TCustomTablet.SetPacketSize(Size: Byte);
  393. begin
  394. FPacketSize := Size;
  395. ReallocMem(FPPacket, Size + 1);
  396. end;
  397. //----------------------------------------------------------------------------//
  398. { TTablet }
  399. procedure TTablet.Close;
  400. begin
  401. if FPresent and (FContextHandle <> 0) then WTClose(FContextHandle);
  402. end;
  403. constructor TTablet.Create(AOwner: TComponent);
  404. begin
  405. inherited;
  406. FEnabled := False;
  407. FContextHandle := 0;
  408. end;
  409. function TTablet.GetContext: TLogContext;
  410. begin
  411. if FPresent and (FContextHandle <> 0) then WTGet(FContextHandle, {%H-}Result);
  412. end;
  413. function TTablet.GetDeviceName: string;
  414. begin
  415. if FPresent then Result := GetInfoAsString(WTI_DEVICES, DVC_NAME);
  416. end;
  417. function TTablet.GetPacketRate: Integer;
  418. begin
  419. if FPresent then WTInfo(WTI_STATUS, STA_PKTRATE, @Result);
  420. end;
  421. function TTablet.GetPressure: TAxis;
  422. const
  423. EmptyAxis: TAxis = (Min: 0; Max: 0; Units:0; Resolution: 0);
  424. begin
  425. Result := EmptyAxis;
  426. if FPresent then
  427. WTInfo(WTI_DEVICES, DVC_NPRESSURE, @Result);
  428. end;
  429. function TTablet.GetWintabID: string;
  430. begin
  431. if FPresent then Result := GetInfoAsString(WTI_INTERFACE, IFC_WINTABID);
  432. end;
  433. procedure TTablet.Open(Context: TLogContext);
  434. begin
  435. if FPresent then FContextHandle := WTOpen(FWindowHandle, Context, FEnabled);
  436. end;
  437. procedure TTablet.SetContext(Context: TLogContext);
  438. begin
  439. if FPresent then WTSet(FContextHandle, Context);
  440. end;
  441. procedure TTablet.SetEnabled(Value: Boolean);
  442. begin
  443. if FPresent then
  444. begin
  445. FEnabled := Value;
  446. if FContextHandle <> 0 then WtEnable(FContextHandle, Value);
  447. end;
  448. end;
  449. end.