forked from c0ldw1nter/echoes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKeyboardHook.cs
150 lines (126 loc) · 4.98 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
146
147
148
149
150
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
namespace Echoes
{
/// <summary>
/// Class for intercepting low level keyboard hooks
/// </summary>
public class KeyboardHook
{
private const int VK_SHIFT = 0x10;
private const int VK_CONTROL = 0x11;
private const int VK_MENU = 0x12;
private const int VK_CAPITAL = 0x14;
public List<Keys> suppressedKeys = new List<Keys>();
/// <summary>
/// Internal callback processing function
/// </summary>
private delegate IntPtr KeyboardHookHandler(int nCode, IntPtr wParam, IntPtr lParam);
private KeyboardHookHandler hookHandler;
/// <summary>
/// Function that will be called when defined events occur
/// </summary>
/// <param name="key">VKeys</param>
public delegate void KeyboardHookCallback(KeyEventArgs e);
#region Events
public event KeyboardHookCallback KeyDown;
public event KeyboardHookCallback KeyUp;
#endregion
/// <summary>
/// Hook ID
/// </summary>
private IntPtr hookID = IntPtr.Zero;
/// <summary>
/// Install low level keyboard hook
/// </summary>
public void Install()
{
hookHandler = HookFunc;
hookID = SetHook(hookHandler);
}
/// <summary>
/// Remove low level keyboard hook
/// </summary>
public void Uninstall()
{
UnhookWindowsHookEx(hookID);
}
/// <summary>
/// Registers hook with Windows API
/// </summary>
/// <param name="proc">Callback function</param>
/// <returns>Hook ID</returns>
private IntPtr SetHook(KeyboardHookHandler proc)
{
using (ProcessModule module = Process.GetCurrentProcess().MainModule)
return SetWindowsHookEx(13, proc, GetModuleHandle(module.ModuleName), 0);
}
/// <summary>
/// Default hook call, which analyses pressed keys
/// </summary>
private IntPtr HookFunc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
int iwParam = wParam.ToInt32();
Keys key = (Keys)Marshal.ReadInt32(lParam);
key = AddModifiers(key);
if ((iwParam == WM_KEYDOWN || iwParam == WM_SYSKEYDOWN))
if (KeyDown != null)
KeyDown(new KeyEventArgs(key));
if ((iwParam == WM_KEYUP || iwParam == WM_SYSKEYUP))
if (KeyUp != null)
KeyUp(new KeyEventArgs(key));
if (suppressedKeys.Contains(key)) return (System.IntPtr)1;
}
return CallNextHookEx(hookID, nCode, wParam, lParam);
}
/// <summary>
/// Checks whether Alt, Shift, Control or CapsLock
/// is pressed at the same time as the hooked key.
/// Modifies the keyCode to include the pressed keys.
/// </summary>
private Keys AddModifiers(Keys key)
{
//CapsLock
if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0) key = key | Keys.CapsLock;
//Shift
if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) key = key | Keys.Shift;
//Ctrl
if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) key = key | Keys.Control;
//Alt
if ((GetKeyState(VK_MENU) & 0x8000) != 0) key = key | Keys.Alt;
return key;
}
/// <summary>
/// Destructor. Unhook current hook
/// </summary>
~KeyboardHook()
{
Uninstall();
}
/// <summary>
/// Low-Level function declarations
/// </summary>
#region WinAPI
private const int WM_KEYDOWN = 0x100;
private const int WM_SYSKEYDOWN = 0x104;
private const int WM_KEYUP = 0x101;
private const int WM_SYSKEYUP = 0x105;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookHandler lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
}
}