5

有没有办法从代码中禁用鼠标提升,即防止窗口将触摸事件解释为鼠标事件?

我在我的 WPF 应用程序中捕获触摸事件,并且我不希望这些交互影响鼠标指针的可见性和位置。

有一个TouchFrameEventArgs.SuspendMousePromotionUntilTouchUp 方法似乎就是这样做的。不幸的是,它仅适用于 Silverlight 和 Windows Phone。

此外,还有一些系统设置可以用来禁用双击和右键单击提升,但没有任何东西可以整体禁用鼠标提升。

Windows 8 特定解决方案或低级别解决方案也会有所帮助。

4

3 回答 3

2
public static class PreventTouchToMousePromotion
{

    public static void Register(FrameworkElement root)
    {
        root.PreviewMouseDown += Evaluate;
        root.PreviewMouseMove += Evaluate;
        root.PreviewMouseUp += Evaluate;
    }

    private static void Evaluate(object sender, MouseEventArgs e)
    {
        if (e.StylusDevice != null)
        {
            e.Handled = true;
        }
    }
}

示例用法:

public MainWindow()
    {
        InitializeComponent();
        PreventTouchToMousePromotion.Register(this);
    }

或者看看这个帖子

http://social.msdn.microsoft.com/Forums/vstudio/en-US/9b05e550-19c0-46a2-b19c-40f40c8bf0ec/prevent-a-wpf-application-to-interpret-touch-events-as-mouse-事件?论坛=wpf#9965f159-04a4-41ed-b199-30394991f120

于 2013-10-23T11:14:31.737 回答
1

禁用鼠标触摸提升的普通 Win32 API 方法是处理WM_POINTER*窗口中的消息WindowProc(实际上,这似乎就WM_POINTERDOWN足够了)而不是调用DefWindowProc().

这是我们在一些商业应用程序中实际所做的,也是这里的建议。

这仅适用于 Windows 8 及更高版本,因为WM_POINTER*消息不是由 Windows 7 及更低版本生成的。

现在,在 WPF 世界中,这变得更加复杂。

首先,为了获得WM_POINTER*WPF 堆栈的正确处理,您首先需要

(在这里报告代码,以防MS页面消失)您需要将其插入到您的app.config文件中:

<configuration>
    <runtime>
        <AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/>
    </runtime>
</configuration>

现在,新的闪亮 WPF 堆栈已激活,但即使您处理OnTouchDownOnTouchUpOnTouchMove事件并将Handled标志设置为 true,它也会出现问题并移动鼠标光标。

通过使用 aHwndSourceHook并阻止WM_POINTERDOWN消息,我们发现鼠标光标最终保持静止(尽管我们阻止了所有触地交互!)

因此,我们推断出闪亮的新 WPF 实际上正在调用DefWindowProc,即使我们正在处理OnTouch*事件。

我们的想法是使用Microsoft Detours来拦截DefWindowProc呼叫,并阻止呼叫WM_POINTERDOWN到达真实的DefWindowProc.

绕行代码为:

#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();
}

注意:SetupDefWindowProcDetour必须由应用程序的主 (UI) 线程调用。

于 2020-07-09T12:12:44.120 回答
0

似乎没有任何这样的选项(至少到 Windows 8.1 和 .NET 4.5)。

禁用鼠标提升的唯一方法是完全禁用手指输入,或者从系统控制面板中(打开控制面板,打开“笔和触摸”,选择“触摸”选项卡,禁用“将手指用作输入设备”)或通过注册表(HKLM\Software\Microsoft\Wisp\Touch,TouchGate = 0 =禁用触摸)

然后,您仍然可以使用以下(讨厌的)替代方法之一来处理触摸输入:

最后,您可以使用自定义路由事件或使用触摸注入将收集到的触摸数据注入您的应用程序。

当然,在任何情况下,您都会对系统上的任何其他应用程序失去触控支持,因此该解决方案通常对您没有太大帮助。

于 2013-10-09T09:17:33.623 回答