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

问题描述 投票:3回答:2

[编辑]这是到目前为止我收集的有关鼠标输入处理的内容。请注意,我是通过许多不同的来源和通过实验学到的,所以不要将其当作福音:1)鼠标事件起源于鼠标移动2)SetWindowsHookEx(WH_MOUSE_LL)处理程序LowLevelMouseProc首先看到事件3)OS / app框架在较高级别上处理Mouse事件(鼠标光标移动)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!

-马特

c# wpf wndproc
2个回答
3
投票

经过长时间的谷歌搜索,似乎其他人已经描述并解决了我正在尝试使用UMDF执行的操作:http://oblita.com/Interception

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


0
投票

我也有这个问题,但我可以通过以管理员权限运行应用程序来解决。似乎WM_INPUT消息受UIPI(用户界面特权隔离)的约束。您可以看到链接https://docs.microsoft.com/zh-cn/windows/win32/wintouch/sendmessage--postmessage--and-related-functions的备注。

尽管方法DefWindowProc()会认为它不会处理下一个应用程序的消息。但是,如果有一个以管理员身份运行并专注的应用程序,例如任务管理器,窗口设备管理器等,则较低特权的应用程序无法接收到来自上述应用程序的一些窗口消息。此问题不仅是WN_IPUT,还包括挂钩。

© www.soinside.com 2019 - 2024. All rights reserved.