3

私の目標は単純なものでなければなりません...フォームでクリックイベントを発生させたマウスのデバイスハンドルを取得します(複数のマウスがあります)。

私のフォームでは、パッチを適用しました

    public bool PreFilterMessage(ref Message message) {

...子コントロールが見落とされないようにします(これは正常に機能しています)。

このルーチン内で、デバイス ハンドルを取得するために必要なすべての API を処理するクラスを呼び出しています。

   public bool PreFilterMessage(ref Message message) {
        switch (message.Msg) {
            case 0x0201: //LButtonDown
                int HardwareID = new clsGetInputID().GetDeviceID(message);
                break;
            case 0x204: //RButtonDown
                int HardwareID2 = new clsGetInputID().GetDeviceID(message);
                break;
   }

同じマウスでクリックしても、HardwareID には常に異なる番号が表示されます。

いくつかの定数が正しく設定されていないか、正しくマーシャリングしていない可能性があります。

class clsGetInputID {

    [DllImport("User32.dll")]
    extern static uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
    [DllImport("User32.dll")]
    extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);


    private const int RID_INPUT = 0x10000003;

    [StructLayout(LayoutKind.Sequential)]
    internal struct BUTTONSSTR {
        [MarshalAs(UnmanagedType.U2)]
        public ushort usButtonFlags;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usButtonData;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RAWHID {
        [MarshalAs(UnmanagedType.U4)]
        public int dwSizHid;
        [MarshalAs(UnmanagedType.U4)]
        public int dwCount;
    }
    [StructLayout(LayoutKind.Explicit)]
    internal struct RAWMOUSE {
        [MarshalAs(UnmanagedType.U2)]
        [FieldOffset(0)]
        public ushort usFlags;
        [MarshalAs(UnmanagedType.U4)]
        [FieldOffset(4)]
        public uint ulButtons;
        [FieldOffset(4)]
        public BUTTONSSTR buttonsStr;
        [MarshalAs(UnmanagedType.U4)]
        [FieldOffset(8)]
        public uint ulRawButtons;
        [FieldOffset(12)]
        public int lLastX;
        [FieldOffset(16)]
        public int lLastY;
        [MarshalAs(UnmanagedType.U4)]
        [FieldOffset(20)]
        public uint ulExtraInformation;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RAWKEYBOARD {
        [MarshalAs(UnmanagedType.U2)]
        public ushort MakeCode;
        [MarshalAs(UnmanagedType.U2)]
        public ushort Flags;
        [MarshalAs(UnmanagedType.U2)]
        public ushort Reserved;
        [MarshalAs(UnmanagedType.U2)]
        public ushort VKey;
        [MarshalAs(UnmanagedType.U4)]
        public uint Message;
        [MarshalAs(UnmanagedType.U4)]
        public uint ExtraInformation;
    }
    [StructLayout(LayoutKind.Explicit)]

    internal struct RAWINPUT {
        [FieldOffset(0)]
        public RAWINPUTHEADER header;
        [FieldOffset(16)]
        public RAWMOUSE mouse;
        [FieldOffset(16)]
        public RAWKEYBOARD keyboard;
        [FieldOffset(16)]
        public RAWHID hid;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RAWINPUTHEADER {
        [MarshalAs(UnmanagedType.U4)]
        public int dwType;
        [MarshalAs(UnmanagedType.U4)]
        public int dwSize;
        public IntPtr hDevice;
        [MarshalAs(UnmanagedType.U4)]
        public int wParam;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct RID_DEVICE_INFO_HID {
        [MarshalAs(UnmanagedType.U4)]
        public int dwVendorId;
        [MarshalAs(UnmanagedType.U4)]
        public int dwProductId;
        [MarshalAs(UnmanagedType.U4)]
        public int dwVersionNumber;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsagePage;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsage;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RID_DEVICE_INFO_KEYBOARD {
        [MarshalAs(UnmanagedType.U4)]
        public int dwType;
        [MarshalAs(UnmanagedType.U4)]
        public int dwSubType;
        [MarshalAs(UnmanagedType.U4)]
        public int dwKeyboardMode;
        [MarshalAs(UnmanagedType.U4)]
        public int dwNumberOfFunctionKeys;
        [MarshalAs(UnmanagedType.U4)]
        public int dwNumberOfIndicators;
        [MarshalAs(UnmanagedType.U4)]
        public int dwNumberOfKeysTotal;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RID_DEVICE_INFO_MOUSE {
        [MarshalAs(UnmanagedType.U4)]
        public int dwId;
        [MarshalAs(UnmanagedType.U4)]
        public int dwNumberOfButtons;
        [MarshalAs(UnmanagedType.U4)]
        public int dwSampleRate;
        [MarshalAs(UnmanagedType.U4)]
        public int fHasHorizontalWheel;
    }
    [StructLayout(LayoutKind.Explicit)]
    internal struct RID_DEVICE_INFO {
        [FieldOffset(0)]
        public int cbSize;
        [FieldOffset(4)]
        public int dwType;
        [FieldOffset(8)]
        public RID_DEVICE_INFO_MOUSE mouse;
        [FieldOffset(8)]
        public RID_DEVICE_INFO_KEYBOARD keyboard;
        [FieldOffset(8)]
        public RID_DEVICE_INFO_HID hid;
    }


    public int GetDeviceID(Message message) {
        uint dwSize = 0;

        GetRawInputData(
            message.LParam,
            RID_INPUT,
            IntPtr.Zero,
            ref dwSize,
            (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))
        );

        IntPtr buffer = Marshal.AllocHGlobal((int)dwSize);

        GetRawInputData(
            message.LParam,
            RID_INPUT,
            buffer,
            ref dwSize,
            (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))
        );

        RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(buffer, typeof(RAWINPUT));



        uint size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(RID_DEVICE_INFO));

        GetRawInputDeviceInfo(raw.header.hDevice, 0x2000000b, IntPtr.Zero, ref size);
        IntPtr HardwareRawInfoPTR = Marshal.AllocHGlobal((int)size);
        GetRawInputDeviceInfo(raw.header.hDevice, 0x2000000b, HardwareRawInfoPTR, ref size);

        RID_DEVICE_INFO RawDevInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(HardwareRawInfoPTR, typeof(RID_DEVICE_INFO));

        Marshal.FreeHGlobal(buffer);

        System.Diagnostics.Debug.WriteLine(String.Format("hDevice: {0} HdHandle: {1}", raw.header.hDevice, RawDevInfo.mouse.dwId));

        return RawDevInfo.mouse.dwId;
    }

}

raw.header.hDevice と RawDevInfo.mouse.dwId は常に異なる値です。

誰かが私が間違っていることを見つけることができますか?

4

1 に答える 1

4

いくつかの試行錯誤の後、最終的に問題を解決しました。

理由は完全にはわかりませんが、何らかの理由で、PreFilterMessage() (およびおそらく wndProc) オーバーライドの「マウス ボタン ダウン」メッセージは、デバイス/ハードウェア ID を正しく判断するのに十分な情報を API に提供しません。

代わりに、マウス ボタンの検出をクラスに移動し、このフィルターを通過するすべてのメッセージに対して API を実行しました。

また、デバイス情報をリッスンするには、最初にフォーム ハンドルに対して RegisterRawInputDevices() を呼び出す必要があることも確認しました。

完全な作業コード...

形:

public partial class frmQuizMaster : Form, IMessageFilter {
    clsGetInputID MouseHandler;

//  Initialization
    public frmQuizMaster() {
        InitializeComponent();
        Application.AddMessageFilter(this);
    }

    private void frmQuizMaster_Load(object sender, EventArgs e) {
        MouseHandler = new clsGetInputID(this.Handle);
    }

    private void frmQuizMaster_FormClosing(object sender, FormClosingEventArgs e) {
        Application.RemoveMessageFilter(this);
    }


    public bool PreFilterMessage(ref Message message) {
        int HardID = MouseHandler.GetDeviceID(message);

        if (HardID > 0) {
            System.Diagnostics.Debug.WriteLine("Device ID : " + HardID.ToString());
            //Return true here if you want to supress the mouse click
            //bear in mind that mouse down and up messages will still pass through, so you will need to filter these out and return true also.
        }

        return false;
    }

clsGetInputID:

class clsGetInputID {
    private const int RID_INPUT = 0x10000003;
    private const int RIDEV_INPUTSINK = 0x00000100;

    [DllImport("user32.dll", SetLastError = true)]
    extern static uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
    [DllImport("User32.dll")]
    extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);
    [DllImport("User32.dll")]
    extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);


    [Flags()]
    public enum RawMouseFlags : ushort {
        /// <summary>Relative to the last position.</summary>
        MoveRelative = 0,
        /// <summary>Absolute positioning.</summary>
        MoveAbsolute = 1,
        /// <summary>Coordinate data is mapped to a virtual desktop.</summary>
        VirtualDesktop = 2,
        /// <summary>Attributes for the mouse have changed.</summary>
        AttributesChanged = 4
    }
    [Flags()]
    public enum RawMouseButtons : ushort {
        /// <summary>No button.</summary>
        None = 0,
        /// <summary>Left (button 1) down.</summary>
        LeftDown = 0x0001,
        /// <summary>Left (button 1) up.</summary>
        LeftUp = 0x0002,
        /// <summary>Right (button 2) down.</summary>
        RightDown = 0x0004,
        /// <summary>Right (button 2) up.</summary>
        RightUp = 0x0008,
        /// <summary>Middle (button 3) down.</summary>
        MiddleDown = 0x0010,
        /// <summary>Middle (button 3) up.</summary>
        MiddleUp = 0x0020,
        /// <summary>Button 4 down.</summary>
        Button4Down = 0x0040,
        /// <summary>Button 4 up.</summary>
        Button4Up = 0x0080,
        /// <summary>Button 5 down.</summary>
        Button5Down = 0x0100,
        /// <summary>Button 5 up.</summary>
        Button5Up = 0x0200,
        /// <summary>Mouse wheel moved.</summary>
        MouseWheel = 0x0400
    }


    [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;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct RAWHID {
        [MarshalAs(UnmanagedType.U4)]
        public int dwSizHid;
        [MarshalAs(UnmanagedType.U4)]
        public int dwCount;
    }
    [StructLayout(LayoutKind.Explicit)]
    public struct RawMouse {
        /// <summary>
        /// The mouse state.
        /// </summary>
        [FieldOffset(0)]
        public RawMouseFlags Flags;
        /// <summary>
        /// Flags for the event.
        /// </summary>
        [FieldOffset(4)]
        public RawMouseButtons ButtonFlags;
        /// <summary>
        /// If the mouse wheel is moved, this will contain the delta amount.
        /// </summary>
        [FieldOffset(6)]
        public ushort ButtonData;
        /// <summary>
        /// Raw button data.
        /// </summary>
        [FieldOffset(8)]
        public uint RawButtons;
        /// <summary>
        /// The motion in the X direction. This is signed relative motion or 
        /// absolute motion, depending on the value of usFlags. 
        /// </summary>
        [FieldOffset(12)]
        public int LastX;
        /// <summary>
        /// The motion in the Y direction. This is signed relative motion or absolute motion, 
        /// depending on the value of usFlags. 
        /// </summary>
        [FieldOffset(16)]
        public int LastY;
        /// <summary>
        /// The device-specific additional information for the event. 
        /// </summary>
        [FieldOffset(20)]
        public uint ExtraInformation;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RAWKEYBOARD {
        [MarshalAs(UnmanagedType.U2)]
        public ushort MakeCode;
        [MarshalAs(UnmanagedType.U2)]
        public ushort Flags;
        [MarshalAs(UnmanagedType.U2)]
        public ushort Reserved;
        [MarshalAs(UnmanagedType.U2)]
        public ushort VKey;
        [MarshalAs(UnmanagedType.U4)]
        public uint Message;
        [MarshalAs(UnmanagedType.U4)]
        public uint ExtraInformation;
    }

    public enum RawInputType {
        /// <summary>
        /// Mouse input.
        /// </summary>
        Mouse = 0,
        /// <summary>
        /// Keyboard input.
        /// </summary>
        Keyboard = 1,
        /// <summary>
        /// Another device that is not the keyboard or the mouse.
        /// </summary>
        HID = 2
    }

    [StructLayout(LayoutKind.Explicit)]
    internal struct RawInput {
        /// <summary>Header for the data.</summary>
        [FieldOffset(0)]
        public RawInputHeader Header;
        /// <summary>Mouse raw input data.</summary>
        [FieldOffset(16)]
        public RawMouse Mouse;
        /// <summary>Keyboard raw input data.</summary>
        [FieldOffset(16)]
        public RAWKEYBOARD Keyboard;
        /// <summary>HID raw input data.</summary>
        [FieldOffset(16)]
        public RAWHID Hid;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct RawInputHeader {
        /// <summary>Type of device the input is coming from.</summary>
        public RawInputType Type;
        /// <summary>Size of the packet of data.</summary>
        public int Size;
        /// <summary>Handle to the device sending the data.</summary>
        public IntPtr Device;
        /// <summary>wParam from the window message.</summary>
        public IntPtr wParam;
    }


    public bool LockForBuzzersOnly = true;
    public List<int> BuzzerDevices = new List<int>();


    public int GetDeviceID(Message message) {
        uint dwSize = 0;

        GetRawInputData(
            message.LParam,
            RID_INPUT,
            IntPtr.Zero,
            ref dwSize,
            (uint)Marshal.SizeOf(typeof(RawInputHeader))
        );

        IntPtr buffer = Marshal.AllocHGlobal((int)dwSize);

        GetRawInputData(
            message.LParam,
            RID_INPUT,
            buffer,
            ref dwSize,
            (uint)Marshal.SizeOf(typeof(RawInputHeader))
        );

        RawInput raw = (RawInput)Marshal.PtrToStructure(buffer, typeof(RawInput));
        Marshal.FreeHGlobal(buffer);

        if (raw.Mouse.ButtonFlags == RawMouseButtons.LeftDown || raw.Mouse.ButtonFlags == RawMouseButtons.RightDown) {
            return (int)raw.Header.Device;
        } else {
            return 0;
        }
    }


    public clsGetInputID(IntPtr hwnd) {
        RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];

        rid[0].usUsagePage = 0x01;
        rid[0].usUsage = 0x02;
        rid[0].dwFlags = RIDEV_INPUTSINK;
        rid[0].hwndTarget = hwnd;

        if (!RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0]))) {
            throw new ApplicationException("Failed to register raw input device(s).");
        }
    }
}
于 2013-01-30T14:32:54.553 に答える