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