有啥方法可以从 WPF 访问鼠标原始输入?

Posted

技术标签:

【中文标题】有啥方法可以从 WPF 访问鼠标原始输入?【英文标题】:Any way to access mouse Raw Input from WPF?有什么方法可以从 WPF 访问鼠标原始输入? 【发布时间】:2012-05-31 15:22:51 【问题描述】:

如果鼠标光标到达屏幕一角,我目前正在使用全局鼠标钩子使应用程序出现。我刚刚读到了原始输入的存在,据我了解,这是一种更强大的方法,因为我的钩子减速不会影响整个系统。

问题是我在任何地方都找不到任何关于在 WPF 中使用原始输入的示例。

我得到的最接近的是 SlimDX,代码如下:

  Device.RegisterDevice(UsagePage.Generic, UsageId.Mouse, 
                        DeviceFlags.None);

  Device.MouseInput += new EventHandler<MouseInputEventArgs>(mouse_MouseInput);

但这似乎在 WPF 中不起作用,只有 winforms。

【问题讨论】:

基本上您需要使用 DllImport 来访问 GetRawInputData 函数并处理 WM_INPUT 消息。这是一个提供良好基础的 CodeProject 链接:codeproject.com/Articles/17123/…。创建此代码项目是为了允许使用多个键盘,但如果您密切注意,您会发现它们在某种程度上也支持鼠标。这不是一个完整的答案,但它是一个好的开始。 谢谢乔希。通过一些工作,我设法在 WPF 应用程序中获取事件,只是发现坐标始终是相对的。不要认为我可以使这项工作适合我的使用。即使我把增量加起来,它们也会偏离现实,因为当光标碰到屏幕边缘时我仍然会得到增量! 【参考方案1】:

那些DeviceFlags.None 需要InputSink 才能在后台捕获输入。 SharpDX 标志实际上有一个 RAWINPUTDEVICEFLAGS (InputSink = 0x00000100) 的包装器。

在 WPF 中,您希望 1) 覆盖 OnSourceInitialized 和 2) 在那里挂钩 WndProc。当窗口指针可用时,您需要定义要观看的 RAWINPUTDEVICE,标记 InputSink

它看起来像

protected override void OnSourceInitialized(EventArgs e)

    base.OnSourceInitialized(e);
    HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
    source.AddHook(WndProc);

    var win = source.Handle;

    RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[2];

    rid[0].UsagePage = (HIDUsagePage)0x01;
    rid[0].Usage = (HIDUsage)0x05;                 // adds game pad
    rid[0].Flags = RawInputDeviceFlags.InputSink;  // accept input in background
    rid[0].WindowHandle = win;

    rid[1].UsagePage = (HIDUsagePage)0x01;
    rid[1].Usage = (HIDUsage)0x04;                 // adds joystick
    rid[1].Flags = RawInputDeviceFlags.InputSink;  // accept input in background
    rid[1].WindowHandle = win;

    if (RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])) == false)
    
        var err = Marshal.GetLastWin32Error();
        if (err > 0)
        
            throw new Win32Exception($"GetLastWin32Error: err");
        
        else
        
            throw new Win32Exception("RegisterRawInputDevices failed with error code 0. Parameter count mis-match?");
        
    


private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)

    switch (msg)
    
        case WM_INPUT:
            
                System.Diagnostics.Debug.WriteLine("Received WndProc.WM_INPUT");
                DoTheThing(lParam);
            
            break;
    
    return hwnd;

【讨论】:

以上是关于有啥方法可以从 WPF 访问鼠标原始输入?的主要内容,如果未能解决你的问题,请参考以下文章

有啥软件可以一个鼠标两台电脑用?

WPF学习第十七章 鼠标输入

WPF 程序鼠标在窗口之外的时候,控件拿到的鼠标位置在哪里?

WPF学习第十七章 鼠标输入

WPF 鼠标按下事件没有坐标

鼠标滚轮在功能区中的列表框上滚动 [WPF]