44using System . Linq ;
55using System . Runtime . InteropServices ;
66using System . Windows . Input ;
7+ using static ChefKeys . NativeMethods ;
8+ using static ChefKeys . Constants . KeyboardKeys ;
79
810namespace 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 ;
0 commit comments