using System.Collections.Concurrent; using System.Diagnostics; using EnumsNET; using GlobalHotKey; using log4net; using SparkClient.Model.Extension; namespace SparkClient.Model.Helper; public sealed class ClientHotKeyManager { private static readonly ILog Logger = LogManager.GetLogger(typeof(ClientHotKeyManager)); #region 单例模式 private static readonly Lazy _instance = new Lazy(() => new ClientHotKeyManager()); public static ClientHotKeyManager Instance => _instance.Value; private ClientHotKeyManager() { } #endregion #region 存储结构 private readonly ConcurrentDictionary _hotKeys = new ConcurrentDictionary(); private readonly ConcurrentDictionary _manager = new ConcurrentDictionary(); // private HotKeyManager _hotKeyManager = new HotKeyManager(); #endregion #region 公共方法 /// /// 注册热键 /// /// 热键 /// 事件 /// 来源类 /// 非法参数 /// 重复注册 public void Register(HotKey hotKey, EventHandler handler, object registrant = null) { if (hotKey == null) throw new ArgumentNullException(nameof(hotKey)); if (handler == null) throw new ArgumentNullException(nameof(handler)); Logger.Info($"快捷键注册: [ Key = {hotKey.Key.GetName()}, Modifiers = {hotKey.Modifiers.ToSafeAbundantString()}, Handler = {handler.Method.Name}, From = {registrant.GetType().Name}]"); var record = new HotKeyRecord(hotKey, handler, registrant ?? GetDefaultRegistrant()); if (_hotKeys.TryAdd(hotKey, record)) { HotKeyManager _hotKeyManager = new HotKeyManager(); _hotKeyManager.Register(hotKey); _hotKeyManager.KeyPressed += handler; _manager.TryAdd(hotKey, _hotKeyManager); } else { Logger.Info($"快捷键注册跳过: [ Key = {hotKey.Key.GetName()}, Modifiers = {hotKey.Modifiers.ToSafeAbundantString()}, Handler = {handler.Method.Name}, From = {registrant.GetType().Name}]"); return; } } /// /// 释放热键 /// /// public void Unregister(HotKey hotKey) { if (_hotKeys.TryRemove(hotKey, out var record)) { Logger.Info($"快捷键释放: {hotKey.ToSafeAbundantString()}"); HotKeyManager _hotKeyManager = _manager.ContainsKey(hotKey)? _manager[hotKey]: new HotKeyManager(); _hotKeyManager.Unregister(hotKey); _hotKeyManager.KeyPressed -= record.Handler; _manager.TryRemove(hotKey, out _); } } /// /// 热键是否注册 /// /// /// public bool ContainsHotKey(HotKey hotKey) => _hotKeys.ContainsKey(hotKey); /// /// 刷新热键 /// /// /// /// /// private void RefreshHotKey(HotKey hotKey, EventHandler newHandler, object newRegistrant = null) { if (hotKey == null || newHandler == null) throw new ArgumentNullException(); var registrant = newRegistrant ?? GetDefaultRegistrant(); if (!_manager.ContainsKey(hotKey)) { HotKeyManager managerTemp = new HotKeyManager(); managerTemp.Register(hotKey); managerTemp.KeyPressed += newHandler; _manager.TryAdd(hotKey, managerTemp); } HotKeyManager _hotKeyManager = _manager.ContainsKey(hotKey)? _manager[hotKey]: null; _hotKeys.AddOrUpdate( hotKey, key => { _hotKeyManager.Register(key); _hotKeyManager.KeyPressed += newHandler; return new HotKeyRecord(hotKey, newHandler,newRegistrant); }, (key, existingRecord) => { _hotKeyManager.KeyPressed -= existingRecord.Handler; _hotKeyManager.KeyPressed += newHandler; return new HotKeyRecord(hotKey, newHandler,newRegistrant); }); } #endregion #region 调试支持 [Conditional("DEBUG")] public void PrintDebugInfo() { foreach (var kvp in _hotKeys) { Debug.WriteLine($"HotKey: {kvp.Key} | Registrant: {kvp.Value.Registrant}"); } } #endregion #region 辅助方法 private object GetDefaultRegistrant() { // 获取调用堆栈中的注册者信息(例如:类名+方法名) var stackTrace = new StackTrace(skipFrames: 2); var frame = stackTrace.GetFrame(0); return $"{frame.GetMethod().DeclaringType?.Name}.{frame.GetMethod().Name}"; } #endregion #region 内部记录类 private class HotKeyRecord { public HotKey HotKey { get; } public EventHandler Handler { get; } public object Registrant { get; } public HotKeyRecord(HotKey hotKey, EventHandler handler, object registrant) { HotKey = hotKey; Handler = handler; Registrant = registrant; } } #endregion }