首页 文章

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

提问于
浏览
3

[编辑]这是我迄今为止收集的有关鼠标输入处理的内容 . 请注意,我通过一堆不同的来源和实验学到了这一点,所以不要把它当作福音:1)鼠标事件源于鼠标移动2)SetWindowsHookEx(WH_MOUSE_LL)处理程序LowLevelMouseProc首先看事件3)OS / app框架处理某些高级别的鼠标事件(鼠标光标移动)4)WM_INPUT事件由app事件队列拾取并由WndProc处理(尽管此时处理不会阻止鼠标光标在步骤3中移动) . 5)通过ComponentDispatcher调度消息6)触发PreviewMouseMove和MouseMove事件,并且可以由app处理 .

基于此,我认为确保鼠标光标不移动的唯一方法是通过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

1 回答

  • 3

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

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

相关问题