Skip to content

Commit f7928ae

Browse files
committed
restructure
1 parent 0832680 commit f7928ae

File tree

4 files changed

+195
-162
lines changed

4 files changed

+195
-162
lines changed
Lines changed: 12 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -4,167 +4,19 @@
44
using System.Linq;
55
using System.Runtime.InteropServices;
66
using System.Windows.Input;
7+
using static ChefKeys.NativeMethods;
8+
using static ChefKeys.Constants.KeyboardKeys;
79

810
namespace ChefKeys
911
{
1012
public static class ChefKeysManager
1113
{
12-
private const int WH_KEYBOARD_LL = 13;
13-
private const int WM_KEYDOWN = 0x0100;
14-
private const int WM_KEYUP = 0x0101;
15-
private const int WM_SYSKEYDOWN = 0x0104;
16-
private const int WM_SYSKEYUP = 0x0105;
17-
private const int VK_LWIN = 0x5B;
18-
private const int VK_RWIN = 0x5C;
19-
private const int VK_LALT = 0xA4;
20-
private const int VK_RALT = 0xA5;
21-
private const int VK_LCTRL = 0xA2;
22-
private const int VK_RCTRL = 0xA3;
23-
private const int VK_LSHIFT = 0xA0;
24-
private const int VK_RSHIFT = 0xA1;
25-
private const int VK_SHIFT = 0x10;
26-
private const uint KEYEVENTF_KEYUP = 0x0002;
27-
28-
private static LowLevelKeyboardProc _proc;
2914
private static IntPtr _hookID = IntPtr.Zero;
15+
private static LowLevelKeyboardProc _proc;
3016
private static bool _isSimulatingKeyPress = false;
31-
32-
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
33-
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
34-
35-
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
36-
[return: MarshalAs(UnmanagedType.Bool)]
37-
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
38-
39-
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
40-
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
41-
42-
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
43-
private static extern IntPtr GetModuleHandle(string lpModuleName);
44-
45-
[DllImport("user32.dll")]
46-
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
47-
48-
[DllImport("user32.dll")]
49-
public static extern short GetAsyncKeyState(int vKey);
50-
51-
private record KeyPressActionRecord()
52-
{
53-
internal int vk_code { get; set; }
54-
55-
internal List<KeyComboRecord> KeyComboRecords = new();
56-
57-
internal bool isSingleKeyRegistered { get; set; } = false;
58-
59-
internal Action<string> action;
60-
61-
internal Func<IntPtr, int, KeyPressActionRecord, bool> HandleKeyPress { get; set; }
62-
63-
internal bool AreKeyCombosRegistered() => KeyComboRecords.Count > 0;
64-
65-
internal void RegisterKeyCombo(string hotkey, int vk_code, Action<string> action, int vkCodeCombo0, int vkCodeCombo1 = 0, int vkCodeCombo2 = 0)
66-
{
67-
if (KeyComboRecords.Any(x => x.comboRaw == hotkey))
68-
return;
69-
70-
KeyComboRecords
71-
.Add(
72-
new KeyComboRecord
73-
{
74-
vk_code = vk_code,
75-
vkCodeCombo0 = vkCodeCombo0,
76-
vkCodeCombo1 = vkCodeCombo1,
77-
vkCodeCombo2 = vkCodeCombo2,
78-
action = action,
79-
comboRaw = hotkey
80-
});
81-
82-
}
83-
};
84-
85-
private record KeyComboRecord()
86-
{
87-
internal int vk_code { get; set; }
88-
89-
internal Action<string> action;
90-
91-
internal int vkCodeCombo0 { get; set; } = 0;
92-
93-
internal int vkCodeCombo1 { get; set; } = 0;
94-
95-
internal int vkCodeCombo2 { get; set; } = 0;
96-
97-
internal string comboRaw { get; set; } = string.Empty;
98-
99-
internal bool AreComboKeysHeldDown()
100-
{
101-
var heldDown = true;
102-
103-
// vk_code is the release key, which is already pressed, no need to check.
104-
var comboKeys = new Dictionary<int, string> { { vk_code, string.Empty } };
105-
106-
if (vkCodeCombo0 > 0)
107-
{
108-
comboKeys.Add(vkCodeCombo0, string.Empty);
109-
110-
if ((GetAsyncKeyState(vkCodeCombo0) & 0x8000) == 0)
111-
heldDown = false;
112-
}
113-
114-
if (vkCodeCombo1 > 0)
115-
{
116-
comboKeys.Add(vkCodeCombo1, string.Empty);
117-
118-
if ((GetAsyncKeyState(vkCodeCombo1) & 0x8000) == 0)
119-
heldDown = false;
120-
}
121-
122-
if (vkCodeCombo2 > 0)
123-
{
124-
comboKeys.Add(vkCodeCombo2, string.Empty);
125-
126-
if ((GetAsyncKeyState(vkCodeCombo2) & 0x8000) == 0)
127-
heldDown= false;
128-
}
129-
130-
if (NonRegisteredModifierKeyPressed(comboKeys))
131-
heldDown = false;
132-
133-
return heldDown;
134-
}
135-
136-
private bool NonRegisteredModifierKeyPressed(Dictionary<int, string> comboKeys)
137-
{
138-
if (!comboKeys.ContainsKey(VK_LCTRL) && ((GetAsyncKeyState(VK_LCTRL) & 0x8000) != 0))
139-
return true;
140-
141-
if (!comboKeys.ContainsKey(VK_RCTRL) && ((GetAsyncKeyState(VK_RCTRL) & 0x8000) != 0))
142-
return true;
143-
144-
if (!comboKeys.ContainsKey(VK_LALT) && ((GetAsyncKeyState(VK_LALT) & 0x8000) != 0))
145-
return true;
146-
147-
if (!comboKeys.ContainsKey(VK_RALT) && ((GetAsyncKeyState(VK_RALT) & 0x8000) != 0))
148-
return true;
149-
150-
if (!comboKeys.ContainsKey(VK_LSHIFT) && ((GetAsyncKeyState(VK_LSHIFT) & 0x8000) != 0))
151-
return true;
152-
153-
if (!comboKeys.ContainsKey(VK_RSHIFT) && ((GetAsyncKeyState(VK_RSHIFT) & 0x8000) != 0))
154-
return true;
155-
156-
if (!comboKeys.ContainsKey(VK_LWIN) && ((GetAsyncKeyState(VK_LWIN) & 0x8000) != 0))
157-
return true;
158-
159-
if (!comboKeys.ContainsKey(VK_RWIN) && ((GetAsyncKeyState(VK_RWIN) & 0x8000) != 0))
160-
return true;
161-
162-
return false;
163-
}
164-
}
165-
166-
private static readonly Dictionary<int, KeyPressActionRecord> registeredHotkeys;
167-
private static readonly KeyPressActionRecord nonRegisteredKeyRecord;
17+
18+
private static readonly Dictionary<int, KeyRecord> registeredHotkeys;
19+
private static readonly KeyRecord nonRegisteredKeyRecord;
16820

16921
private static bool isLWinKeyDown = false;
17022
private static bool nonRegisteredKeyDown = false;
@@ -173,8 +25,8 @@ private bool NonRegisteredModifierKeyPressed(Dictionary<int, string> comboKeys)
17325

17426
static ChefKeysManager()
17527
{
176-
registeredHotkeys = new Dictionary<int, KeyPressActionRecord>();
177-
nonRegisteredKeyRecord = new KeyPressActionRecord { vk_code = 0, HandleKeyPress = HandleNonRegisteredKeyPress };
28+
registeredHotkeys = new Dictionary<int, KeyRecord>();
29+
nonRegisteredKeyRecord = new KeyRecord { vk_code = 0, HandleKeyPress = HandleNonRegisteredKeyPress };
17830

17931
_proc = HookCallback;
18032
}
@@ -198,8 +50,6 @@ private static IntPtr SetHook(LowLevelKeyboardProc proc)
19850
}
19951
}
20052

