using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Input; using KeyEventHandler = System.Windows.Input.KeyEventHandler; namespace InABox.WPF { public enum HotKeyModifier { Ctrl, Shift, Alt } public static class HotKeyManager { private static readonly List>> _hotkeys = new(); private static Tuple> FindHotKey(Key key, HotKeyModifier[] modifiers) { var m = modifiers != null ? modifiers : new HotKeyModifier[] { }; var existing = _hotkeys.FirstOrDefault( x => x.Item1 == key && x.Item2.Length == m.Length && x.Item2.Intersect(m).Count() == x.Item2.Length); return existing; } public static void RegisterHotKey(Key key, Func action) { RegisterHotKey(key, new HotKeyModifier[] { }, action); } public static void RegisterHotKey(Key key, HotKeyModifier[] modifiers, Func action) { var existing = FindHotKey(key, modifiers); if (existing != null) throw new Exception(string.Format("HotKey [{0}+{1}] is already registered!", string.Join("+", modifiers.Select(x => x)), key)); _hotkeys.Add(new Tuple>(key, modifiers, action)); } public static void UnRegisterHotKey(Key key) { UnRegisterHotKey(key, new HotKeyModifier[] { }); } public static void UnRegisterHotKey(Key key, HotKeyModifier[] modifiers) { var existing = FindHotKey(key, modifiers); if (existing != null) _hotkeys.Remove(existing); } public static bool ProcessHotKey(Key key) { var modifiers = new List(); if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) modifiers.Add(HotKeyModifier.Shift); if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) modifiers.Add(HotKeyModifier.Ctrl); if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) modifiers.Add(HotKeyModifier.Alt); var existing = FindHotKey(key, modifiers.ToArray()); if (existing != null) return existing.Item3.Invoke(); return false; } public static void Initialize() { EventManager.RegisterClassHandler( typeof(Window), Keyboard.KeyDownEvent, new KeyEventHandler( (o, args) => { ProcessHotKey(args.Key); //args.Handled = args.Key == Key.Space ? true : ProcessHotKey(args.Key); } ), true ); } } }