blob: 334a0eca9741b4ae0905191600e4ada732a15876 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
#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<System::IntPtr>^ 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<MultiHandleDevice^>^ GetList()
{
return ListMaker::MakeList()->AsReadOnly();
}
ref class ListMaker {
List<RawInputDevice^>^ devices = gcnew List<RawInputDevice^>();
delegate void NativeDevHandler(rawinput_device&);
void Add(rawinput_device& dev)
{
devices->Add(Marshal::PtrToStructure<RawInputDevice^>(IntPtr(&dev)));
}
ListMaker() {}
public:
static List<MultiHandleDevice^>^ MakeList()
{
auto maker = gcnew ListMaker();
NativeDevHandler^ del = gcnew NativeDevHandler(maker, &Add);
GCHandle gch = GCHandle::Alloc(del);
auto fp = static_cast<void (*)(rawinput_device&)>(
Marshal::GetFunctionPointerForDelegate(del).ToPointer());
rawinput_foreach(fp);
gch.Free();
auto ret = gcnew List<MultiHandleDevice^>();
auto count = maker->devices->Count;
auto first = 0;
auto last = 0;
if (count > 0) {
maker->devices->Sort(gcnew Comparison<RawInputDevice^>(&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<RawInputDevice^>^ seq)
{
auto it = seq->GetEnumerator();
if (it->MoveNext()) {
name = it->Current->name;
id = it->Current->id;
handles = gcnew List<IntPtr>();
do handles->Add(it->Current->handle); while (it->MoveNext());
}
}
};
|