c# - 传递所有鼠标事件,但不传递手写笔事件

标签 c# .net wpf

我正在制作一个供个人使用的应用程序,其中可以使用手写笔在当前屏幕上绘图,但不会中断正常使用(使用鼠标)。

目前,我正在尝试使用 WS_EX_TRANSPARENT 设置窗口以允许鼠标事件通过,但似乎手写笔事件也可以通过而不被捕获。

是否有任何其他方法可以用来传递鼠标/键盘事件,同时仍然允许手写笔事件?这是我的程序到目前为止的样子:

Example picture

最佳答案

Disable the RealTimeStylus for WPF Applications MSDN 上指出:

[...] (WPF) has built in support for processing Windows 7 touch input [...] Windows 7 also provides multi-touch input as Win32 WM_TOUCH window messages. These two APIs are mutually exclusive on the same HWND.

这似乎意味着,对于给定的窗口,您可以接收手写笔事件或触摸事件,但不能同时接收两者。由于您确实想要处理手写笔事件,这意味着您无需费心过滤触摸事件。只剩下鼠标和键盘了。

起初我以为您可以使用自定义窗口过程(WndProc)并过滤掉鼠标和键盘消息。但是,WndProc(在 WPF 中使用时)实际上只是一种通知机制,您无法阻止接收到的消息。

我发现了一个名为 BlockInput 的 Windows API据说“阻止键盘和鼠标输入事件到达应用程序”。然而,从文档来看,这似乎是系统范围的而不是特定于应用程序的,因此可能对您没有任何用处。

我能想到的唯一其他方法是使用低级键盘或鼠标 Hook 。这需要一些 P/Invoke,但并不是太困难。这些 Hook 允许您注册在引发键盘和鼠标事件时调用的回调函数。优点是您可以阻止这些事件传播并有效地“吞噬”它们,这听起来正是您所需要的。

我不太喜欢发布一个基本上是“搜索...”的答案,但所涉及的代码量并不小,并且已发布在 Stack Overflow 和其他地方的许多地方,因此:尝试搜索low level Keyboard hook c# wpf,您应该会找到一些可能有帮助的代码!

即使您走这条路,您也可能会遇到麻烦的一件事是焦点。一旦您的“不可见”最顶层窗口收到它响应的手写笔消息,我假设焦点将切换到您的 WPF 应用程序,从而从之前使用的任何应用程序中“窃取”焦点。您也许可以再次使用 P/Invoke 设置主窗口的窗口样式标志以防止出现这种情况(根据 this SO question 的接受答案)。


原始答案

您可以重写窗口的相应键盘、鼠标和触摸预览...事件处理程序方法,并将它们标记为已处理。这具有阻止子控件接收这些事件的效果。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        e.Handled = true;
        base.OnPreviewKeyDown(e);
    }

    protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
    {
        e.Handled = true;
        base.OnPreviewMouseDown(e);
    }

    protected override void OnPreviewMouseMove(MouseEventArgs e)
    {
        e.Handled = true;
        base.OnPreviewMouseMove(e);
    }

    protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
    {
        e.Handled = true;
        base.OnPreviewMouseWheel(e);
    }

    protected override void OnPreviewTouchDown(TouchEventArgs e)
    {
        e.Handled = true;
        base.OnPreviewTouchDown(e);
    }

    protected override void OnPreviewTouchMove(TouchEventArgs e)
    {
        e.Handled = true;
        base.OnPreviewTouchMove(e);
    }
}

我在这里完成了基本的键盘、鼠标和触摸事件。在一个简单的应用程序测试中,它似乎做到了这一点,我认为它仍然会让手写笔事件通过(我没有可以测试的手写笔)。

您可能必须尝试哪些事件需要这样处理。例如,我只做了KeyDown,而不是KeyUp,因为我认为如果没有前者,后者是不相关的。我可能还实现了一些不需要处理的内容,并且我不确定是否需要调用基本方法。正如我所说,不断尝试,直到找到适合您的东西。

关于c# - 传递所有鼠标事件,但不传递手写笔事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28869048/

相关文章:

c# - HttpWebRequest 与从 javascript 动态生成 html 的页面?

c# - 从通用平面获取轴对齐坐标

c# - 如何阻止MediaPlayer每次启动?

c# - 类中的 AutoFixture 设置界面属性

.net - 为什么子不能同时实现接口(interface)和处理事件?

c# - 如何刷新wpf数据触发器?

wpf - 使用 Visual Studio 2012 在 wpf 工具包中找不到 AutoCompleteBox

c# - 如何让 ToolTip 绑定(bind)与 ComboBox 一起工作?

C# 设计模式 - 与 Base 交互

c# - 我可以在 WPF 中即时创建图标吗?