none
Weird values from WM_INPUT RRS feed

  • Question

  • I am trying to get the raw mouse input of the system into a C# application. I am using WM_INPUT (Link 1, URL at the bottom) to get access to the data. To do so I am using the user32.dll. This (Link 2, URL at the bottom) helped me alot with writing the API Wrapper.

    This is the function that registers the mouse:

    public static bool RegisterRawInputMouse()

    {

    RAWINPUTDEVICE[] rawInputDevicesToMonitor = new RAWINPUTDEVICE[1]; RAWINPUTDEVICE device = new RAWINPUTDEVICE(); device.dwFlags = RIDEV_INPUTSINK; device.hwndTarget = Process.GetCurrentProcess().MainWindowHandle; device.usUsage = 0x02; device.usUsagePage = 0x01; rawInputDevicesToMonitor[0] = device; if (!RegisterRawInputDevices(rawInputDevicesToMonitor, 1, (uint)Marshal.SizeOf(new RAWINPUTDEVICE()))) { Console.WriteLine("Registration of device was not successful - Error: " + Marshal.GetLastWin32Error()); return false; } Console.WriteLine("Registration of device was successful"); return true; }

    This is the WndProc function that fetches all of the windows messages of my window:

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x00ff) {
    
            uint dwSize = 40;
    
            byte[] raw = new byte[40];
            GCHandle handle = GCHandle.Alloc(raw, GCHandleType.Pinned);
    
            APIWrapper.GetRawInputData((IntPtr)m.LParam, 0x10000003, handle.AddrOfPinnedObject(), ref dwSize, Marshal.SizeOf(new APIWrapper.RAWINPUTHEADER()));
            
            APIWrapper.RAWINPUT rawData = (APIWrapper.RAWINPUT)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(APIWrapper.RAWINPUT));
    
            if (rawData.header.dwType == 0)
            {
                logMouseX += rawData.mouse.lLastX.ToString() + ", ";
                logMouseY += rawData.mouse.lLastY.ToString() + ", ";
            }
    
            handle.Free();
        }
    
        base.WndProc(ref m);
    }

    There is a problem with rawData.mouse.lLastX and rawData.mouse.lLastY. Unfortunately both values behave a little strange:

    • rawData.mouse.lLastX is 0 when moving the mouse downwards and 65535 when moving the mouse upwards
    • rawData.mouse.lLastY is zero always no matter if I move the mouse left or right

    Might it be that I am messing up something with the typecasts? Or maybe something like a Big-Endian and Little-Endian mix up?

    Links:

    Link 1:
    https://msdn.microsoft.com/en-us/library/windows/desktop/ee418864(v=vs.85).aspx
    
    Link 2:
    http://stackoverflow.com/questions/27866645/registering-a-touch-screen-hid-with-registerrawinputdevices-does-not-work






    • Edited by Boolean Dude Wednesday, August 17, 2016 10:16 PM
    • Moved by Hart Wang Friday, August 19, 2016 5:13 AM
    Wednesday, August 17, 2016 10:12 PM

Answers

  • Show and check the definition of RAWINPUT and RAWMOUSE according to Windows API documentation. In 64-bit mode, I think that the offsets are:

    [StructLayout(LayoutKind.Explicit)]
    internal struct RAWMOUSE
    {
          [FieldOffset(0)]
          public ushort usFlags;
          [FieldOffset(4)]
          public uint ulButtons;
          [FieldOffset(4)]
          public ushort usButtonFlags;
          [FieldOffset(6)]
          public ushort usButtonData;
          [FieldOffset(8)]
          public uint ulRawButtons;
          [FieldOffset(12)]
          public int lLastX;
          [FieldOffset(16)]
          public int lLastY;
          [FieldOffset(20)]
          public uint ulExtraInformation;
    }

    The offset of RAWMOUSE within RAWINPUT is 24.

    • Marked as answer by Boolean Dude Friday, August 19, 2016 12:18 PM
    Thursday, August 18, 2016 10:32 AM

