This repository has been archived by the owner on Feb 22, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MainWindow.xaml.cs
277 lines (240 loc) · 10.4 KB
/
MainWindow.xaml.cs
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Threading;
namespace MySendKeySample {
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window {
#region Declaration
public delegate bool EnumWindowsDelegate(IntPtr hWnd, IntPtr lparam);
private static class NativeMethods {
internal const uint MAPVK_VK_TO_VSC = 0;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct MOUSEINPUT32_WithSkip {
public uint __Unused0; // See INPUT32 structure
public int X;
public int Y;
public uint MouseData;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct KEYBDINPUT32_WithSkip {
public uint __Unused0; // See INPUT32 structure
public ushort VirtualKey;
public ushort ScanCode;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Explicit)]
internal struct INPUT32 {
[FieldOffset(0)]
public uint Type;
[FieldOffset(0)]
public MOUSEINPUT32_WithSkip Mouse;
[FieldOffset(0)]
public KEYBDINPUT32_WithSkip Keyboard;
}
// INPUT.KI (40). vk: 8, sc: 10, fl: 12, t: 16, ex: 24
[StructLayout(LayoutKind.Explicit, Size = 40)]
internal struct INPUT64 {
[FieldOffset(0)]
public uint Type;
[FieldOffset(8)]
public ushort VirtualKey;
[FieldOffset(10)]
public ushort ScanCode;
[FieldOffset(12)]
public uint Flags;
[FieldOffset(16)]
public uint Time;
[FieldOffset(24)]
public IntPtr ExtraInfo;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public extern static bool EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr lparam);
[DllImport("user32")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("User32.dll")]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, [Out] out uint lpdwProcessId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("User32.dll", EntryPoint = "SendInput", SetLastError = true)]
internal static extern uint SendInput32(uint nInputs, INPUT32[] pInputs, int cbSize);
[DllImport("User32.dll", EntryPoint = "SendInput", SetLastError = true)]
internal static extern uint SendInput64(uint nInputs, INPUT64[] pInputs, int cbSize);
[DllImport("user32.dll")]
public static extern IntPtr GetMessageExtraInfo();
[DllImport("User32.dll")]
internal static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("User32.dll")]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("User32.dll")]
private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType,IntPtr hKL);
internal static uint MapVirtualKey3(uint uCode, uint uMapType, IntPtr hKL) {
if (hKL == IntPtr.Zero) {
return MapVirtualKey(uCode, uMapType);
} else {
return MapVirtualKeyEx(uCode, uMapType, hKL);
}
}
}
private static class KeyStroke {
public const int KeyDown = 0x100;
public const int KeyUp = 0x101;
public const int SysKeyDown = 0x104;
public const int SysKeyup = 0x105;
}
private static class Flags {
public const int None = 0x00;
public const int KeyDown = 0x00;
public const int KeyUp = 0x02;
public const int ExtendeKey = 0x01;
public const int Unicode = 0x04;
public const int ScanCode = 0x08;
}
private class KeySet {
public ushort VirtualKey;
public ushort ScanCode;
public uint Flag;
public KeySet(byte[] pair) : this(pair, Flags.None) {
}
public KeySet(byte[] pair, uint flag) {
this.VirtualKey = KeySetPair.VirtualKey(pair);
this.ScanCode = KeySetPair.ScanCode(pair);
this.Flag = flag;
}
}
private static class ExtraInfo {
public const int SendKey = 1;
}
private static class InputType {
public const uint Mouse = 0;
public const uint Keyboard = 1;
public const uint Hardware = 2;
}
private static string _className;
private static bool _findSelf = false;
private static IntPtr _targetWIndows = IntPtr.Zero;
private static MainWindow _self;
private static IntPtr _keyboardLayout = IntPtr.Zero;
private delegate bool SendVKeyNativeDelegate(uint keyStroke, KeySet keyset);
#endregion
#region Constructor
public MainWindow() {
InitializeComponent();
_self = this;
_className = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
uint uPID;
uint uTID = NativeMethods.GetWindowThreadProcessId(NativeMethods.GetForegroundWindow(), out uPID);
_keyboardLayout = NativeMethods.GetKeyboardLayout(uTID);
}
#endregion
#region Event
private void Button_Click(object sender, RoutedEventArgs e) {
NativeMethods.EnumWindows(new EnumWindowsDelegate(EnumWindowCallBack), IntPtr.Zero);
}
#endregion
#region Public Method
public void SendKey(IntPtr hWnd) {
NativeMethods.SetForegroundWindow(hWnd);
DoEvents();
SendVKeyNativeDelegate sendKey;
if (IntPtr.Size == 4) {
sendKey = this.SendVKeyNative32;
} else {
sendKey = this.SendVKeyNative64;
}
// https://stackoverflow.com/questions/12761169/send-keys-through-sendinput-in-user32-dll
sendKey(KeyStroke.KeyDown, new KeySet(KeySetPair.A));
sendKey(KeyStroke.KeyDown, new KeySet(KeySetPair.Tab));
sendKey(KeyStroke.KeyDown, new KeySet(KeySetPair.B));
sendKey(KeyStroke.KeyDown, new KeySet(KeySetPair.B));
DoEvents();
sendKey(KeyStroke.KeyDown, new KeySet(KeySetPair.Enter));
}
#endregion
#region Private Method
private static bool EnumWindowCallBack(IntPtr hWnd, IntPtr lparam) {
if (!NativeMethods.IsWindowVisible(hWnd)) {
return true;
}
int length = NativeMethods.GetWindowTextLength(hWnd);
if (0 < length) {
uint processId;
NativeMethods.GetWindowThreadProcessId(hWnd, out processId);
var proccess = Process.GetProcessById((int)processId);
if (_findSelf) {
_self.SendKey(hWnd);
_findSelf = false;
return false;
} else if (proccess.ProcessName == _className) {
_findSelf = true;
}
}
return true;
}
private static void DoEvents() {
DispatcherFrame frame = new DispatcherFrame();
var callback = new DispatcherOperationCallback(ExitFrames);
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, callback, frame);
Dispatcher.PushFrame(frame);
}
private static object ExitFrames(object obj) {
((DispatcherFrame)obj).Continue = false;
return null;
}
private bool SendVKeyNative32(uint keyStroke, KeySet keyset) {
var input = new NativeMethods.INPUT32();
input.Type = InputType.Keyboard;
input.Keyboard.Flags = keyStroke | keyset.Flag;
input.Keyboard.VirtualKey = keyset.VirtualKey;
// input.Keyboard.ScanCode =(ushort)(NativeMethods.MapVirtualKey3((uint)keyset.VirtualKey, NativeMethods.MAPVK_VK_TO_VSC, _keyboardLayout) & 0xFFU); ;
input.Keyboard.ScanCode = 0;
input.Keyboard.Time = 0;
input.Keyboard.ExtraInfo = NativeMethods.GetMessageExtraInfo();
NativeMethods.INPUT32[] inputs = { input };
if (NativeMethods.SendInput32(1, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT32))) != 1)
return false;
return true;
}
private bool SendVKeyNative64(uint keyStroke, KeySet keyset) {
var input = new NativeMethods.INPUT64();
input.Type = InputType.Keyboard;
input.Flags = keyStroke | keyset.Flag;
input.VirtualKey = keyset.VirtualKey;
// input.ScanCode = (ushort)(NativeMethods.MapVirtualKey3((uint)keyset.VirtualKey, NativeMethods.MAPVK_VK_TO_VSC, _keyboardLayout) & 0xFFU);
input.ScanCode = 0;
input.Time = 0;
input.ExtraInfo = NativeMethods.GetMessageExtraInfo();
NativeMethods.INPUT64[] inputs = { input };
if (NativeMethods.SendInput64(1, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT64))) != 1)
return false;
return true;
}
#endregion
}
}