Is there any way to disable mouse promotion from code, that is preventing windows to interpret touch events as mouse events?
I capture touch events in my WPF application, and I don't want these interactions to effect mouse pointer visibility and position.
There is a TouchFrameEventArgs.SuspendMousePromotionUntilTouchUp Method that seems to be doing exactly that. Unfortunately it's available only for Silverlight and Windows Phone.
In addition there are some system settings you can use to disable double click and right click promotion, but nothing to disable mouse promotion as a whole.
A Windows 8 specific solution or a low level solution would also help.
The plain Win32 API way of disabling touch promotion to mouse is to handle WM_POINTER*
messages in your window's WindowProc
(actually, it seems just WM_POINTERDOWN
is enough) and NOT call DefWindowProc()
.
This is what we actually do in some of our commercial applications, and what is suggested here.
This is ONLY available from Windows 8 and later, since the WM_POINTER*
messages are not generated by Windows 7 and below.
Now, in the WPF world, this gets more complicated.
First of all, in order to get proper WM_POINTER*
handling by the WPF stack, you first need to
(Reporting the code here, just in case the MS page disappears) You need to insert this in your app.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/>
</runtime>
</configuration>
Now the new shiny WPF stack is activated, but it's bugged and moves the mouse cursor even if you handle the OnTouchDown
, OnTouchUp
, OnTouchMove
events and set the Handled
flag to true.
We discovered, through the use of a HwndSourceHook
and blocking the WM_POINTERDOWN
message, that the mouse cursor was finally staying still (although we were blocking all touch-down interactions!)
So, we deducted that the shiny new WPF is actually calling DefWindowProc
, even if we are handling the OnTouch*
events.
Our soultion was to use Microsoft Detours, in order to intercept the DefWindowProc
call, and block the WM_POINTERDOWN
from reaching the real DefWindowProc
.
The detour code is:
#include <Windows.h>
#include <detours.h>
static LRESULT(WINAPI * _originalDefWindowProcA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) = DefWindowProcA;
static LRESULT(WINAPI * _originalDefWindowProcW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) = DefWindowProcW;
static LRESULT WINAPI myDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_POINTERDOWN:
return 0;
default:
return _originalDefWindowProcA(hWnd, Msg, wParam, lParam);
}
}
static LRESULT WINAPI myDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_POINTERDOWN:
return 0;
default:
return _originalDefWindowProcW(hWnd, Msg, wParam, lParam);
}
}
void SetupDefWindowProcDetour()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)_originalDefWindowProcA, myDefWindowProcA);
DetourAttach(&(PVOID&)_originalDefWindowProcW, myDefWindowProcW);
DetourTransactionCommit();
}
NOTE: SetupDefWindowProcDetour
must be called by the main (UI) thread of your app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With