Basics
Introduction
What this page covers
This page will give the developer a basic overview of the Wintab API framework, the Wintab programming model, and details on writing a Wintab application.
Target platforms
Windows operating systems that support the Wintab API. See Overview for details.
Target tablets
Wacom devices that support the Wintab API. See the Wintab Overview page for details.
Programming framework, SDK, languages
Applications using Wintab API can be written for any programming framework that supports the import of Windows DLL modules. These modules ship with and are installed by the Wacom tablet driver installation package.
The Wintab SDK is actually a combination of modules installed with the tablet driver and header files included with the sample code used to interface to those modules. When building a C++ Wintab application, it is necessary to include these three header files:
- Wintab.h – defines the supported Wintab constructs
- Msgpack.h – macros for unpacking Wintab messages
- Pktdef.h – for building the Wintab packet definition (what data is needed, such as X, Y, pressure) to send to the driver
To simplify Wintab app development, all Wintab function access can be implemented using dynamic functions that are initialized when the Wintab32.dll module is loaded. All demo code uses this technique (there is no static linking to a Wintab library). The files Utils.cpp and Utils.h support this dynamic loading technique. The big advantage of dynamic loading is that you need build only one version of the app, and it will execute on both 64bit and 32bit Windows hosts.
For those developers using Windows .NET, Wintab support is built into the WintabDN.dll module that is the SDK for that platform. As with Wintab C++ support; however, the tablet driver must be installed to use this SDK.
To assist the developer, a complete description of the Wacom-supported Wintab API Reference, with C-style definitions, can be found at: Reference.
The Wintab SDK comes with ready-to-use C++ and .NET (C#) Wintab support. See Sample Code for Visual Studio Wintab demos.
See the FAQs for information on other (non-Wacom supported) Wintab framework support.
Wintab Architecture Overview
Description
When a Wacom tablet driver is installed, Windows Wintab-supporting DLLs are installed as well, providing the ability for the app to communicate through a private data context with the driver, map the tablet into the application’s data space, and receive driver pen data packets and configuration. Because of the way Wintab support is partitioned in the driver, it is possible for multiple applications to have their own private Wintab pen data streams from the driver.
The following image illustrates a high-level view of how a Wintab application connects to the tablet driver:
Basic programming model
The two primary concepts of the Wintab programming model are Wintab contexts and Wintab data acquisition. An application creates, configures and opens a Wintab context. The application's message loop either responds to Wintab data messages and queries for data, or responds to other triggers (such as mouse events) and queries for data. Acquired data can then be processed in the application space for use in drawing or signature capture (two common examples).
Wintab contexts
From its beginning, the Wintab API has supported multiple independent, simultaneous, per-application and per-tablet contexts. This means that you can write an app that will receive independent pen data streams from a context for each attached tablet (or a single virtual stream from all tablets through one context). And multiple Wintab apps will each have their own contexts and pen data streams.
The way in which Wintab protects per-application data is through the Wintab context. The context is the place that defines, among other attributes, what type of data will be sent to the app (tablet counts or system pixels) and how it maps to the system display. With the app, once a default digitizing or system context is obtained, many properties of the Wintab context can be adjusted. It is worth noting that any context adjustments made for an application do not affect either the contexts within other Wintab apps, or the global Wacom tablet preferences.
Wintab contexts play a central role in the interface; they are the objects that applications use to specify their use of the tablet. Contexts include not only the physical area of the tablet that the application will use, but also information about the type, contents, and delivery method for tablet events, as well as other information. Tablet contexts are somewhat analogous to display contexts in the GDI interface model; they contain context information about a specific application's use of the tablet.
An application can open more than one context, but most only need one. Applications can customize their contexts, or they can open a context using a default context specification that is always available. The WTInfo function provides access to the default context specification.
Opening a context requires a window handle. The window handle becomes the context's owner and will receive any window messages associated with the context.
Contexts are remotely similar to screen windows in that they can physically overlap. The tablet interface uses a combination of context overlap order and context attributes to decide which context will process a given event. The topmost context in the overlap order whose input context encompasses the event, and whose event masks select the event, will process the event. (Note that the notion of overlap order is separate from the notion of the physical z dimension.)
Wintab holds all open contexts for all applications in a single overlapping 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. The Wacom implementation of Wintab manages the context order for an application. This means that an application will only get data when that application has keyboard focus. Wacom did this because too many applications do not correctly handle their own contexts. This policy was created to prevent apps from receiving data while other important apps are in the foreground.
Wintab data acquisition
Wintab supports two methods of pen data capture: message-driven and polling.
With pen data capture, a standard Windows message queue receives data only when the driver sends a message indicating there is data for the application’s Wintab context. The context can be initialized to capture either raw tablet (Digitizer) data or (System) pixel data. At this point, the application may process the data (e.g. draw a point) and wait for the next message.
With polling data capture, the application uses a non-Wintab message (such as a mouse down or move message) as the trigger to query Wintab for data from the tablet. As the user moves their pen within the tablet’s capture (hover) range, pen data is always being cached. When the app receives the non-Wintab message, the app then has the option of querying for the latest data item or the latest N data items.
Regardless of which type of data capture is used, a Wintab application should register for Wintab messages that notify of key events – such as driver powering down, tablet attach/detach, system display changes, etc. to take steps to preserve its state.
Because each application’s Wintab context is a property managed by the tablet driver’s application support, that context is valid only so long as the driver is running. If the driver is restarted (such as through system reboot) or the application is restarted, then a new Wintab context is generated, and so an application would have to reopen a new Wintab context. Wintab message notifications, as mentioned, help manage such alerts.
Wintab API programming concepts
Default Wintab contexts: Digitizer, System
There are two default Wintab contexts available for applications when initializing for Wintab: Digitizing and System.
The digitizing context (WTI_DDCTXS or WTI_DEFCONTEXT) tells Wintab to deliver pen data packets containing tablet count data to the app when polled for or through a Wintab WT_PACKET message. With digitizing context data, the application has high-resolution streaming pen data that can be used, for example, in fine-grained control of vectors in graphics apps or for biometric information in signature apps. For this context, the user must interpolate the data into the app’s client rectangle.
The system context (WTI_DEFSYSCTX) tells Wintab to deliver pen data packets containing system pixel data (dpi adjusted) to the app when polled for or through a Wintab WT_PACKET message. With system data, it is very easy to make a system call to convert the data into the app’s client rectangle. Such data is ideal for drawing or signature apps.
Context properties
Each of the default Wintab contexts provides a set of properties, returned from a call to WtInfo(), that specifies how pen data is mapped from the tablet to the display, which tablet options are in effect, tablet data rate, stylus button masks, etc. See the Wintab Reference page for a description of all Wintab context properties.
An example of one context option property that is frequently customized is the option (CXO_SYSTEM) that allows the app to move or not move the system cursor with the pen. This is useful for those apps for which moving the system cursor must be customized (such as a signature app).
Another set of context properties that can be modified allows the developer to indicate a portion of the tablet that should send data (e.g. the upper left quadrant, which could be useful in partitioning the tablet for different functions (such as a signature field). See our sample code for many examples of setting the Wintab context.
Setting up to capture desired data (X, Y, Pressure, etc.)
The Wintab application must specify what pen data is expected in the data packets by defining the PACKETDATA macro. This tells the tablet driver how to build the pen data packets to send to the application. Usually, the definition will contain X, Y, and Pressure, but it may also specify pen button data (to indicate which button was pushed), timestamps, pen rotation, pen orientation, etc. See Wintab Reference for details.
Mapping tablet to display
The Wintab context contains definitions for specifying what part of the tablet space is mapped to what part of the system display. By default, the mapping for a display tablet is the entire tablet space to the display monitor, and the mapping for an opaque (non-display) tablet is the entire tablet space to the entire system desktop (over all monitors). In many apps, the defaults are just fine. However, customization may sometimes be needed to control pen input areas and pen output coordinates.
There are three sets of Wintab context properties that are used for this mapping:
- InOrg, InExt – origin and extent (region) of the tablet (in tablet counts) that accepts pen input
- OutOrg, OutExt – origin and extent of tablet tablet counts output for a Digitizing context
- SysOrg, SysExt – origin and extent of system coordinates that are output for a System context
See sample code for examples of using these context settings. Also see Wintab Reference for further details.
Wintab message handling (including message types)
Wintab apps rely on Windows messages to receive data (polling is also supported; see below) and notification of important tablet events. The messages are handled like any other Windows message through the app’s message handling loop.
The following Wintab messages are supported:
- WT_PACKET – Pen data notification (i.e. new pen data is available)
- WT_INFOCHANGE – Tablet configuration (e.g. attach/detach) notification
- WT_PROXIMITY – Pen has come into or gone out of proximity
- WT_CTXOPEN – A Wintab context has opened
- WT_CTXCLOSE – The Wintab context has closed
- WT_CTXUPDATE – The Wintab context has been updated
- WT_CSRCHANGE – A new stylus cursor has come into proximity (e.g. switch to eraser)
- WT_PACKETEXT – Packet notification for Wintab extensions data
When one of these messages comes in, the app may be required to use one of the Wintab functions to get the desired data. For example, on a WT_PACKET message, the app can use WTPacket() to query for the new pen data. The Wintab function WTPacketsGet() may be used to query for a sequence of data packets.
Wintab polling
In addition to message-based notification for getting pen data, an app may decide to use a polling method, where the decision to poll is based on a non-Wintab trigger (such as WM_MOUSEMOVE). This method of data acquisition could be useful in some applications that rely on mouse messages to do extensive graphics processing (such as in OpenGL) and the app simply needs to know the pen pressure at the time of those triggers. The same Wintab methods for getting the data (WTPacket() and WTPacketsGet()) are used as for the pen data notification scenario.
Tablet enumeration
As pointed out, multiple attached tablets can each have their own Wintab context, in which context properties can be adjusted as needed. This is helpful, for example, for applications that need to process data based on tablet extent characteristics.
The following is an example of opening a Digitizing context for multiple tablets:
int ctxIndex = 0;
do
{
LOGCONTEXT lcMine = {0};
int ctx = gpWTInfoA(WTI_DDCTXS + ctxIndex, 0, &lcMine);
… // query for tablet properties; adjust context as needed for this tablet
if (!gpWTOpenA(hWnd, &lcMine, TRUE) { break; /* no more tablets */}
ctxIndex++;
} while (TRUE);
As was mentioned, Wintab also supports a “virtual context”, meaning that there is one context for multiple attached tablets. In this case WTI_DEFCONTEXT would be used and the returned context is an aggregate context for all attached tablets. The virtual context is simpler to program, but may result in unexpected data behavior that does not match the extents of any of the attached tablets (if those tablets are different).
See Wintab ScribbleDemo for an example for each of these enumerations.
Cursor types
Wintab provides a way for the app to distinguish between different stylus cursors. In this context, the word “cursor” takes on a hardware meaning. Devices may have multiple “cursor” types that have different physical configurations, or that have different numbers of buttons, or return auxiliary information, such as pressure information.
To get information about the cursor type, the app would call WTInfo() with the parameter CSR_TYPE. The query response, and how the response can be masked to indicate the cursor type, includes support for these types:
General stylus: (CSR_TYPE & 0x0F06) == 0x0802
Airbrush: (CSR_TYPE & 0x0F06) == 0x0902
Art Pen: (CSR_TYPE & 0x0F06) == 0x0804
Based on the cursor type, the app can implement different behavior (e.g. different cursor).
See Wintab Reference for more information.
Wintab Extensions
Wacom added an extension capability to the original Wintab specification that supports, among other things, the ability for an application to receive notifications when a tablet control is activated. This allows the app to execute custom responses to those notifications, thereby extending the app’s capabilities without having to rebuild the app. Such extension support is limited to certain device hardware input elements; specifically ExpressKeys and TouchRings (supported on Wacom opaque tablets and ExpressKey Remote devices).
The Wintab demo, Wintab Tablet Controls (C++) and ExtensionTestApp within the Wintab .NET (C#) sample package show how to use extensions.
Wintab program fundamentals
Creating a Wintab program to capture pen data is conceptually simple. Essentially, the program must:
- Define a macro specifying what pen data is desired (e.g. X,Y, Pressure, etc.).
- Query the driver to see if it is alive and responding.
- Obtain a Wintab default context (System or Digitizing).
- Modify the context as needed.
- Open a handle to the context.
- Add a Windows message handler for Wintab pen data messages.
- Add Windows message handlers for other Wintab data messages as needed (e.g. tablet attaches).
- Add code to process the pen data (such as performing graphic rendering operations).
- Close the Wintab context handle when done with it.
These points are illustrated in the following code snippets taken from the Wintab ScribbleDemo sample. Note the snippets are very minimal. For in-depth detail, please look at the ScribbleDemo code itself, as well as its accompanying README documentation.
Define a macro specifying what pen data is desired (e.g. X,Y, Pressure, etc.)
The PACKETDATA macro is compiled in by the C++ preprocessor, and is used to set the context lcPktData flag to inform the tablet driver what pen data to send back in Wintab data packets. In this example, the PACKETDATA specifies that pen properties: X, Y, Z, Buttons, NormalPressure, Orientation and Cursor (type) should be returned.
#include < wintab.h >
#define PACKETDATA ( PK_X | PK_Y | PK_Z | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR )
#define PACKETMODE 0
#include < pktdef.h >
HCTX ctx = {0};
...
// Get a default System context
gpWTInfoA( WTI_DEFSYSCTX, 0, &ctx );
...
// Set the PACKETDATA definition to specify required data
ctx.lcPktData = PACKETDATA;
...
Query to see if the driver is alive and responding
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. In the following example, the dynamic construction of this function is used to verify whether the driver is alive.
gpWTInfoA(0, 0, NULL);
Obtain a Wintab default context (System or Digitizing)
A Wintab application must create at least one Wintab context. Get a default context using WTInfo() and use it as a template to create your own tablet context. If using a System context, then only one context (a virtual context) is needed for all attached tablets. If using a Digitizing context, it is optional to set up a single (virtual) context, or to open a context for each attached tablet. The example below obtains a default System context.
LOGCONTEXT
lcMine = {0};
gpWTInfoA(WTI_DEFSYSCTX, 0, &ctx);
Modify the context as needed
Once a default context is obtained, it can be modified to adjust how pen data is delivered (relative or absolute, the extents of the pen coordinates from the tablet and how they map to the display, whether the pen should move the system cursor, etc.). See Wintab Reference for more information on setting up a Wintab context. The example below makes a change to the context lcOptions member allowing the pen to move the system cursor.
lcMine.lcOptions |= CXO_SYSTEM; // move system cursor
Open a handle to the context
Once the context has been obtained and modified as needed, it must be opened. If successful, the call to WTOpen() will return a context handle to the app. That handle is then included with pen data packets and can be used by the app to distinguish data from different tablets.
gpWTOpenA(hWnd, &ctx, TRUE);
Respond to Wintab pen data message
Wintab sends a WT_PACKET message to the app when new pen data is available. The example below shows that the app must query for the data. There are two functions that can be used to query for the data: WTPacket(), which queries for the most recent data as in the sample below, and WTPacketsGet(), which allows the app to query for a range of data.
case WT_PACKET:
{
hctx = (HCTX)lParam;
PACKET pkt = {0};
if (gpWTPacket(hctx, wParam, &pkt))
{
…
ptNew.x = pkt.pkX;
ptNew.y = pkt.pkY;
…
}
}
break;
Respond to other Wintab data messages as needed (e.g. tablet attaches)
In addition to WT_PACKET messages, Wintab sends other messages indicating events that should be handled by the app. See Wintab Reference for more information. For example, the WT_INFOCHANGE message (as shown below) is sent when tablets are attached or detached. When this message is received, the app should tear down and rebuild its Wintab contexts.
case WT_INFOCHANGE:
{
int nAttachedDevices = 0;
gpWTInfoA(WTI_INTERFACE, IFC_NDEVICES, &nAttachedDevices);
// close all current tablet contexts;
// create/open new contexts
…
}
break;
Process the pen data
Process the pen data captured in the WT_PACKET handler to update the UI - for example, to draw the points corresponding to pen movement.
case WM_PAINT:
{
…
POINT newPoint = { ptNew.x, ptNew.y };
… // convert ptNew into client coordinates
LineTo(hDC, newPoint.x, newPoint.y);
…
}
break;
Close the Wintab context handle when done with it
When the app closes (such as on a WM_DESTROY message), clean up by closing all Wintab context handles. Wintab should do this automatically, but it's good practice to do it anyway.
gpWTClose(hCtx);
See Also
Reference - Wintab API Reference document
FAQs – Wintab programming tips
Where to get help
If you have programming questions about the Wintab API, please visit our Support page at: https://developer.wacom.com/developer-dashboard/support