jjzjj

c# - 使 GetRawInputDeviceInfo 和 RIDI_DEVICEINFO 与 C# 一起工作

coder 2024-06-13 原文

我遇到的问题是,我似乎无法将 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;
}

关于c# - 使 GetRawInputDeviceInfo 和 RIDI_DEVICEINFO 与 C# 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12260384/

有关c# - 使 GetRawInputDeviceInfo 和 RIDI_DEVICEINFO 与 C# 一起工作的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  4. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  7. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  8. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  9. ruby - JetBrains RubyMine 3.2.4 调试器不工作 - 2

    使用Ruby1.9.2运行IDE提示说需要gemruby​​-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall

  10. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

随机推荐