Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable mouse promotion

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.

like image 526
Frank im Wald Avatar asked Oct 21 '22 03:10

Frank im Wald


1 Answers

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

  • Use .NET 4.7
  • Change some configuration in your WPF app:

(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.

like image 144
gog Avatar answered Oct 24 '22 01:10

gog