-
Notifications
You must be signed in to change notification settings - Fork 17
/
KeyboardHook.cs
145 lines (122 loc) · 4.67 KB
/
KeyboardHook.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
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace GoogleAssistantWindows
{
/// <summary>
/// From https://gist.github.com/Larry57/5365740
/// </summary>
public class KeyboardHook
{
#region pinvoke details
private enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
public struct KBDLLHOOKSTRUCT
{
public UInt32 vkCode;
public UInt32 scanCode;
public UInt32 flags;
public UInt32 time;
public IntPtr extraInfo;
}
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(
HookType code, HookProc func, IntPtr instance, int threadID);
[DllImport("user32.dll")]
private static extern int UnhookWindowsHookEx(IntPtr hook);
[DllImport("user32.dll")]
private static extern int CallNextHookEx(
IntPtr hook, int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
#endregion
HookType _hookType = HookType.WH_KEYBOARD_LL;
IntPtr _hookHandle = IntPtr.Zero;
HookProc _hookFunction = null;
// hook method called by system
private delegate int HookProc(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
// events
public delegate void HookEventHandler(object sender, HookEventArgs e);
public event HookEventHandler KeyDown;
public event HookEventHandler KeyUp;
public KeyboardHook()
{
_hookFunction = new HookProc(HookCallback);
Install();
}
~KeyboardHook()
{
Uninstall();
}
// hook function called by system
private int HookCallback(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
{
if (code < 0)
return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
// KeyUp event
if ((lParam.flags & 0x80) != 0 && this.KeyUp != null)
this.KeyUp(this, new HookEventArgs(lParam.vkCode));
// KeyDown event
if ((lParam.flags & 0x80) == 0 && this.KeyDown != null)
this.KeyDown(this, new HookEventArgs(lParam.vkCode));
return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
}
private void Install()
{
// make sure not already installed
if (_hookHandle != IntPtr.Zero)
return;
// need instance handle to module to create a system-wide hook
Module[] list = System.Reflection.Assembly.GetExecutingAssembly().GetModules();
System.Diagnostics.Debug.Assert(list != null && list.Length > 0);
// install system-wide hook
_hookHandle = SetWindowsHookEx(_hookType,
_hookFunction, Marshal.GetHINSTANCE(list[0]), 0);
}
private void Uninstall()
{
if (_hookHandle != IntPtr.Zero)
{
// uninstall system-wide hook
UnhookWindowsHookEx(_hookHandle);
_hookHandle = IntPtr.Zero;
}
}
}
// The callback method converts the low-level keyboard data into something more .NET friendly with the HookEventArgs class.
public class HookEventArgs : EventArgs
{
// using Windows.Forms.Keys instead of Input.Key since the Forms.Keys maps
// to the Win32 KBDLLHOOKSTRUCT virtual key member, where Input.Key does not
public Keys Key;
public bool Alt;
public bool Control;
public bool Shift;
public HookEventArgs(UInt32 keyCode)
{
// detect what modifier keys are pressed, using
// Windows.Forms.Control.ModifierKeys instead of Keyboard.Modifiers
// since Keyboard.Modifiers does not correctly get the state of the
// modifier keys when the application does not have focus
this.Key = (Keys)keyCode;
this.Alt = (System.Windows.Forms.Control.ModifierKeys & Keys.Alt) != 0;
this.Control = (System.Windows.Forms.Control.ModifierKeys & Keys.Control) != 0;
this.Shift = (System.Windows.Forms.Control.ModifierKeys & Keys.Shift) != 0;
}
}
}