201-
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
202-
20353
private static IEnumerable<string> SplitHotkeyReversed(string hotkeys) => hotkeys.Split("+", StringSplitOptions.RemoveEmptyEntries).Reverse();
20454

20555
public static void RegisterHotkey(string hotkeys, Action<string> action) => RegisterHotkey(hotkeys, hotkeys, action);
@@ -234,7 +84,7 @@ public static void RegisterHotkey(string hotkeys, string previousHotkey, Action<
23484
return;
23585
}
23686

237-
var keyRecord = new KeyPressActionRecord
87+
var keyRecord = new KeyRecord
23888
{
23989
vk_code = ToKeyCode(keys.First()),
24090
HandleKeyPress = HandleRegisteredKeyPress,
@@ -324,7 +174,7 @@ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
324174
{
325175
int vkCode = Marshal.ReadInt32(lParam);
326176

327-
var keyRecord = !registeredHotkeys.TryGetValue(vkCode, out KeyPressActionRecord registeredKeyRecord)
177+
var keyRecord = !registeredHotkeys.TryGetValue(vkCode, out KeyRecord registeredKeyRecord)
328178
? nonRegisteredKeyRecord
329179
: registeredKeyRecord;
330180

@@ -337,7 +187,7 @@ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
337187
return CallNextHookEx(_hookID, nCode, wParam, lParam);
338188
}
339189

340-
private static bool HandleRegisteredKeyPress(IntPtr wParam, int vkCode, KeyPressActionRecord keyRecord)
190+
private static bool HandleRegisteredKeyPress(IntPtr wParam, int vkCode, KeyRecord keyRecord)
341191
{
342192
if (nonRegisteredKeyDown)
343193
cancelAction = true;
@@ -412,7 +262,7 @@ private static bool HandleRegisteredKeyPress(IntPtr wParam, int vkCode, KeyPress
412262
return false;
413263
}
414264

415-
private static bool HandleNonRegisteredKeyPress(IntPtr wParam, int vkCode, KeyPressActionRecord registeredKeyRecord)
265+
private static bool HandleNonRegisteredKeyPress(IntPtr wParam, int vkCode, KeyRecord registeredKeyRecord)
416266
{
417267
if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
418268
nonRegisteredKeyDown = true;

ChefKeys/Constants/KeyboardKeys.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace ChefKeys.Constants
2+
{
3+
internal static class KeyboardKeys
4+
{
5+
internal const int WH_KEYBOARD_LL = 13;
6+
internal const int WM_KEYDOWN = 0x0100;
7+
internal const int WM_KEYUP = 0x0101;
8+
internal const int WM_SYSKEYDOWN = 0x0104;
9+
internal const int WM_SYSKEYUP = 0x0105;
10+
internal const int VK_LWIN = 0x5B;
11+
internal const int VK_RWIN = 0x5C;
12+
internal const int VK_LALT = 0xA4;
13+
internal const int VK_RALT = 0xA5;
14+
internal const int VK_LCTRL = 0xA2;
15+
internal const int VK_RCTRL = 0xA3;
16+
internal const int VK_LSHIFT = 0xA0;
17+
internal const int VK_RSHIFT = 0xA1;
18+
internal const int VK_SHIFT = 0x10;
19+
internal const uint KEYEVENTF_KEYUP = 0x0002;
20+
}
21+
}

ChefKeys/KeyRecords.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using static ChefKeys.Constants.KeyboardKeys;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace ChefKeys
7+
{
8+
internal record KeyRecord()
9+
{
10+
internal int vk_code { get; set; }
11+
12+
internal List<KeyComboRecord> KeyComboRecords = new();
13+
14+
internal bool isSingleKeyRegistered { get; set; } = false;
15+
16+
internal Action<string> action;
17+
18+
internal Func<IntPtr, int, KeyRecord, bool> HandleKeyPress { get; set; }
19+
20+
internal bool AreKeyCombosRegistered() => KeyComboRecords.Count > 0;
21+
22+
internal void RegisterKeyCombo(string hotkey, int vk_code, Action<string> action, int vkCodeCombo0, int vkCodeCombo1 = 0, int vkCodeCombo2 = 0)
23+
{
24+
if (KeyComboRecords.Any(x => x.comboRaw == hotkey))
25+
return;
26+
27+
KeyComboRecords
28+
.Add(
29+
new KeyComboRecord
30+
{
31+
vk_code = vk_code,
32+
vkCodeCombo0 = vkCodeCombo0,
33+
vkCodeCombo1 = vkCodeCombo1,
34+
vkCodeCombo2 = vkCodeCombo2,
35+
action = action,
36+
comboRaw = hotkey
37+
});
38+
39+
}
40+
};
41+
42+
internal record KeyComboRecord()
43+
{
44+
internal int vk_code { get; set; }
45+
46+
internal Action<string> action;
47+
48+
internal int vkCodeCombo0 { get; set; } = 0;
49+
50+
internal int vkCodeCombo1 { get; set; } = 0;
51+
52+
internal int vkCodeCombo2 { get; set; } = 0;
53+
54+
internal string comboRaw { get; set; } = string.Empty;
55+
56+
internal bool AreComboKeysHeldDown()
57+
{
58+
var heldDown = true;
59+
60+
// vk_code is the release key, which is already pressed, no need to check.
61+
var comboKeys = new Dictionary<int, string> { { vk_code, string.Empty } };
62+
63+
if (vkCodeCombo0 > 0)
64+
{
65+
comboKeys.Add(vkCodeCombo0, string.Empty);
66+
67+
if ((NativeMethods.GetAsyncKeyState(vkCodeCombo0) & 0x8000) == 0)
68+
heldDown = false;
69+
}
70+
71+
if (vkCodeCombo1 > 0)
72+
{
73+
comboKeys.Add(vkCodeCombo1, string.Empty);
74+
75+
if ((NativeMethods.GetAsyncKeyState(vkCodeCombo1) & 0x8000) == 0)
76+
heldDown = false;
77+
}
78+
79+
if (vkCodeCombo2 > 0)
80+
{
81+
comboKeys.Add(vkCodeCombo2, string.Empty);
82+
83+
if ((NativeMethods.GetAsyncKeyState(vkCodeCombo2) & 0x8000) == 0)
84+
heldDown = false;
85+
}
86+
87+
if (NonRegisteredModifierKeyPressed(comboKeys))
88+
heldDown = false;
89+
90+
return heldDown;
91+
}
92+
93+
private bool NonRegisteredModifierKeyPressed(Dictionary<int, string> comboKeys)
94+
{
95+
if (!comboKeys.ContainsKey(VK_LCTRL) && ((NativeMethods.GetAsyncKeyState(VK_LCTRL) & 0x8000) != 0))
96+
return true;
97+
98+
if (!comboKeys.ContainsKey(VK_RCTRL) && ((NativeMethods.GetAsyncKeyState(VK_RCTRL) & 0x8000) != 0))
99+
return true;
100+
101+
if (!comboKeys.ContainsKey(VK_LALT) && ((NativeMethods.GetAsyncKeyState(VK_LALT) & 0x8000) != 0))
102+
return true;
103+
104+
if (!comboKeys.ContainsKey(VK_RALT) && ((NativeMethods.GetAsyncKeyState(VK_RALT) & 0x8000) != 0))
105+
return true;
106+
107+
if (!comboKeys.ContainsKey(VK_LSHIFT) && ((NativeMethods.GetAsyncKeyState(VK_LSHIFT) & 0x8000) != 0))
108+
return true;
109+
110+
if (!comboKeys.ContainsKey(VK_RSHIFT) && ((NativeMethods.GetAsyncKeyState(VK_RSHIFT) & 0x8000) != 0))
111+
return true;
112+
113+
if (!comboKeys.ContainsKey(VK_LWIN) && ((NativeMethods.GetAsyncKeyState(VK_LWIN) & 0x8000) != 0))
114+
return true;
115+
116+
if (!comboKeys.ContainsKey(VK_RWIN) && ((NativeMethods.GetAsyncKeyState(VK_RWIN) & 0x8000) != 0))
117+
return true;
118+
119+
return false;
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)