Getting Started with Windows Touch Messages



This section explains the tasks associated with getting Windows Touch input to function in your application.

The following steps are typically performed when working with Windows Touch messages:

  1. Test the capabilities of the input digitizer.
  2. Register to receive Windows Touch messages.
  3. Handle the messages.

The message used for Windows Touch is ​WM_TOUCH​. This message indicates the various states of contact with a digitizer.

Testing the Capabilities of the Input Digitizer

The ​​ GetSystemMetrics​​ function can be used to query the capabilities of the input digitizer by passing in the nIndex value of SM_DIGITIZER. ​​ GetSystemMetrics​​ returns a bit field that indicates whether the device is ready, whether the device supports pen or touch, whether the input device is integrated or external, and whether the device supports multiple inputs (Windows Touch). The following table shows the bits for the various fields.

Bit

8

7

6

5

4

3

2

1

Value

Stack Ready

Multi-input

Reserved

Reserved

External Pen

Integrated Pen

External Touch

Integrated Touch

 

To test the result from the command for a particular feature, you can use the bitwise & operator and the particular bit you are testing. For example, to test for Windows Touch, you would test that the seventh-order bit is set (0x40 in hex). The following code example shows how these values could be tested.


C++




#include <windows.h>


C++




// test for touch
int value = GetSystemMetrics(SM_DIGITIZER);
if (value & NID_READY){ /* stack ready */}
if (value & NID_MULTI_INPUT){
/* digitizer is multitouch */
MessageBoxW(hWnd, L"Multitouch found", L"IsMulti!", MB_OK);
}
if (value & NID_INTEGRATED_TOUCH){ /* Integrated touch */}


The following table lists the constants defined in windows.h for testing touch capabilities of the input digitizer.

Name

Value

Description

TABLET_CONFIG_NONE

0x00000000

The input digitizer does not have touch capabilities.

NID_INTEGRATED_TOUCH

0x00000001

An integrated touch digitizer is used for input.

NID_EXTERNAL_TOUCH

0x00000002

An external touch digitizer is used for input.

NID_INTEGRATED_PEN

0x00000004

An integrated pen digitizer is used for input.

NID_EXTERNAL_PEN

0x00000008

An external pen digitizer is used for input.

NID_MULTI_INPUT

0x00000040

An input digitizer with support for multiple inputs is used for input.

NID_READY

0x00000080

The input digitizer is ready for input. If this value is unset, it may mean that the tablet service is stopped, the digitizer is not supported, or digitizer drivers have not been installed.

 

Checking the NID_* values is a useful way of checking the capabilities of a user's computer to configureyour application for touch, pen, or non-tablet input. For example, if you have a dynamic user interface (UI) and want to automatically configure some of it, you could check for NID_INTEGRATED_TOUCH, NID_MULTITOUCH, and could get the maximum number of touches the first time that a user runs your application.

Note   There are some inherent limitations for SM_GETSYSTEMMETRICS. For example, there is no support for plug and play. For this reason, use caution when using this function as a means for permanent configuration.

Registering to Receive Windows Touch Input

Before receiving Windows Touch input, applications must first register to receive Windows Touch input. By registering the application window, the application indicates that it is touch compatible. After the application registers its window, notifications from the Windows Touch driver are forwarded to the application when input is made on the window. When the application shuts down, it unregisters its window to disable notifications.

Note  ​WM_TOUCH​ messages are currently "greedy." After the first touch message is received on a window, all touch messages are sent to that window until another window receives focus.

Note  By default, you receive ​WM_GESTURE​​ messages instead of ​WM_TOUCH​​ messages. If you call ​RegisterTouchWindow​, you will stop receiving WM_GESTURE messages.

The following code demonstrates how an application could register to receive Windows Touch messages in a Win32 application.


C++




RegisterTouchWindow(hWnd, 0);


Handling Windows Touch Messages

You can handle the Windows Touch messages from applications in Windows operating systems in many ways. If you are programming a GUI application, you add code within the ​​WndProc​​ function to handle the messages of interest. If you are programming a Microsoft Foundation Class (MFC) or managed application, you add handlers for the messages of interest. The following code example shows how touch messages could be handled from WndProc in a Windows-based application.


C++




LRESULT OnTouch(HWND hWnd, WPARAM wParam, LPARAM lParam ){
BOOL bHandled = FALSE;
UINT cInputs = LOWORD(wParam);
PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs];
if (pInputs){
if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))){
for (UINT i=0; i < cInputs; i++){
TOUCHINPUT ti = pInputs[i];
//do something with each touch input entry
}
bHandled = TRUE;
}else{
/* handle the error here */
}
delete [] pInputs;
}else{
/* handle the error here, probably out of memory */
}
if (bHandled){
// if you handled the message, close the touch input handle and return
CloseTouchInputHandle((HTOUCHINPUT)lParam);
return 0;
}else{
// if you didn't handle the message, let DefWindowProc handle it
return DefWindowProc(hWnd, WM_TOUCH, wParam, lParam);
}
}


C++




LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
// pass touch messages to the touch handler
case WM_TOUCH:
OnTouch(hWnd, wParam, lParam);
break;


The following code shows how you can implement the message map and a message handler. Note that the messages must be declared in the message map and then the handler for the message should be implemented. For example, in an MFC application, this could be declared in the dialog code. Note also, that the ​​OnInitDialog​​​ function for your dialog window would have to include a call to ​RegisterTouchWindow​​ such as ​​RegisterTouchWindow(m_hWnd, 0)​​.


C++




// Class implementations within a dialog
LRESULT TestDlg::OnTouch( WPARAM wParam, LPARAM lParam ){
//Insert handler code here to do something with the message or uncomment the following line to test
//MessageBox(L"touch!", L"touch!", MB_OK);
return 0;
}
// The message map
BEGIN_MESSAGE_MAP()
ON_WM_CREATE()
... ... ...
ON_MESSAGE(WM_TOUCH, OnTouch)
END_MESSAGE_MAP()

BOOL TestDlg::OnInitDialog()
{
CDialog::OnInitDialog();

RegisterTouchWindow(m_hWnd, 0);
... ... ...
}


Touching the window will indicate touches from a pop-up window.