【问题标题】:Passthrough all mouse events but not stylus events传递所有鼠标事件,但不传递触控笔事件
【发布时间】:2015-03-05 02:37:01
【问题描述】:

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

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

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

【问题讨论】:

  • 你说的“手写笔可以在当前屏幕上绘图但正常使用(鼠标)不会中断”是什么意思?您是否正在尝试编写一个响应触控笔并忽略所有鼠标和键盘事件的 WPF 应用程序?
  • 是的,这正是我想要做的!

标签: c# .net wpf


【解决方案1】:

MSDN 上的Disable the RealTimeStylus for WPF Applications 声明:

[...] (WPF) 已内置支持处理 Windows 7 触摸输入 [...] Windows 7 还提供多点触摸输入作为 Win32 WM_TOUCH 窗口消息。 这两个 API 在同一个 HWND 上是互斥的。

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

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

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

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

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

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


原始答案

您可以覆盖 Window 的相应键盘、鼠标和触摸 Preview... 事件处理程序方法并将它们标记为已处理。这具有阻止子控件接收这些事件的效果。

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,因为我认为后者在没有前者的情况下是无关紧要的。我可能还实现了一些不需要处理的东西,我也不确定是否需要调用基本方法。正如我所说,试验直到你得到适合你的东西。

【讨论】:

  • 这个问题是事件不会传递到后面的窗口。当我设置 WS_EX_TRANSPARENT 时,所有鼠标事件都会传递到后面的窗口,而它仍然呈现在顶部(使用 Topmost)。在屏幕截图中,您可以看到我将如何使用手写笔进行绘图,但我仍然希望用户能够使用鼠标和键盘与他们的计算机进行交互
  • @DavidDiaz 哦,我明白了你现在想要完成的事情。我已经用一些替代建议更新了我的答案。
  • 干杯!我想这是我能得到的最好的信息来源,这个问题似乎比最初看起来更复杂。感谢您的帮助!
  • @DavidDiaz 你找到解决这个问题的方法了吗?请问有什么参考吗?我在同一点,使用 WS_EX_TRANSPARENT 我无法获得手写笔事件。
  • @jgd 抱歉,我放弃了 :( 无法正常工作
猜你喜欢
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多