Notes for Tablet Aware Application Developers
Audience
This document is mainly intended to assist developers who already have tablet aware applications and want to add new capabilities to their applications. You should already be able to access the tablet data and capabilities. Developers who are adding tablet features for the first time should start with the Overview section, and examine the sample code.
Overview
Applications receive tablet-specific data by using the Wintab Application Programmers Interface. Wintab is an industry standard for interfacing with pointing devices. Not all features of the Wintab interface are supported and some pointing devices support feature while others do not. Information on Wintab, including a developers’ SDK can be obtained from the downloads page. The TiltTest program which is included with this implementers guide is a good example of how to use Wintab to get tablet data.
There are two main points in an application where modifications may be made to support tablets:
- Initialization
During initialization you need to:
-
Determine if a tablet is attached by looking for the Wintab interface. Call the Wintab function
WTInfo(0, 0, NULL)to see if Wintab is present. -
Use
WTInfo()to get static information about the tablet, such as tablet dimensions, coordinate resolution, the presence of tilt, pressure range, tangential pressure range, and other features. -
Create at least one Wintab context for your application. Get a default context using
WTInfo()and use it as a template to create your own tablet context. Set up the context as appropriate for your application. Applications can open two kinds of contexts: system contexts and digitizing contexts. Wintab moves the system cursor on behalf of the application for system contexts, while applications must move the system cursor themselves for digitizing contexts. Most applications use system contexts. The user can change the area of a system context to make navigation easier. Digitizer contexts usually cover the entire tablet. Digitizer contexts are used for digitizing or to define tablet menus. Setting up the context includes determining what data items will be included in the packets. Although the documentation says you can not include items in the packet that are not supported by the tablet, it appears that this is incorrect. Unsupported items may be included and will be set to zero. Then callWTOpen()to create your context so you can begin processing packet data. -
Wintab passes data for a tablet point, such as coordinates, pressure and tilt, to an application as a Wintab packet. By default, the packet queue for a context is very small and can easily overflow. Applications should guard against overflowing their queues by increasing their context’s queue sizes using
WTQueueSizeSet().
-
- Message Handling
During device operation, you will get data from the tablet. This data is used for line rendering or navigation. You may need to find additional information about the tablet device currently in use. This device information can be used to change tools or screen cursors, for example, when a stylus eraser is placed in use or when tools are changed based on device ID.
The following Windows messages should be handled.
-
WM_LBUTTONDOWN/WM_LBUTTONUPmessageOn
WM_LBUTTONDOWNthe packets in the tablet queue should be flushed using, for example,WTPacketsGet()(since they are old). If you are very particular, you may want to flush all packets up to the one with the button pressed and use the rest for drawing. Set a flag indicating packet events should now be processed and drawn. OnWM_LBUTTONUPclear the flag and stop processing packets. Again, if you are particular, on theWM_LBUTTONUPevent process the packets in the queue that correspond to the button press state. -
WT_PACKETmessage (usually during a button down)In the draw loop (usually continuously done between
WM_LBUTTONDOWNandWM_LBUTTONUP), tablet data is read from packets and used to modify the rendering of the line being drawn. Data such as current pressure, tilt angles, and fingerwheel values are used to change rendering parameters like opacity, brush direction, line thickness, and so forth. Wintab stores packets in a context-unique packet queue until the application that opened the context requests packet data using a Wintab function such asWTPacket().When applications open a context they pass Wintab a window handle. If the application sets the context’s
CXO_MESSAGESoption, the window receives notification that a packet has been added to the queue via theWT_PACKETmessage. This event contains the serial number for the packet that generated the event. Upon receiving the event, callWTPacket()with the serial number provided in the message.CAUTION! If the queue overflows, Wintab stops informing the application that packets have been queued, and it discards the subsequently received packets until the queue is no longer full. Be sure to avoid overflow by draining the queue during
WT_PACKETmessages. -
WT_CSRCHANGE(and/orWT_PROXIMITY) messageWhen a pointing device enters or leaves a context, the application that opened the context is notified through the
WT_PROXIMITYmessage. When a different pointing device enters proximity of the context, the application is informed through aWT_CSRCHANGEmessage, if the application requested this message when the context was created. When an application receives aWT_PROXIMITYand/orWT_CSRCHANGEmessage, it can callWTInfo()to get information about the pointing device, such as number of buttons on the device, which end of the stylus is in use, or the device’s physical ID. This message is very useful for changing drawing tools. The selected tool (and/or screen cursor) should change when the pointing device is first brought into use, not when drawing starts. Therefore, you will want to check for tip vs. eraser, and check the Unique ID at this point. -
WT_PACKETmessage (without a button down)You may want to look at device information for navigational purposes, such as rotating an object with the stylus tilt. You can do this by always reading tablet packets in response to
WT_PACKETevents, even when a button is not down. For example, if you are using a 4D Mouse for navigation, current device information can be used to modify an object’s position or to modify your own viewpoint.
-
Notes
With some exceptions the Wacom driver implements the Wintab specification version 1.1 as published by LCS/Telegraphics. The specification version return by the Wacom driver is 1.4.
// Check the Wintab version in this manner WORD thisVersion; WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &thisVersion);
Version 1.2 added CSR_TYPE which is needed to carry information for Unique ID.
Version 1.3 add a now depricated incomplete extension for express keys. (WTX_EXPKEYS)
Version 1.4 adds an updated extension for express keys and also adds extensions
for touch strips and touch rings. (WTX_EXPKEYS2, WTX_TOUCHSTRIP, WTX_TOUCHRING)
You should not have to change any code to support the features you currently support, you simply add code to support new features. The depricated express key implementation of 1.3 will not return unsupported.
Here are the latest header files, WINTAB.H and
PKTDEF.H to replace the files you are now using.
These files bring the data structures up to specification 1.4, and add the 1.2 feature
(CSR_TYPE).
Wintab holds all open contexts for all applications in a single overlaping container
for each tablet. It uses the overlap order to decide which context should process
each tablet packet. Each packet is put in only one context’s packet queue.
In general, if context A is above context B in the overlap order, context A will
receive tablet packets and context B will not. Applications bring their contexts
to the top or bottom of the overlap order by calling WTOverlap(). Many
applications fail to properly handle their context ordering. This causes simultaneously
executing Wintab applications to stop working or to behave unpredictably. When applications
receive the WM_ACTIVATE message, they should push their contexts to
the bottom of the overlap order if their application is being deactivated, and should
bring their context to the top if they are being activated. Applications should
also disable their contexts when they are minimized.
The Wacom implentation of Wintab will manage the context order for the application. This means that the application will only get data when that application has keyboard focus. We did this because to many application do not correctly handle their own contexts. Please help us out by correctly managing your contexts so some day we can remove this code.
It is best to have at least two undo buffers, or one more than the desired number. Don’t flush the undo buffer on a button down when you are about to draw, it takes too long. Flush the buffer on a button up. This will improve the beginning of your strokes.
Features You Should Already Have Implemented
Eraser and Tilt are features that have been around for some time. A large installed base of tablets supports these capabilities and, if you have not already done so, you can increase the power and performance of your application by implementing these features.
-
Eraser
The obvious purpose of the eraser is to use it as an erasing tool. But you can change the function of the eraser to perform more advanced tasks. Using the stylus tip in conjunction with the eraser, you can easily perform two opposing functions such as dodge and burn, or ink and bleach. The eraser can also function independently as any tool selected in the application.
There are several ways to detect the use of the eraser.
One way is to look for a negative orAltitude value in the pkOrientation data of a packet. If you use this method please note that the tilt value is defined as unsigned (although it is stated to be signed in the Wintab specification) so you will have to cast the tilt value as signed to make this work.
Another way to detect the eraser is to look for cursor number 2, and with the advent of the Dual Track (explianed later) also check for cursor number 5. The time to check the cusor number is once the device is brought into proximity. The
WT_CSRCHANGEmessage is will allow you to detect when a new device enters proximity. For backwards compatibility you might also process theWT_PROXIMITYmessage. Be sure to include the cursor number (pkCursorfield) in the data packet. If you wish to use this method you should ask Wintab for the number of cursors per device (WTInfo(WTI_INTERFACE, IFC_NCURSORS, &data)and modulus that result with thepkCursorfield to do the test.The third way an application can detect the eraser is by looking at the
TPS_INVERTbit-field in thepkStatusdata item of a packet. This field was added to the Wintab 1.1 specification. -
Tilt
Stylus tilt has several uses, but the most obvious is to change brush shape. Tilt can also be used for object rotation, or as a joystick.
During initialization you can check for the existence of tilt this way:
// Get info. about tilt struct tagAXIS tiltOrient[3]; BOOL tiltSupport = FALSE; tiltSupport = WTInfo(WTI_DEVICES, DVC_ORIENTATION, &tiltOrient); if (tiltSupport ) { // Does the tablet support azimuth and altitude if (tiltOrient[0].axResolution && tiltOrient[1].axResolution) { // Get resolution azimuth = tiltOrient[0].axResolution; altitude = tiltOrient[1].axResolution; } else { tiltSupport = FALSE; } }Tilt data is in the pkOrientation packet.
New Features to Implement
New features introduced with the Intuos series tablets include: Unique ID , Airbrush Fingerwheel, 4D Mouse Rotation, and 4D Mouse Thumbwheel. If your application already supports Wintab then these features are VERY easy to add. An old feature which is now fully supported is Dual Track.
-
Dual Track
Dual Track, also referred to as multimode, allows two devices to be tracked at the same time. With the UDII series 12 x 12 and larger it is possible to simultaneously track a stylus and a puck. With the Intuos series it is possible to track ANY two devices.
Working with two tools at once expands your capabilities in many unique ways. Stretch a line from both ends, or move a frisket with one hand while airbrushing around it with the other. Move a magnifying glass with one hand and draw on either the magnified, or the unmagnified image with the other. See the paper Bier, Eric A., Stone, Maureen C., Pier, Ken, Buxton, William. "Toolglass and Magic Lenses: The See-Through Interface" Computer Graphics, (1993), 73-80 or the video tape submission submission A GUI Paradigm Using Tablets, Two Hands and Transparency George Fitzmaurice, Thomas Baudel, Gordon Kurtenbach and Bill Buxton, CHI 97 Video Program by ACM.
Here are some things to keep in mind when implementing dual track:
-
It is not possible to have the system move two screen cursors for you, it can only move one. So you will have to turn tracking on for one device and off for the other (or turn both off). You will have to move your own "screen cursor (sprite?)" for at least one device.
-
There is a major hand and a minor hand, the major hand, being your dominant hand, usually performs the more complex task. For example, the major hand does the drawing while the minor hand may hold a frisket.
-
Avoid collisions. The application should change the offsets for the two devices (or partition the tablet) so that you do not have to position the two devices on top of one another.
Pointing devices are indexed from 0 to 5. The application can tell which device generated a packet by looking at the packet’s
pkCursordata item. The possible index values are:Index 0 – Puck-like device #1
Index 1 – Stylus-like device #1
Index 2 – Inverted stylus-like device #1
Index 3 – Puck-like device #2
Index 4 – Stylus-like device #2
Index 5 – Inverted stylus-like device #2
The indexes are really placeholders for actual pointing devices. For example, the first time device index 2 enters the proximity of a context, it may be an inverted airbrush. As long as device index 2 is in proximity of the context, the device index of 2 uniquely identifies this physical device as the same inverted airbrush. However, after device 2 exits proximity, the next time the context sees a pointing device with an index of 2 enter proximity, index 2 may identify a different device, such as an inverted pen.
By default, tracking is turned on for the first device (
pkCursor= 0, 1, or 2). This is the first device to enter proximity. Tracking is turned off (pkCursor= 3, 4, or 5) for the second device to enter proximity. So, an application that does not support dual tracking will virtually have the second device turned off. If they are both on, the screen cursor jumps back and forth between them. You may need to reverse this on the fly (on aWT_CSRCHANGEmessage) based on which device is in which hand.Use the cursor number (
pkCursorfield) in the data packet to separate the packet stream into two streams (0-2 and 3-5) one steam for each device.Note: Dual track was only supported for the following tablets. UDII 12x12, Intuos and Intuos II. Intuos III and IV do not support Dual track.
-
-
Unique ID
There is another new feature to the Intuos series: Unique ID. A chip with a unique number is inside every device so every device can be uniquely identified. With Unique ID you can assign a specific drawing tool to a specific pointing device or use it to "sign" a document. You can restrict access to document layers to particular devices and have settings follow a device to other machines.
The ID code from the device is in two sections. It is the combination of the two that is guaranteed unique. One section, the
CSR_TYPE, is actually a code unique to each device type. The other section, theCSR_PHYSID, is a unique 32 bit number within a device type.CSR_PHYSIDmay be repeated between device types, but not within a type.The
CSR_TYPEis a coded bit field. Some bits have special meaning to the hardware, but are not of interest to a developer.What is of interest is:
There are 12 bits total.
Bits 1,2,8,9,10,11 identify the device. The middle 4 bits (4,5,6,7) are used to differentiate between electrically similar, but physically different devices, such as a general stylus with a different color. So to figure out a specific device type you mask with
0x0F06. For example maybe0x0812is a stylus that is black,0x0802is the standard stylus included in the box, and0x0832may be a stylus with one side switch. Bits 0,3 are used internally and should be ignored.The currently supported types are:
General stylus:
(CSR_TYPE & 0x0F06) == 0x0802Airbrush:
(CSR_TYPE & 0x0F06) == 0x0902Art Pen:
(CSR_TYPE & 0x0F06) == 0x08044D Mouse:
(CSR_TYPE & 0x0F06) == 0x00045 button puck:
(CSR_TYPE & 0x0F06) == 0x0006To create the unique ID just concatenate
CSR_TYPE(without masking with0x0F06) andCSR_PHYSIDto make a 48 bit (you will probably use 64 bit) serial number. -
Airbrush Fingerwheel
The Intuos series tablets have a device that is similar to an airbrush. The device not only supports pressure on the tip, but also has a fingerwheel on the side to simultaneously vary a second value. For example, using the fingerwheel to vary ink density and, using pressure to vary line width.
The value of the fingerwheel on the side of the airbrush is reported in the
pkTangentPressure(tangential pressure) field so be sure to include it in your packets. The value varies between 0 and 1023. But don’t hard code 1024! Use the functionWTInfo(WTI_DEVICES, DVC_TPRESSURE)to query the tangent pressure range supported by the tablet. -
4D Mouse Rotation
The Intuos series tablets have a device that is similar to a puck. In addition to normal puck parameters, this puck supports axial rotation and a thumbwheel on the side. For example, with the 4D Mouse rotation, you can rotate the paper or an object, and zoom with the thumbwheel.
4D Mouse axial rotation is reported in the
pkOrientation.orTwistfield. Values in this field range from 0 to 3599.During initialization you can check for the existence of rotation this way:
// Get info. about rotation struct tagAXIS tiltOrient[3]; BOOL rotateSupport = FALSE; rotateSupport = WTInfo(WTI_DEVICES, DVC_ORIENTATION, &tiltOrient); if (rotateSupport) { // Does the tablet support twist if (!tiltOrient[2].axResolution) { rotateSupport = FALSE; } }You would probably check for this at the same time you check for tilt, since it is in the same data structure.
-
4D Mouse Thumbwheel
Uses for the 4D Mouse thumbwheel include zooming and 3D navigation. The thumbwheel value is reported in the
pkZfield. The thumbwheel varies frompkZ = 1023topkZ = -1023and snaps to the middle when released. The middle is 0, and the total range is fromaxMintoaxMax. The value axResolution is 0 if the tablet does not support the 4D Mouse (such as legacy tablets). The thumbwheel may not have a broad enough range for all uses. It is left as an exercise to the reader to devise a way to extend the range.During initialization you can check for the existence of the thumbwheel this way:
// Get info. about thumbwheel struct tagAXIS thumbwheelAxis; BOOL thumbwheelSupport = FALSE; thumbwheelSupport = WTInfo(WTI_DEVICES, DVC_Z, &thumbwheelAxis); if (thumbWheelSupport) { // Does the tablet support thumbwheel? if (!thumbwheelAxis.axResolution) { thumbwheelSupport = FALSE; } }
Extensions
-
ExpressKeys extension
Some tablets have physical key on the tablet surface. We have received requests to expose these keys to an application and allow the application to perform tasks when the key is pressed.
This extension allows an application to receive Express Key event notifications, and to override the normal system-wide behavior of Express Keys. To make use of this extension, perform the following steps:
-
Make sure you have versions of
WINTAB.HandPKTDEF.Hthat support this extension (≥ 1.4).The following information items are supported for this extension:
EXT_NAME— (TCHAR[])
The null-terminated string"ExpressKeys"EXT_TAG— (UINT)
The tag valueWTX_EXPKEYS2EXT_MASK— (WTPKT)
The masked used when creating the context to activate the extension.EXT_SIZE— (UINT[2])
The size of the data structure in the extension packet.EXT_AXES— (AXIS[1])
An axis structure withaxMinequal to 0,axMaxequal to the value returned if all button are pressed,axResolutionis 1 andaxUnitsisTU_NONE.
-
Detect at run-time whether the Express Key extension is supported by the installed driver. This can be done by scanning the
WTI_EXTENSIONSinformation categories for an extensions whose tag is equal toWTX_EXPKEYS2. If found, the extension is supported. (seePKTDEF.Hfor details)// Iterate through Wintab extension indices for ( UINT i=0, thisTag = 0; WTInfo(WTI_EXTENSIONS+i, EXT_TAG, &thisTag); i++) { // looking for the specified tag if (thisTag == WTX_EXPKEYS2) { // note the index of the found tag return i; } } return ERROR("EXPKEYS2 not supported by this Wintab"); -
Add the Express Keys data to your extension packet definition by adding the following declaration before including
PKTDEF.H:#define PACKETEXPKEYS PKEXT_ABSOLUTEThis causes the EXPKEYSDATA structure to be included in the
PACKETEXTstructure definition. It is added aspkExpKeys. -
Get the required mask for the extension and the mask with the lcPktData member of the context.
// get the extension mask for the express keys WTInfo(WTI_EXTENSIONS + extIndex_ExpKeys, EXT_MASK, &lExpKeys_Mask); ... lcContext.lcPktData = PACKETDATA | lExpKeys_Mask;
This tells the driver to fill in the EXPKEYSDATA structure.
-
Determine the keys that are present by requesting extension data through the
WTExtGetcommand:// allocate a buffer BYTE *buffer = new BYTE [sizeof(EXTPROPERTY) + sizeof(BOOL)]; // cast the buffer to the extension property data structure EXTPROPERTY *prop = (EXTPROPERTY*)buffer; // fill in the data prop->version = 0; prop->tabletIndex = tablet_I; prop->controlIndex = control_I; prop->functionIndex = function_I; prop->propertyID = TABLET_PROPERTY_AVAILABLE; prop->reserved = 0; prop->dataSize = sizeof(BOOL); // send the command to Wintab if (WTExtGet(ghCtx, ext_I, prop)) { // store the data requested return *((BOOL*)(&prop->data[0])); }WTExtGetuses the EXTPROPERTY structure to recieve data about the extension. -
Override ExpressKey behavior by calling
WTExtSet.// allocate a buffer BYTE *buffer = new BYTE [sizeof(EXTPROPERTY) + sizeof(BOOL)]; // cast the buffer to the extension property data structure EXTPROPERTY *prop = (EXTPROPERTY*)buffer; // fill in the data prop->version = 0; prop->tabletIndex = tablet_I; prop->controlIndex = control_I; prop->functionIndex = function_I; prop->propertyID = TABLET_PROPERTY_OVERRIDE; prop->reserved = 0; prop->dataSize = sizeof(BOOL); *((BOOL*)(&prop->data[0])) = TRUE; // send the command to Wintab return !WTExtSet(ghCtx, ext_I, prop);
With
WTExtSetcommand, you can also override the name of the Express Key. (see the WINTAB.H for a complete list of properties)
-
-
Touch Strip and Touch Ring extension
This extension allows an application to receive Touch Strip and Touch Ring event notifications, and to override the normal system-wide behavior of Touch Strip and Touch Ring. To make use of this extension, perform the following steps:
-
Make sure you have versions of
WINTAB.HandPKTDEF.Hthat support this extension (≥ 1.4).The following information items are supported for the touch strip extension:
EXT_NAME— (TCHAR[])
The null-terminated string"TouchStrips"EXT_TAG— (UINT)
The tag valueWTX_TOUCHSTRIPEXT_MASK— (WTPKT)
The masked used when creating the context to activate the extension.EXT_SIZE— (UINT[2])
The size of the data structure in the extension packet.EXT_AXES— (AXIS[1])
An axis structure withaxMinequal to 0,axMaxequal to the number of zones on the touch ring,axResolutionis1/axMaxandaxUnitsisTU_CIRCLE.
The following information items are supported for the touch ring extension:
EXT_NAME— (TCHAR[])
The null-terminated string"TouchRings"EXT_TAG— (UINT)
The tag valueWTX_TOUCHRINGEXT_MASK— (WTPKT)
The masked used when creating the context to activate the extension.EXT_SIZE— (UINT[2])
The size of the data structure in the extension packet.EXT_AXES— (AXIS[1])
An axis structure withaxMinequal to 0,axMaxequal to the value returned if all button are pressed,axResolutionis 1 andaxUnitsisTU_NONE.
-
Detect at run-time whether the extension is supported by the installed driver. This can be done by scanning the
WTI_EXTENSIONSinformation categories for an extensions whose tag is equal toWTX_TOUCHSTRIPand/orWTX_TOUCHRINGrespectfully. If found, the extension is supported. (seePKTDEF.Hfor details)// Iterate through Wintab extension indices for ( UINT i=0, thisTag = 0; WTInfo(WTI_EXTENSIONS+i, EXT_TAG, &thisTag); i++) { // looking for the specified tag if (thisTag == WTX_TOUCHSTRIP) { // note the index of the found tag return i; } } return ERROR("TOUCHSTRIP not supported by this Wintab"); -
Add the Express Keys data to your extension packet definition by adding the following declaration before including
PKTDEF.H:#define PACKETTOUCHSTRIP PKEXT_ABSOLUTE#define PACKETTOUCHRING PKEXT_ABSOLUTEThis causes the SLIDERDATA structure to be included in the
PACKETEXTstructure definition. The touchstrip extension addspkTouchStrip; while the touchring extension addspkTouchRing. -
Get the required mask for the extension and and the mask with the lcPktData member of the context.
// get the extension mask for the touch strip WTInfo(WTI_EXTENSIONS + extIndex_TouchStrip, EXT_MASK, &lTouchStrip_Mask); // get the extension mask for the touch ring WTInfo(WTI_EXTENSIONS + extIndex_TouchRing, EXT_MASK, &lTouchRing_Mask); ... lcContext.lcPktData = PACKETDATA | lTouchStrip_Mask | lTouchRing_Mask;
This tells the driver to fill in the correct SLIDERDATA structure.
-
Determine the function that are present by requesting extension data through the
WTExtGetcommand:// allocate a buffer BYTE *buffer = new BYTE [sizeof(EXTPROPERTY) + sizeof(BOOL)]; // cast the buffer to the extension property data structure EXTPROPERTY *prop = (EXTPROPERTY*)buffer; // fill in the data prop->version = 0; prop->tabletIndex = tablet_I; prop->controlIndex = control_I; prop->functionIndex = function_I; prop->propertyID = TABLET_PROPERTY_AVAILABLE; prop->reserved = 0; prop->dataSize = sizeof(BOOL); // send the command to Wintab if (WTExtGet(ghCtx, ext_I, prop)) { // store the data requested return *((BOOL*)(&prop->data[0])); }WTExtGetuses the EXTPROPERTY structure to recieve data about the extension. -
Override the function behavior by calling
WTExtSet.// allocate a buffer BYTE *buffer = new BYTE [sizeof(EXTPROPERTY) + sizeof(BOOL)]; // cast the buffer to the extension property data structure EXTPROPERTY *prop = (EXTPROPERTY*)buffer; // fill in the data prop->version = 0; prop->tabletIndex = tablet_I; prop->controlIndex = control_I; prop->functionIndex = function_I; prop->propertyID = TABLET_PROPERTY_OVERRIDE; prop->reserved = 0; prop->dataSize = sizeof(BOOL); *((BOOL*)(&prop->data[0])) = TRUE; // send the command to Wintab return !WTExtSet(ghCtx, ext_I, prop);
With
WTExtSetcommand, you can also override the name of the function. (see the WINTAB.H for a complete list of properties)
-
-
Notes about the extension queue
When an extension event occurs, an extension packet is created and queued to the context. If the application requested messages then a WT_PACKETEXT message is sent to the application. This message is identical to the WT_PACKET message except for the queue. The application should call the WTPacket function with the context provided and a PACKETEXT will be returned. This packet contains an EXTENSIONBASE data stucture as well as any other structures the application requested at PKTDEF.h include time.
NOTE: It is recommended that applications remove their overrides when the application's main window is no longer active (use WM_ACTIVATE). Extension overrides take effect across the entire system; if an application leaves its overrides in place, that control will not function correctly in other applications.
EXPKEYSDATA structure
typedef struct tagEXPKEYSDATA { /* 1.4 */
BYTE nTablet; // index of the tablet
BYTE nControl; // position index of the control
BYTE nLocation; // location of the control
BYTE nReserved; //
DWORD nState; // state of the control (1 - pressed, 0 - released)
} EXPKEYSDATA;
This structure is returned as part of the PACKETEXT structure.
SLIDERDATA structure
typedef struct tagSLIDERDATA { /* 1.4 */
BYTE nTablet; // index of the tablet
BYTE nControl; // position index of the control
BYTE nFunction; // control function index
BYTE nReserved; //
DWORD nPosition; // position of the finger on the control (zero for no touch)
} SLIDERDATA;
This structure is returned as part of the PACKETEXT structure.
EXTPROPERTY structure
typedef struct tagEXTPROPERTY { /* 1.4 */
BYTE version; // Structure version, 0 for now
BYTE tabletIndex; // 0-based index for tablet
BYTE controlIndex; // 0-based index for control
BYTE functionIndex; // 0-based index for control's sub-function
WORD propertyID; // property ID
WORD reserved; // DWORD-alignment filler
DWORD dataSize; // number of bytes in data[] buffer
BYTE data[1]; // raw data
} EXTPROPERTY;
This structure is used for WTExtGet and WTExtSet.
Note that this stucture is of variable size. The total size of the structure is sizeof(EXTPROPERTY) + dataSize. Take care to allocate the correct amount of memory before using this structure.