c# - 我的 WPF 应用程序中的 WndProc 不是 'handling' WM_INPUT 事件

标签 c# wpf wndproc

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

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


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

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


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

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

我希望将消息标记为已处理并返回 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!

-马特

最佳答案

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

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

关于c# - 我的 WPF 应用程序中的 WndProc 不是 'handling' WM_INPUT 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11370911/

相关文章:

c# - SHA256哈希计算

c# - 在 Visual Studio 2015 中,可以设置只读自动属性并构建它!这是一个错误吗?

c# - NHibernate:非法尝试将集合与两个打开的 session 关联

c# - 重绘图像 WPF

WPF FrameworkElement 不接收鼠标输入

c# - WPF 设计器代码一直告诉我有错误

winforms - 如何使用 Windows 窗体在窗口标题栏中绘制自定义按钮?

c# - Entity Framework 仅在更新时抛出异常 - 无效的对象名称 'dbo.BirdBrain.service'

c++ - WM_DESTROY 未在包装的 WndProc 中调用

c# - 自定义 WndProc 不会停止调整大小