来自WM_INPUT的奇怪值,投射错误?

时间:2016-08-15 17:17:57

标签: c# casting mouse marshalling windows-messages

关于

我正在尝试将系统的原始鼠标输入到C#应用程序中。我正在使用WM_INPUTMSDN link)来访问数据。为此,我使用的是user32.dll。这个(stackoverflow link)帮助我编写了API Wrapper。

目前的方法

以下代码段显示了WndProc方法。 rimTypeMouseCount已经显示Windows消息似乎正确获取。当我向上或向下转动鼠标的轮询速率时,我也可以通过检查计数来看到这一点 - 较低的轮询速率意味着较低的计数,较高的轮询速率意味着在记录相等的时间间隔时较高的计数。到目前为止,这很好。

WndProc回调方法:

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x00ff) {
        uint dwSize = 40;

        byte[] raw = new byte[40];
        IntPtr rawPtr = Marshal.AllocHGlobal(raw.Length);

        APIWrapper.GetRawInputData((IntPtr)m.LParam, 0x10000003, rawPtr, ref dwSize, Marshal.SizeOf(new APIWrapper.RAWINPUTHEADER()));

        Marshal.Copy(rawPtr, raw, 0, 40);

        GCHandle handle = GCHandle.Alloc(raw, GCHandleType.Pinned);
        APIWrapper.RAWINPUT rawData = (APIWrapper.RAWINPUT)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(APIWrapper.RAWINPUT));
        handle.Free();

        if (rawData.header.dwType == 0)
        {
            rimTypeMouseCount++;
            logMouseX = logMouseX + rawData.mouse.lLastX.ToString() + Environment.NewLine;
            logMouseY = logMouseY + rawData.mouse.lLastY.ToString() + Environment.NewLine;
        }
    }

    base.WndProc(ref m);
}

RAWINPUT结构:

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

问题

logMouseXlogMouseY存在问题。那些字符串只需在每次调用时附加x和y轴的鼠标增量。不幸的是,logMouseX仅记录值0或65535,而logMouseY仅记录0。我还尝试记录鼠标左键等向上/向下等消息。实际上似乎没有任何作用。对我而言,似乎有点数字可能是随机的或类似的东西。

问题

这就是我(我想)做的事情:

  1. APIWrapper.GetRawInputData(...)需要一个指向字节数组的指针。所以我只是通过编组在非托管内存中分配空间并得到一个指针作为结果。
  2. 我正在调用填充指针指向的数组的函数。
  3. 我正在使用指向填充数组的指针并将其内容复制到实际的字节数组中。
  4. 要访问struct RAWINPUT的字段,我需要将字节数组转换为RAWINPUT结构。
  5. 我用三条使用GCHandle的行来做这件事。我实际上在某个地方找到了片段,但之前从未使用过该课程。
  6. 可能是因为我搞乱了吗?也许像Big-Endian和Little-Endian这样的东西混在一起?

    编辑

    • 我发现使用rawData.mouse.lLastX&时得到的值rawData.mouse.lLastY表现得像这样:

      • 向下移动鼠标时X为零,向上移动时为65535
      • 无论是向左还是向右移动鼠标,Y都是零
    • 我发现使用rawDataL.hid.pbRawData包含有关此移动的更多信息。在那里,我得到的值取决于我移动鼠标的速度。不幸的是,没有X或Y组件,所以这只适用于一个轴(向下/向上)。

    • 我发现了一种更简单的演员阵容。不幸的是,我仍然得到如上所述的奇怪值。它现在看起来像这样:

    投射WndProc的一部分:

    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)
    {
        // accessing data
    }
    
    handle.Free();
    

1 个答案:

答案 0 :(得分:0)

我在这里发布了我的问题(MSDN link),我被告知RAWMOUSE结构的偏移量不正确。

所以我只记录原始数据数组的所有字节,最后可以看到我需要的所有数据,因此可以看到正确的偏移量。我想使用32位或64位机器时,偏移量会有所不同。以下是相关的代码更改:

WndProc改变:

RawMouseData rawData = (RawMouseData) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RawMouseData));

RawMouseData struct:

[StructLayout(LayoutKind.Explicit)]
internal struct RawMouseData
{
    [FieldOffset(20)]
    public ButtonFlags buttonFlags;
    [FieldOffset(22)]
    public ushort buttonData;
    [FieldOffset(28)]
    public int lastX;
    [FieldOffset(32)]
    public int lastY;
}

这是每个鼠标移动方向的原始字节数组的数据日志的样子:

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 

我移动鼠标的速度越快(向下或向右移动)或越小(向上或向左移动时)值越大。