使 GetRawInputDeviceInfo 和 RIDI_DEVICEINFO 与 C# 一起使用

2024-05-26

我有一个问题,我似乎无法使 GetRawInputDeviceInfo 与 RIDI_DEVICEINFO 结合使用(尝试检索 RID_DEVICE_INFO)根本不起作用。

我从函数中得到错误 -1,这意味着没有足够的空间来存储 RID_DEVICE_INFO,我已经尝试将其增加到所需的空间,但效果相同。

我使用了以下 DLLImports :

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

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

两者都没有结果,但是当我使用 RIDI_DEVICENAME 尝试这些时,它们都工作得很好。 在本例中,我这样调用该函数:

首先获取尺寸:GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, IntPtr.Zero, pSize);

进而 :GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, pData, pSize);

得到名字。两者都工作正常,但是当我像这样调用该函数时:

int intReturn = (int)GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICEINFO, IntPtr.Zero, pInfoSize);
intReturn = (int)GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICEINFO, pInfoData, pInfoSize);

然后首先我将 0 放入 intReturn 并且也可以获得正确的大小, 但随后我返回 -1,当我执行 PtrToStructure 时,它​​只是返回错误且看似随机的值。

另外,当我之后执行 GetLastWin32Error() 时,它有时会返回 1008 或 87 ,这对我来说似乎也没有任何逻辑,因为我看不出在哪里可以制作错误的参数。

我将 RIDI_DEVICENAME 和 RIDI_DEVICEINFO 定义为:

internal const uint RIDI_DEVICENAME = 0x20000007;
internal const uint RIDI_DEVICEINFO = 0x2000000b;

任何人都可以帮助解决这个问题或向我展示 GetRawInputDeviceInfo 的有效 C# 示例吗?

谢谢, 彼得


我让它在 Windows 8.1 x64 中工作(如果我在某处错过了枚举或结构,请告诉我):

/// <summary>
/// Retrieves information about the raw input device.
/// </summary>
/// <param name="hDevice">A handle to the raw input device. This comes from the lParam of the WM_INPUT message, from the hDevice member of RAWINPUTHEADER, or from GetRawInputDeviceList. It can also be NULL if an application inserts input data, for example, by using SendInput.</param>
/// <param name="uiCommand">Specifies what data will be returned in pData.</param>
/// <param name="pData">A pointer to a buffer that contains the information specified by uiCommand. If uiCommand is RIDI_DEVICEINFO, set the cbSize member of RID_DEVICE_INFO to sizeof(RID_DEVICE_INFO) before calling GetRawInputDeviceInfo. </param>
/// <param name="pcbSize">The size, in bytes, of the data in pData. </param>
/// <returns>If successful, this function returns a non-negative number indicating the number of bytes copied to pData. If pData is not large enough for the data, the function returns -1. If pData is NULL, the function returns a value of zero. In both of these cases, pcbSize is set to the minimum size required for the pData buffer. Call GetLastError to identify any other errors.</returns>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/ms645597%28v=vs.85%29.aspx</remarks>
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern uint GetRawInputDeviceInfo(
    [In] IntPtr hDevice,
    [In] RawInputDeviceInformationCommand uiCommand,
    [In, Out] IntPtr pData,
    [In, Out] ref uint pcbSize);

public enum RawInputDeviceInformationCommand : int
{
    /// <summary>
    /// pData points to a string that contains the device name. For this uiCommand only, the value in pcbSize is the character count (not the byte count).
    /// </summary>
    RIDI_DEVICENAME = 0x20000007,
    /// <summary>
    /// pData points to an RID_DEVICE_INFO structure.
    /// </summary>
    RIDI_DEVICEINFO = 0x2000000b,
    /// <summary>
    /// pData points to the previously parsed data.
    /// </summary>
    RIDI_PREPARSEDDATA = 0x20000005
}

