3

[編集]これまでにマウス入力の処理について収集した内容は次のとおりです。私はこれをさまざまなソースと実験を通じて学んだので、これを福音と見なさないでください:1)マウスイベントはマウスの動きで発生します2)SetWindowsHookEx(WH_MOUSE_LL)ハンドラーLowLevelMouseProcは最初にイベントを確認します3)OS / appフレームワークはマウスイベントを高レベルで処理します(マウスカーソルの移動)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!

-マット

4

2 に答える 2

3

グーグルで長時間過ごした後、UMDFを使用して私がやろうとしていることを他の誰かがすでに説明して解決しているようです:http://oblita.com/Interception

そこに行かなくてもいいと思っていたのですが、特定のデバイスからのイベントを実際に傍受する唯一の方法のようです。

于 2012-07-20T16:10:00.353 に答える
2

私もこの問題を抱えていました。管理者権限でアプリケーションを実行することで問題を解決しました。

WM_INPUTメッセージはUIPI(ユーザーインターフェイス特権の分離)の対象になっているようです。ここでリファレンスをチェックしてください:

SendMessage、PostMessage、および関連関数

メソッドDefWindowProc()はメッセージを配信しますが、次のアプリケーションにメッセージを処理しません。ただし、などのように管理者として実行されているアプリケーションがある場合、Task Manager権限Window Device Managerの低いアプリケーションは、上記のアプリケーションから配信されたウィンドウメッセージの一部を受信できません。この問題は、だけでなく、WN_IPUT他にもありHookます。

于 2019-11-01T01:48:14.150 に答える