A customer had a program which responded to left mouse clicks, but they found that when used with a touch screen, when users touched the screen, the WM_LBUTTONDOWN message didn’t arrive until the users lifted their fingers from the screen. They wanted to know whether this was by design, and also whether there was a way to get the WM_LBUTTONDOWN message as soon as the finger touches the screen.
Yes, this behavior is by design. The system is waiting to see whether the user is making a press-and-hold gesture. If so, then the touch events are converted to right-mouse-button messages (WM_RBUTTONDOWN and WM_RBUTTONUP). But if the finger does not remain in contact for a long time, then the touch events are converted to left-mouse-button messages (WM_LBUTTONDOWN and WM_LBUTTONUP).
The customer’s program was targeting Windows 7, so they were looking for solutions that would work on that platform.
Take our scratch program and add the following:
#include <strsafe.h> // StringCchPrintf
#include <tpcshrd.h> // WM_TABLET_QUERYSYSTEMGESTURESTATUS
BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
g_hwndChild = CreateWindow(TEXT("listbox"), NULL,
LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_VSCROLL,
0, 0, 0, 0, hwnd, NULL, g_hinst, 0);
return TRUE;
}
void
OnSize(HWND hwnd, UINT state, int cx, int cy)
{
if (g_hwndChild) {
MoveWindow(g_hwndChild, 0, 0, cx, cy/2, TRUE);
}
}
LRESULT CALLBACK
WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
...
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
{
TCHAR buffer[80];
StringCchPrintf(buffer, 80, TEXT("%04x %d %d"), uiMsg,
GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
ListBox_AddString(g_hwndChild, buffer);
}
break;
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
return TABLET_DISABLE_PRESSANDHOLD;
...
}
Most of this code is just creating a logging window so we can see the message traffic. (Note that we divide cy by 2 in the OnSize function so that there is room at the bottom of the window for touch activity.)
The interesting part is adding a handler for the WM_TABLET_QUERYSYSTEMGESTURESTATUS message and responding that we want to disable press-and-hold.
This successfully disables the press-and-hold gesture on Tablet PC (remember that?), allowing the left-button messages to be generated immediately upon contact. But it doesn’t help for Windows 7 and above. For that, we need something else:
BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
g_hwndChild = CreateWindow(TEXT("listbox"), NULL,
LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_VSCROLL,
0, 0, 0, 0, hwnd, NULL, g_hinst, 0);
GESTURECONFIG config;
config.dwID = 0;
config.dwWant = 0;
config.dwBlock = GC_ALLGESTURES;
SetGestureConfig(hwnd, 0, 1, &config, sizeof(config));
return TRUE;
}
This time, we disable all gestures using SetGestureConfig. This takes care of Windows 7 and higher.
So there are your options: There’s a “Windows XP and Windows Vista” solution, and there’s a “Windows 7 and higher” solution. Or you can just play it safe and use both.
0 comments