Receiving Input From RawInput Registered Devices In c#

放肆的年华 提交于 2021-02-07 10:50:30

问题


So I have a console application and I've imported RegisterRawInputDevices from user32.dll

You can't register a device onto the console window handler, so I've created a class that inherits from Form. This is also the class that overrides WndProc. Right now all I'm having it do is write message.Msg to the console.

So I instantiate the form and pass the window handler to RegisterRawInputDevices where it registers the mouse and keyboard. But after that the window no longer receives any messages.
Edit: Added some code to show what I'm currently trying.
This is my main method (though I have some other code which keeps the window alive):

Input window = new Input();
PS4Input.RegisterControllers(window.Handle);

This is the class that I use to create the window. Pretty Basic:

public class Input : Form
{
    protected override void WndProc(ref Message message)
    {
        Console.WriteLine(message.Msg);
        base.WndProc(ref message);
    }
}

Here is how I register my device. It currently says that it works.

[DllImport("User32.dll", SetLastError = true)]
extern static uint GetRawInputDeviceList(IntPtr pRawInputDeviceList, ref uint uiNumDevices, uint cbSize);

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

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, ref DeviceInfo pData, ref uint pcbSize);

[DllImport("user32.dll", SetLastError = true)]
static extern bool RegisterRawInputDevices(RawInputDevice[] pRawInputDevice, uint numberDevices, uint size);

[DllImport("user32.dll", SetLastError = true)]
internal extern static uint GetRegisteredRawInputDevices(RawInputDevice[] pRawInputDevice, ref uint puiNumDevices, uint cbSize);

public static void RegisterControllers(IntPtr hwnd)
{
    uint deviceCount = 0;
    int dwSize = Marshal.SizeOf(typeof(RawInputDeviceList));

    if (GetRawInputDeviceList(IntPtr.Zero, ref deviceCount, (uint)dwSize) == 0)
    {
        IntPtr pRawInputDeviceList = Marshal.AllocHGlobal((int)(dwSize * deviceCount));
        GetRawInputDeviceList(pRawInputDeviceList, ref deviceCount, (uint)dwSize);

        for (int i = 0; i < deviceCount; i++)
        {
            RawInputDeviceList rid = (RawInputDeviceList)Marshal.PtrToStructure(new IntPtr(pRawInputDeviceList.ToInt32() + (dwSize * i)), typeof(RawInputDeviceList));

            uint size = (uint)Marshal.SizeOf(typeof(DeviceInfo));
            var di = new DeviceInfo { Size = Marshal.SizeOf(typeof(DeviceInfo)) };

            GetRawInputDeviceInfo(rid.hDevice, (uint)RawInputDeviceInfo.RIDI_DEVICEINFO, ref di, ref size);

            if (di.Type == DeviceType.RimTypeHid && di.HIDInfo.Usage == (ushort)HidUsage.Gamepad && di.HIDInfo.UsagePage == (ushort)HidUsagePage.GENERIC)
            {
                var device = new RawInputDevice();
                Console.WriteLine("Registering Device");

                device.UsagePage = di.HIDInfo.UsagePage;
                device.Usage = (ushort)HidUsage.Keyboard;
                device.Flags = RawInputDeviceFlags.INPUTSINK;
                device.Target = hwnd;

                RawInputDevice[] devices = new RawInputDevice[1];
                devices[0] = device;

                if (RegisterRawInputDevices(devices, (uint)devices.Length, (uint)Marshal.SizeOf(typeof(RawInputDevice))) == false)
                {
                    Console.WriteLine("Failure");
                    return;
                }
                else
                {
                    Console.WriteLine("Success!");
                }
                break;
            }
        }

        Marshal.FreeHGlobal(pRawInputDeviceList);
    }
    else
    {
        Console.WriteLine(Marshal.GetLastWin32Error());
    }
}

[StructLayout(LayoutKind.Sequential)]
internal struct RawInputDevice
{
    internal ushort UsagePage;
    internal ushort Usage;
    internal RawInputDeviceFlags Flags;
    internal IntPtr Target;

    public override string ToString()
    {
        return string.Format("{0}/{1}, flags: {2}, target: {3}", UsagePage, Usage, Flags, Target);
    }
}

[StructLayout(LayoutKind.Sequential)]
internal struct RawInputDeviceList
{
    public IntPtr hDevice;
    public uint dwType;
}

[StructLayout(LayoutKind.Explicit)]
public struct DeviceInfo
{
    [FieldOffset(0)]
    public int Size;
    [FieldOffset(4)]
    public int Type;

    [FieldOffset(8)]
    public DeviceInfoMouse MouseInfo;
    [FieldOffset(8)]
    public DeviceInfoKeyboard KeyboardInfo;
    [FieldOffset(8)]
    public DeviceInfoHid HIDInfo;

    public override string ToString()
    {
        return string.Format("DeviceInfo\n Size: {0}\n Type: {1}\n", Size, Type);
    }
}

回答1:


Not enough details, but i think that your code look like this:

public static void Main(string[] args)
{
    MyClass messageReciever = new MyClass();
    messageReciever.StartRecievingMessages();
    Console.WriteLine("Press Q to exit...");
    while (Console.ReadKey(true).Key != ConsoleKey.Q) { }
}

Add the [STAThread] to your entry point to keep window alive:

[STAThread]
public static void Main(string[] args)

UPDATE: I have a solution for you my friend! In program entry you need add this:

Application.Run(window);

And also in Input class override OnShow (to hide window when it appear):

protected override void OnShown(EventArgs e)
{
    base.OnShown(e);
    Hide();
}

The reason is that the Form must first get the focus, only then Flag-"keep capturing in background" works.



来源:https://stackoverflow.com/questions/41886124/receiving-input-from-rawinput-registered-devices-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!