#include "input.h" using namespace System; using namespace System::Collections::Generic; using namespace System::Runtime::InteropServices; [StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)] public ref struct RawInputDevice { System::IntPtr handle; [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_NAME_LEN)] System::String^ name; [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)] System::String^ id; }; static int CompareByID(RawInputDevice^ x, RawInputDevice^ y) { return String::Compare(x->id, y->id); } public ref struct MultiHandleDevice { System::String^ name; System::String^ id; List^ handles; // Returned list represents the current connected raw input devices, // where each device has a distinct device id // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-ids static IList^ GetList() { return ListMaker::MakeList()->AsReadOnly(); } ref class ListMaker { List^ devices = gcnew List(); delegate void NativeDevHandler(rawinput_device&); void Add(rawinput_device& dev) { devices->Add(Marshal::PtrToStructure(IntPtr(&dev))); } ListMaker() {} public: static List^ MakeList() { auto maker = gcnew ListMaker(); NativeDevHandler^ del = gcnew NativeDevHandler(maker, &Add); GCHandle gch = GCHandle::Alloc(del); auto fp = static_cast( Marshal::GetFunctionPointerForDelegate(del).ToPointer()); rawinput_foreach(fp); gch.Free(); auto ret = gcnew List(); auto count = maker->devices->Count; auto first = 0; auto last = 0; if (count > 0) { maker->devices->Sort(gcnew Comparison(&CompareByID)); while (++last != count) { if (!String::Equals(maker->devices[first]->id, maker->devices[last]->id)) { auto range = maker->devices->GetRange(first, last - first); ret->Add(gcnew MultiHandleDevice(range)); first = last; } } auto range = maker->devices->GetRange(first, last - first); ret->Add(gcnew MultiHandleDevice(range)); } return ret; } }; private: MultiHandleDevice(IEnumerable^ seq) { auto it = seq->GetEnumerator(); if (it->MoveNext()) { name = it->Current->name; id = it->Current->id; handles = gcnew List(); do handles->Add(it->Current->handle); while (it->MoveNext()); } } };