All replies

  • If your program runs in 64-bit mode, then 40 is not enough, since the size of RAWINPUT is 48. Try a larger value or determine the size programmatically using ‘Marshal.SizeOf(typeof(APIWrapper.RAWINPUT))’, or calling GetRawInputData with special null parameters.



    • Edited by Viorel_MVP Thursday, August 18, 2016 4:58 AM
    Thursday, August 18, 2016 4:48 AM
  • Hi Boolean Dude,

    thanks for posting here.

    Seems like your code goes wrong with c# part. I will move  your case to c# forum for better support.

    Your understanding and cooperation will be grateful.

    Best Regards,

    Sera Yu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.

    Thursday, August 18, 2016 8:06 AM
    Moderator
  • Thanks a lot for your answer!

    That was a big mistake I made there actually. You are right, the size of RAWINPUT is 48 not 40. I replaced the hardcoded value for the size whit the size of operation you suggested. Unfortunately the problem is still the same.

    This is how the WndProc function looks like now:

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x00ff) {
    
            uint dwSize = (uint) Marshal.SizeOf(typeof(APIWrapper.RAWINPUT));
    
            byte[] raw = new byte[Marshal.SizeOf(typeof(APIWrapper.RAWINPUT))];
            GCHandle handle = GCHandle.Alloc(raw, GCHandleType.Pinned);
    
            APIWrapper.GetRawInputData((IntPtr)m.LParam, 0x10000003, handle.AddrOfPinnedObject(), ref dwSize, Marshal.SizeOf(new APIWrapper.RAWINPUTHEADER()));
            
            APIWrapper.RAWINPUT rawData = (APIWrapper.RAWINPUT) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(APIWrapper.RAWINPUT));
    
            if (rawData.header.dwType == 0)
            {
                textBox_lastX.Text = rawData.mouse.lLastX.ToString();
                textBox_lastY.Text = rawData.mouse.lLastY.ToString();
            }
    
            handle.Free();
        }
    
        base.WndProc(ref m);
    }

    Thank you so much for your answer again!

    Thursday, August 18, 2016 9:40 AM
  • Show and check the definition of RAWINPUT and RAWMOUSE according to Windows API documentation. In 64-bit mode, I think that the offsets are:

    [StructLayout(LayoutKind.Explicit)]
    internal struct RAWMOUSE
    {
          [FieldOffset(0)]
          public ushort usFlags;
          [FieldOffset(4)]
          public uint ulButtons;
          [FieldOffset(4)]
          public ushort usButtonFlags;
          [FieldOffset(6)]
          public ushort usButtonData;
          [FieldOffset(8)]
          public uint ulRawButtons;
          [FieldOffset(12)]
          public int lLastX;
          [FieldOffset(16)]
          public int lLastY;
          [FieldOffset(20)]
          public uint ulExtraInformation;
    }

    The offset of RAWMOUSE within RAWINPUT is 24.

    • Marked as answer by Boolean Dude Friday, August 19, 2016 12:18 PM
    Thursday, August 18, 2016 10:32 AM
  • Important Edit:

    I logged all of the bytes within the "raw" array and I found out the following:

    Downwards:		Upwards:
    Byte 29: 0 		Byte 29: 0 
    Byte 30: 0 		Byte 30: 0 
    Byte 31: 0 		Byte 31: 0 
    Byte 32: 0 		Byte 32: 0 
    Byte 33: 1 		Byte 33: 255 
    Byte 34: 0 		Byte 34: 255 
    Byte 35: 0 		Byte 35: 255 
    Byte 36: 0 		Byte 36: 255
    
    Left:				Right:
    Byte 29: 255 		Byte 29: 1 
    Byte 30: 255 		Byte 30: 0 
    Byte 31: 255 		Byte 31: 0 
    Byte 32: 255 		Byte 32: 0 
    Byte 33: 0 		Byte 33: 0 
    Byte 34: 0 		Byte 34: 0 
    Byte 35: 0 		Byte 35: 0 
    Byte 36: 0 		Byte 36: 0 

    The faster I move the mouse the bigger (when moving downwards or right) or smaller (when moving upwards or left) the values get.

    So I guess that behaviour is correct like this. Even if I have no idea right now how to process the data, those two double words should provied enough information for further mouse input processing.

    Thanks a lot for your help! The RAWMOUSE offsets you suggested didn't work for me but I think I can figure them out myself. I marked your reply as answer. Thanks again!

    ----------

    Here are the definitions of the two structs:

    [StructLayout(LayoutKind.Explicit)]
    internal struct RAWINPUT
    {
        [FieldOffset(0)]
        public RAWINPUTHEADER header;
    
        [FieldOffset(16 + 8)]
        public RAWMOUSE mouse;
    
        [FieldOffset(16 + 8)]
        public RAWKEYBOARD keyboard;
    
        [FieldOffset(16 + 8)]
        public RAWHID hid;
    }
    [StructLayout(LayoutKind.Explicit)]
    internal struct RAWMOUSE
    {
        [FieldOffset(0)]
        public ushort usFlags;
        [FieldOffset(2)]
        public uint ulButtons;
        [FieldOffset(4)]
        public ushort usButtonFlags;
        [FieldOffset(2)]
        public ushort usButtonData;
        [FieldOffset(6)]
        public uint ulRawButtons;
        [FieldOffset(10)]
        public int lLastX;
        [FieldOffset(14)]
        public int lLastY;
        [FieldOffset(18)]
        public uint ulExtraInformation;
    }

    The RAWINPUT struct should be ok due to I took the field offsets of the MSDN documentation (Link 1, URL at the bottom).

    I tried the values you suggested for the RAWMOUSE struct but then I received zeros only from the last X and last Y fields. I actually have never seen any documentation about the offsets of the RAWMOUSE struct.

    Can't I find out the right offsets when checking the sizes of each datatype? I actually tried that but then I also got zeros only from the last X and last Y fields.

    Links:

    Link 1:
    https://msdn.microsoft.com/de-de/library/windows/desktop/ms645595(v=vs.85).aspx






    Thursday, August 18, 2016 11:16 AM