我的 WPF 应用程序中的 WndProc 未“处理”WM_INPUT 事件

2024-03-03

[编辑] 这是迄今为止我收集到的有关鼠标输入处理的信息。请注意,我是通过许多不同的来源和实验了解到这一点的,所以不要将此视为福音: 1)鼠标事件由鼠标移动引发 2) SetWindowsHookEx(WH_MOUSE_LL) 处理程序 LowLevelMouseProc 首先看到事件 3)操作系统/应用程序框架在较高级别处理鼠标事件(鼠标光标移动) 4) WM_INPUT 事件被应用程序事件队列拾取并由 WndProc 处理(尽管此时的处理不会阻止鼠标光标在步骤 3 中移动)。 5)消息通过ComponentDispatcher调度 6) PreviewMouseMove 和 MouseMove 事件被触发并且可以由应用程序处理。

基于此,我认为保证鼠标光标不移动的唯一方法就是通过WH_MOUSE_LL进行过滤。当然,正如我在这篇文章前面提到的,目前没有足够的信息来知道这个鼠标事件来自哪个设备,所以它是全有或全无过滤,这不符合我的要求。


[编辑] 我已经验证我能够通过挂钩 WH_MOUSE_LL 并从处理程序返回大于 0 的值来删除事件。现在我只需要弄清楚如何将 WH_MOUSE_LL 级别生成的鼠标事件与来自我的设备的事件相匹配...

我确实尝试从 WndProc 返回一个大于 0 的值。该事件仍然由我的应用程序处理。


我正在尝试集成一个基于机械 USB 鼠标 Y 轴的旋转输入设备。我希望该设备仅充当原始输入设备,并删除该设备生成的正常鼠标移动事件(至少在我的应用程序的上下文中)。

到目前为止,我已经能够使用 WindowIteropHandler 和 AddHook 将 WndProc 挂接到我的 WPF 应用程序 MainWindow 中。我能够接收 WM_INPUT 事件并从我的特定 USB VID/PID 设备中过滤鼠标事件(足以满足我的需求)。

我希望将消息标记为已处理并返回 0 会导致消息不会传播到 WPF 窗口的其余部分,但事实并非如此...当我移动设备时,我仍然收到 MouseMove 事件。这是我的代码(简化为删除处理 WM_INPUT 消息,但仍然出现相同的问题):

 public partial class MainWindow : Window
{
    private const int WM_INPUT = 0x00FF;

    public MainWindow()
    {
        InitializeComponent();
    }

    public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_INPUT)
        {
            // TODO - figure out why this doesn't halt further processing of this handled event
            handled = true;
        }
        return IntPtr.Zero;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct RAWINPUTDEVICE
    {
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsagePage;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsage;
        [MarshalAs(UnmanagedType.U4)]
        public int dwFlags;
        public IntPtr hwndTarget;
    }

    private const int RIDEV_INPUTSINK = 0x00000100;

    [DllImport("User32.dll")]
    extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);

    private void Window_SourceInitialized(object sender, EventArgs e)
    {
        WindowInteropHelper helper = new WindowInteropHelper(this);
        HwndSource source = HwndSource.FromHwnd(helper.Handle);
        RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];

        rid[0].usUsagePage  = 0x01;
        rid[0].usUsage      = 0x02;
        rid[0].dwFlags      = RIDEV_INPUTSINK; 
        rid[0].hwndTarget   = source.Handle;
        RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0]));

        source.AddHook(WndProc);
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        e.Handled = true;
    }

    private void button1_MouseMove(object sender, MouseEventArgs e)
    {
        e.Handled = true;
    }
}

任何人都知道如何出列或以其他方式阻止我在 WndProc 中处理的鼠标事件传播到 MainWindow?

TIA!

-Matt


经过长时间的谷歌搜索,看起来其他人已经描述并解决了我试图使用 UMDF 做的事情:http://oblita.com/Interception http://oblita.com/Interception

我希望我不必去那里,但看起来这是实际拦截来自特定设备的事件的唯一方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我的 WPF 应用程序中的 WndProc 未“处理”WM_INPUT 事件 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • WPF 绑定 CompositeCollection 中的 MenuItem 不起作用

    我在将命令绑定到复合集合中的菜单项时遇到问题 这MenuItem是其一部分ContextMenu这是定义在UserControl Resources 问题是新标签的绑定不起作用 当我将 MenuItem 放置在复合集合之外时 它将起作用 有
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