[StructLayout(LayoutKind.Explicit)]
public struct RID_DEVICE_INFO
{
    /// <summary>
    /// The size, in bytes, of the RID_DEVICE_INFO structure. 
    /// </summary>
    [FieldOffset(0)]
    public int cbSize;
    /// <summary>
    /// The type of raw input data.
    /// </summary>
    [FieldOffset(4)]
    public RawInputDeviceType dwType;
    /// <summary>
    /// If dwType is RIM_TYPEMOUSE, this is the RID_DEVICE_INFO_MOUSE structure that defines the mouse. 
    /// </summary>
    [FieldOffset(8)]
    public RID_DEVICE_INFO_MOUSE mouse;
    /// <summary>
    /// If dwType is RIM_TYPEKEYBOARD, this is the RID_DEVICE_INFO_KEYBOARD structure that defines the keyboard. 
    /// </summary>
    [FieldOffset(8)]
    public RID_DEVICE_INFO_KEYBOARD keyboard;
    /// <summary>
    /// If dwType is RIM_TYPEHID, this is the RID_DEVICE_INFO_HID structure that defines the HID device. 
    /// </summary>
    [FieldOffset(8)]
    public RID_DEVICE_INFO_HID hid;
}
/// <summary>
/// Defines the raw input data coming from the specified mouse.
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/ms645589%28v=vs.85%29.aspx</remarks>
[StructLayout(LayoutKind.Sequential)]
public struct RID_DEVICE_INFO_MOUSE
{
    /// <summary>
    /// The identifier of the mouse device.
    /// </summary>
    public int dwId;
    /// <summary>
    /// The number of buttons for the mouse.
    /// </summary>
    public int dwNumberOfButtons;
    /// <summary>
    /// The number of data points per second. This information may not be applicable for every mouse device.
    /// </summary>
    public int dwSampleRate;
    /// <summary>
    /// TRUE if the mouse has a wheel for horizontal scrolling; otherwise, FALSE.
    /// Windows XP:  This member is only supported starting with Windows Vista.
    /// </summary>
    public bool fHasHorizontalWheel;
}
/// <summary>
/// Defines the raw input data coming from the specified keyboard. 
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/ms645587%28v=vs.85%29.aspx</remarks>
[StructLayout(LayoutKind.Sequential)]
public struct RID_DEVICE_INFO_KEYBOARD
{
    /// <summary>
    /// The type of the keyboard. 
    /// </summary>
    public int dwType;
    /// <summary>
    /// The subtype of the keyboard. 
    /// </summary>
    public int dwSubType;
    /// <summary>
    /// The scan code mode. 
    /// </summary>
    public int dwKeyboardMode;
    /// <summary>
    /// The number of function keys on the keyboard.
    /// </summary>
    public int dwNumberOfFunctionKeys;
    /// <summary>
    /// The number of LED indicators on the keyboard.
    /// </summary>
    public int dwNumberOfIndicators;
    /// <summary>
    /// The total number of keys on the keyboard. 
    /// </summary>
    public int dwNumberOfKeysTotal;
}
/// <summary>
/// Defines the raw input data coming from the specified Human Interface Device (HID). 
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/ms645584%28v=vs.85%29.aspx</remarks>
[StructLayout(LayoutKind.Sequential)]
public struct RID_DEVICE_INFO_HID
{
    /// <summary>
    /// The vendor identifier for the HID. 
    /// </summary>
    public int dwVendorId;
    /// <summary>
    /// The product identifier for the HID. 
    /// </summary>
    public int dwProductId;
    /// <summary>
    /// The version number for the HID. 
    /// </summary>
    public int dwVersionNumber;
    /// <summary>
    /// The top-level collection Usage Page for the device. 
    /// </summary>
    public ushort usUsagePage;
    /// <summary>
    /// The top-level collection Usage for the device. 
    /// </summary>
    public ushort usUsage;
}
/// <summary>
/// The type of raw input data.
/// </summary>
public enum RawInputDeviceType : int
{
    /// <summary>
    /// Data comes from a mouse.
    /// </summary>
    RIM_TYPEMOUSE = 0,
    /// <summary>
    /// Data comes from a keyboard.
    /// </summary>
    RIM_TYPEKEYBOARD = 1,
    /// <summary>
    /// Data comes from an HID that is not a keyboard or a mouse.
    /// </summary>
    RIM_TYPEHID = 2,
}
//somewhere in your code:
IntPtr pData = IntPtr.Zero;
uint strsize = 0;
IntPtr deviceHandle = <your device handle here>;
result = GetRawInputDeviceInfo(deviceHandle, RawInputDeviceInformationCommand.RIDI_DEVICENAME, pData, ref strsize);
pData = Marshal.AllocHGlobal(((int)strsize)*2);
result = GetRawInputDeviceInfo(deviceHandle, RawInputDeviceInformationCommand.RIDI_DEVICENAME, pData, ref strsize);
Console.WriteLine("Result = " + result + " ErrorCode = " + Marshal.GetLastWin32Error());
string name = Marshal.PtrToStringAuto(pData);
Console.WriteLine("Name = " + name);
uint structsize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
RID_DEVICE_INFO di = new RID_DEVICE_INFO();
di.cbSize = (int)structsize;
pData = Marshal.AllocHGlobal((int)structsize);
result = GetRawInputDeviceInfo(deviceHandle, RawInputDeviceInformationCommand.RIDI_DEVICEINFO, pData, ref structsize);
di = (RID_DEVICE_INFO)Marshal.PtrToStructure(pData, typeof(RID_DEVICE_INFO));
Console.WriteLine("di.dwType = " + Enum.GetName(typeof(RawInputDeviceType), di.dwType));
switch (di.dwType)
{
    case RawInputDeviceType.RIM_TYPEHID:
        Console.WriteLine("di.hid.dwVendorId = " + di.hid.dwVendorId);
        Console.WriteLine("di.hid.dwProductId = " + di.hid.dwProductId);
        Console.WriteLine("di.hid.dwVersionNumber = " + di.hid.dwVersionNumber);
        Console.WriteLine("di.hid.usUsagePage = " + di.hid.usUsagePage);
        Console.WriteLine("di.hid.usUsage = " + di.hid.usUsage);
        break;
    case RawInputDeviceType.RIM_TYPEKEYBOARD:
        Console.WriteLine("di.keyboard.dwType = " + di.keyboard.dwType);
        Console.WriteLine("di.keyboard.dwSubType = " + di.keyboard.dwSubType);
        Console.WriteLine("di.keyboard.dwNumberOfFunctionKeys = " + di.keyboard.dwNumberOfFunctionKeys);
        Console.WriteLine("di.keyboard.dwNumberOfIndicators = " + di.keyboard.dwNumberOfIndicators);
        Console.WriteLine("di.keyboard.dwNumberOfKeysTotal = " + di.keyboard.dwNumberOfKeysTotal);
        break;
    case RawInputDeviceType.RIM_TYPEMOUSE:
        Console.WriteLine("di.mouse.dwId = " + di.mouse.dwId);
        Console.WriteLine("di.mouse.dwNumberOfButtons = " + di.mouse.dwNumberOfButtons);
        Console.WriteLine("di.mouse.dwSampleRate = " + di.mouse.dwSampleRate);
        Console.WriteLine("di.mouse.fHasHorizontalWheel = " + di.mouse.fHasHorizontalWheel);
        break;
    default:
        break;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使 GetRawInputDeviceInfo 和 RIDI_DEVICEINFO 与 C# 一起使用 的相关文章

  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • Windows 目录永远不会包含临时文件的非 ASCII 字符?

    在 Windows 上使用 MinGW 7 3 0 由于 Windows 限制 Hunspell 无法从包含非 ASCII 字符的位置加载字典文件 我已经尝试了所有方法 1 现在我将文件复制到没有 ASCII 字符的路径 然后再将其交给 H
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