回答編集履歴
2
主目的はマウスだったのを取り違えていた
test
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
Raw Input API を使うとハードウエアで
|
1
|
+
Raw Input API を使うとハードウエアで操作されたか、ソフトウエアで操作されたかを判別できるようです。
|
2
2
|
|
3
3
|
RegisterRawInputDevices API でウインドウを登録すると、WM_INPUT メッセージがウインドウに飛んでくるので GetRawInputData API で LPARAM から情報を取り出します。
|
4
4
|
|
5
5
|
取り出した RAWINPUTHEADER 構造体の hDevice メンバにデバイスハンドルが入ってくるのですが、ソフトウエアから入力された場合は、ゼロになっています。
|
6
6
|
|
7
|
-
Python はわからないので C# Windows Forms アプリケーションのコードを載せておきます。
|
7
|
+
Python はわからないので C# Windows Forms アプリケーションのコードを載せておきます。(キーボードとマウスボタンを検出)
|
8
|
-
|
8
|
+
|
9
|
-
あくまで
|
9
|
+
あくまで変更されたタイミングが分かるだけなので、現在押されているかどうかは、状態を管理してください。
|
10
10
|
|
11
11
|
```csharp
|
12
12
|
using System;
|
@@ -120,11 +120,63 @@
|
|
120
120
|
public int ExtraInformation;
|
121
121
|
}
|
122
122
|
|
123
|
+
[Flags()]
|
124
|
+
private enum RawMouseButtons : short
|
125
|
+
{
|
126
|
+
None = 0,
|
127
|
+
LeftDown = 0x0001,
|
128
|
+
LeftUp = 0x0002,
|
129
|
+
RightDown = 0x0004,
|
130
|
+
RightUp = 0x0008,
|
131
|
+
MiddleDown = 0x0010,
|
132
|
+
MiddleUp = 0x0020,
|
133
|
+
Button4Down = 0x0040,
|
134
|
+
Button4Up = 0x0080,
|
135
|
+
Button5Down = 0x0100,
|
136
|
+
Button5Up = 0x0200,
|
137
|
+
MouseWheel = 0x0400
|
138
|
+
}
|
139
|
+
|
140
|
+
[Flags()]
|
141
|
+
public enum RawMouseFlags : short
|
142
|
+
{
|
143
|
+
MoveRelative = 0,
|
144
|
+
MoveAbsolute = 1,
|
145
|
+
VirtualDesktop = 2,
|
146
|
+
AttributesChanged = 4
|
147
|
+
}
|
148
|
+
|
149
|
+
[StructLayout(LayoutKind.Explicit)]
|
150
|
+
private struct RowMouseData
|
151
|
+
{
|
152
|
+
[FieldOffset(0)]
|
153
|
+
public int Buttons;
|
154
|
+
[FieldOffset(2)]
|
155
|
+
public short ButtonData;
|
156
|
+
[FieldOffset(0)]
|
157
|
+
public RawMouseButtons ButtonFlags;
|
158
|
+
}
|
159
|
+
|
123
160
|
[StructLayout(LayoutKind.Sequential)]
|
161
|
+
private struct RAWMOUSE
|
162
|
+
{
|
163
|
+
public RawMouseFlags Flags;
|
164
|
+
public RowMouseData Data;
|
165
|
+
public int RawButtons;
|
166
|
+
public int LastX;
|
167
|
+
public int LastY;
|
168
|
+
public int ExtraInformation;
|
169
|
+
}
|
170
|
+
|
171
|
+
[StructLayout(LayoutKind.Explicit)]
|
124
172
|
private struct RAWINPUT
|
125
173
|
{
|
174
|
+
[FieldOffset(0)]
|
126
175
|
public RAWINPUTHEADER Header;
|
176
|
+
[FieldOffset(16)]
|
127
177
|
public RAWKEYBOARD Keyboard;
|
178
|
+
[FieldOffset(16)]
|
179
|
+
public RAWMOUSE Mouse;
|
128
180
|
}
|
129
181
|
|
130
182
|
[DllImport("user32.dll")]
|
@@ -150,11 +202,18 @@
|
|
150
202
|
protected override void OnHandleCreated(EventArgs e)
|
151
203
|
{
|
152
204
|
base.OnHandleCreated(e);
|
205
|
+
|
153
|
-
RAWINPUTDEVICE[] rawInputDevices = new RAWINPUTDEVICE[
|
206
|
+
RAWINPUTDEVICE[] rawInputDevices = new RAWINPUTDEVICE[2];
|
207
|
+
|
154
208
|
rawInputDevices[0].usUsagePage = HIDUsagePage.Generic;
|
155
209
|
rawInputDevices[0].usUsage = HIDUsage.Keyboard;
|
156
|
-
rawInputDevices[0].dwFlags = RawInputDeviceFlags.InputSink
|
210
|
+
rawInputDevices[0].dwFlags = RawInputDeviceFlags.InputSink;
|
157
211
|
rawInputDevices[0].hwndTarget = Handle;
|
212
|
+
|
213
|
+
rawInputDevices[1].usUsagePage = HIDUsagePage.Generic;
|
214
|
+
rawInputDevices[1].usUsage = HIDUsage.Mouse;
|
215
|
+
rawInputDevices[1].dwFlags = RawInputDeviceFlags.InputSink;
|
216
|
+
rawInputDevices[1].hwndTarget = Handle;
|
158
217
|
|
159
218
|
var result = RegisterRawInputDevices(rawInputDevices,
|
160
219
|
rawInputDevices.Length,
|
@@ -179,24 +238,52 @@
|
|
179
238
|
if (GetRawInputData(m.LParam, RawInputCommand.Input, buffer, ref dwSize,
|
180
239
|
Marshal.SizeOf(typeof(RAWINPUTHEADER))) == dwSize)
|
181
240
|
{
|
182
|
-
RAWINPUT
|
241
|
+
RAWINPUT raw = Marshal.PtrToStructure<RAWINPUT>(buffer);
|
183
|
-
if (
|
242
|
+
if (raw.Header.hDevice == IntPtr.Zero)
|
184
243
|
{
|
244
|
+
Debug.WriteLine("ソフトウエアだよ!");
|
245
|
+
}
|
246
|
+
else
|
247
|
+
{
|
185
|
-
i
|
248
|
+
switch (raw.Header.dwType)
|
186
249
|
{
|
250
|
+
case RawInputType.Keyboard:
|
251
|
+
if (raw.Keyboard.Flags.HasFlag(RawKeyboardFlags.Break))
|
252
|
+
{
|
187
|
-
Debug.WriteLine("
|
253
|
+
Debug.WriteLine($"キーが離されました: {(Keys)raw.Keyboard.VKey}");
|
188
|
-
}
|
254
|
+
}
|
189
|
-
else
|
255
|
+
else
|
190
|
-
{
|
256
|
+
{
|
191
|
-
|
257
|
+
Debug.WriteLine($"キーが押されました: {(Keys)raw.Keyboard.VKey}");
|
258
|
+
}
|
259
|
+
break;
|
260
|
+
|
261
|
+
case RawInputType.Mouse:
|
192
|
-
if (raw.
|
262
|
+
if (raw.Mouse.Data.ButtonFlags.HasFlag(RawMouseButtons.LeftDown))
|
193
|
-
{
|
263
|
+
{
|
194
|
-
Debug.WriteLine($"
|
264
|
+
Debug.WriteLine($"左ボタンが押されました");
|
195
|
-
}
|
265
|
+
}
|
196
|
-
else
|
266
|
+
if (raw.Mouse.Data.ButtonFlags.HasFlag(RawMouseButtons.LeftUp))
|
197
|
-
{
|
267
|
+
{
|
198
|
-
Debug.WriteLine($"
|
268
|
+
Debug.WriteLine($"左ボタンが離されました");
|
199
|
-
}
|
269
|
+
}
|
270
|
+
if (raw.Mouse.Data.ButtonFlags.HasFlag(RawMouseButtons.RightDown))
|
271
|
+
{
|
272
|
+
Debug.WriteLine($"右ボタンが押されました");
|
273
|
+
}
|
274
|
+
if (raw.Mouse.Data.ButtonFlags.HasFlag(RawMouseButtons.RightUp))
|
275
|
+
{
|
276
|
+
Debug.WriteLine($"右ボタンが離されました");
|
277
|
+
}
|
278
|
+
if (raw.Mouse.Data.ButtonFlags.HasFlag(RawMouseButtons.MiddleDown))
|
279
|
+
{
|
280
|
+
Debug.WriteLine($"中ボタンが押されました");
|
281
|
+
}
|
282
|
+
if (raw.Mouse.Data.ButtonFlags.HasFlag(RawMouseButtons.MiddleUp))
|
283
|
+
{
|
284
|
+
Debug.WriteLine($"中ボタンが離されました");
|
285
|
+
}
|
286
|
+
break;
|
200
287
|
}
|
201
288
|
}
|
202
289
|
}
|
@@ -211,5 +298,3 @@
|
|
211
298
|
}
|
212
299
|
```
|
213
300
|
|
214
|
-
|
215
|
-
|
1
RawKeyboardFlags の判定が誤っていた
test
CHANGED
@@ -17,47 +17,107 @@
|
|
17
17
|
|
18
18
|
public partial class Form1 : Form
|
19
19
|
{
|
20
|
-
private const int RID_INPUT = 0x10000003;
|
21
|
-
private const int RIM_TYPEKEYBOARD = 1;
|
22
|
-
private const int RIDEV_INPUTSINK = 0x00000100;
|
23
|
-
private const int RIDEV_NOLEGACY = 0x00000030;
|
24
20
|
private const int WM_INPUT = 0x00FF;
|
25
21
|
|
22
|
+
private enum HIDUsagePage : short
|
23
|
+
{
|
24
|
+
Undefined = 0x00,
|
25
|
+
Generic = 0x01,
|
26
|
+
Simulation = 0x02,
|
27
|
+
VR = 0x03,
|
28
|
+
Sport = 0x04,
|
29
|
+
Game = 0x05,
|
30
|
+
Keyboard = 0x07,
|
31
|
+
LED = 0x08,
|
32
|
+
Button = 0x09,
|
33
|
+
Ordinal = 0x0A,
|
34
|
+
Telephony = 0x0B,
|
35
|
+
Consumer = 0x0C,
|
36
|
+
Digitizer = 0x0D,
|
37
|
+
PID = 0x0F,
|
38
|
+
Unicode = 0x10,
|
39
|
+
AlphaNumeric = 0x14,
|
40
|
+
Medical = 0x40,
|
41
|
+
MonitorPage0 = 0x80,
|
42
|
+
MonitorPage1 = 0x81,
|
43
|
+
MonitorPage2 = 0x82,
|
44
|
+
MonitorPage3 = 0x83,
|
45
|
+
PowerPage0 = 0x84,
|
46
|
+
PowerPage1 = 0x85,
|
47
|
+
PowerPage2 = 0x86,
|
48
|
+
PowerPage3 = 0x87,
|
49
|
+
BarCode = 0x8C,
|
50
|
+
Scale = 0x8D,
|
51
|
+
MSR = 0x8E
|
52
|
+
}
|
53
|
+
|
54
|
+
private enum HIDUsage : short
|
55
|
+
{
|
56
|
+
Pointer = 0x01,
|
57
|
+
Mouse = 0x02,
|
58
|
+
Joystick = 0x04,
|
59
|
+
Gamepad = 0x05,
|
60
|
+
Keyboard = 0x06,
|
61
|
+
Keypad = 0x07,
|
62
|
+
}
|
63
|
+
|
64
|
+
[Flags()]
|
65
|
+
public enum RawInputDeviceFlags
|
66
|
+
{
|
67
|
+
None = 0,
|
68
|
+
Remove = 0x00000001,
|
69
|
+
Exclude = 0x00000010,
|
70
|
+
PageOnly = 0x00000020,
|
71
|
+
NoLegacy = 0x00000030,
|
72
|
+
InputSink = 0x00000100,
|
73
|
+
CaptureMouse = 0x00000200,
|
74
|
+
NoHotKeys = 0x00000200,
|
75
|
+
AppKeys = 0x00000400
|
76
|
+
}
|
77
|
+
|
26
78
|
[StructLayout(LayoutKind.Sequential)]
|
27
79
|
private struct RAWINPUTDEVICE
|
28
80
|
{
|
29
|
-
public
|
81
|
+
public HIDUsagePage usUsagePage;
|
30
|
-
public
|
82
|
+
public HIDUsage usUsage;
|
31
|
-
public
|
83
|
+
public RawInputDeviceFlags dwFlags;
|
32
84
|
public IntPtr hwndTarget;
|
33
85
|
}
|
34
86
|
|
87
|
+
private enum RawInputType
|
88
|
+
{
|
89
|
+
Mouse = 0,
|
90
|
+
Keyboard = 1,
|
91
|
+
Hid = 2
|
92
|
+
}
|
93
|
+
|
35
94
|
[StructLayout(LayoutKind.Sequential)]
|
36
95
|
private struct RAWINPUTHEADER
|
37
96
|
{
|
38
|
-
public u
|
97
|
+
public RawInputType dwType;
|
39
|
-
public
|
98
|
+
public int dwSize;
|
40
99
|
public IntPtr hDevice;
|
41
100
|
public IntPtr wParam;
|
42
101
|
}
|
43
102
|
|
103
|
+
[Flags]
|
44
|
-
private enum RawKeyboardFla
|
104
|
+
private enum RawKeyboardFlags : short
|
45
|
-
{
|
105
|
+
{
|
46
|
-
|
106
|
+
Make = 0,
|
47
|
-
|
107
|
+
Break = 1,
|
48
|
-
|
108
|
+
E0 = 2,
|
49
|
-
|
109
|
+
E1 = 4,
|
50
110
|
}
|
51
111
|
|
52
112
|
[StructLayout(LayoutKind.Sequential)]
|
53
113
|
private struct RAWKEYBOARD
|
54
114
|
{
|
55
|
-
public
|
115
|
+
public short MakeCode;
|
56
|
-
public RawKeyboardFla
|
116
|
+
public RawKeyboardFlags Flags;
|
57
|
-
public
|
117
|
+
public short Reserved;
|
58
|
-
public
|
118
|
+
public short VKey;
|
59
|
-
public
|
119
|
+
public int Message;
|
60
|
-
public
|
120
|
+
public int ExtraInformation;
|
61
121
|
}
|
62
122
|
|
63
123
|
[StructLayout(LayoutKind.Sequential)]
|
@@ -69,12 +129,18 @@
|
|
69
129
|
|
70
130
|
[DllImport("user32.dll")]
|
71
131
|
private static extern bool RegisterRawInputDevices(
|
72
|
-
RAWINPUTDEVICE[] pRawInputDevices,
|
132
|
+
RAWINPUTDEVICE[] pRawInputDevices, int uiNumDevices, int cbSize);
|
133
|
+
|
134
|
+
private enum RawInputCommand
|
135
|
+
{
|
136
|
+
Header = 0x10000005,
|
137
|
+
Input = 0x10000003,
|
138
|
+
}
|
73
139
|
|
74
140
|
[DllImport("user32.dll")]
|
75
|
-
private static extern
|
141
|
+
private static extern int GetRawInputData(
|
76
|
-
IntPtr hRawInput, u
|
142
|
+
IntPtr hRawInput, RawInputCommand uiCommand, IntPtr pData,
|
77
|
-
ref
|
143
|
+
ref int pcbSize, int cbSizeHeader);
|
78
144
|
|
79
145
|
public Form1()
|
80
146
|
{
|
@@ -85,14 +151,14 @@
|
|
85
151
|
{
|
86
152
|
base.OnHandleCreated(e);
|
87
153
|
RAWINPUTDEVICE[] rawInputDevices = new RAWINPUTDEVICE[1];
|
88
|
-
rawInputDevices[0].usUsagePage =
|
154
|
+
rawInputDevices[0].usUsagePage = HIDUsagePage.Generic;
|
89
|
-
rawInputDevices[0].usUsage =
|
155
|
+
rawInputDevices[0].usUsage = HIDUsage.Keyboard;
|
90
|
-
rawInputDevices[0].dwFlags = RID
|
156
|
+
rawInputDevices[0].dwFlags = RawInputDeviceFlags.InputSink | RawInputDeviceFlags.NoLegacy;
|
91
157
|
rawInputDevices[0].hwndTarget = Handle;
|
92
158
|
|
93
159
|
var result = RegisterRawInputDevices(rawInputDevices,
|
94
|
-
|
160
|
+
rawInputDevices.Length,
|
95
|
-
|
161
|
+
Marshal.SizeOf(typeof(RAWINPUTDEVICE)));
|
96
162
|
if (!result)
|
97
163
|
{
|
98
164
|
throw new Win32Exception();
|
@@ -103,33 +169,33 @@
|
|
103
169
|
{
|
104
170
|
if (m.Msg == WM_INPUT)
|
105
171
|
{
|
106
|
-
|
172
|
+
int dwSize = 0;
|
107
|
-
GetRawInputData(m.LParam, RI
|
173
|
+
GetRawInputData(m.LParam, RawInputCommand.Input, IntPtr.Zero, ref dwSize,
|
108
|
-
|
174
|
+
Marshal.SizeOf(typeof(RAWINPUTHEADER)));
|
109
|
-
|
175
|
+
|
110
|
-
IntPtr buffer = Marshal.AllocHGlobal(
|
176
|
+
IntPtr buffer = Marshal.AllocHGlobal(dwSize);
|
111
177
|
try
|
112
178
|
{
|
113
|
-
if (GetRawInputData(m.LParam, RI
|
179
|
+
if (GetRawInputData(m.LParam, RawInputCommand.Input, buffer, ref dwSize,
|
114
|
-
|
180
|
+
Marshal.SizeOf(typeof(RAWINPUTHEADER))) == dwSize)
|
115
181
|
{
|
116
|
-
RAWINPUT r
|
182
|
+
RAWINPUTHEADER header = Marshal.PtrToStructure<RAWINPUTHEADER>(buffer);
|
117
|
-
if (
|
183
|
+
if (header.dwType == RawInputType.Keyboard)
|
118
184
|
{
|
119
|
-
if (
|
185
|
+
if (header.hDevice == IntPtr.Zero)
|
120
186
|
{
|
121
187
|
Debug.WriteLine("ソフトウエアだよ!");
|
122
188
|
}
|
123
189
|
else
|
124
190
|
{
|
191
|
+
RAWINPUT raw = Marshal.PtrToStructure<RAWINPUT>(buffer);
|
125
|
-
|
192
|
+
if (raw.Keyboard.Flags.HasFlag(RawKeyboardFlags.Break))
|
126
193
|
{
|
127
|
-
|
194
|
+
Debug.WriteLine($"キーが離されました: {(Keys)raw.Keyboard.VKey}");
|
195
|
+
}
|
196
|
+
else
|
197
|
+
{
|
128
|
-
|
198
|
+
Debug.WriteLine($"キーが押されました: {(Keys)raw.Keyboard.VKey}");
|
129
|
-
break;
|
130
|
-
case RawKeyboardFlahs.RI_KEY_BREAK:
|
131
|
-
Debug.WriteLine($"キーが離されました: {(Keys)raw.Keyboard.VKey}");
|
132
|
-
break;
|
133
199
|
}
|
134
200
|
}
|
135
201
|
}
|
@@ -145,3 +211,5 @@
|
|
145
211
|
}
|
146
212
|
```
|
147
213
|
|
214
|
+
|
215
|
+
|