[编辑] 这是我迄今为止收集到的关于鼠标输入处理的信息。请注意,我已经通过一堆不同的来源和实验了解到这一点,所以不要把它当作福音: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 中。我能够从我的特定 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?
蒂亚!
-马特