parent
ce3563e2e0
commit
5e21cb8788
11 changed files with 293 additions and 38 deletions
@ -0,0 +1,153 @@ |
||||
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<ClientHotKeyManager> _instance = |
||||
new Lazy<ClientHotKeyManager>(() => new ClientHotKeyManager()); |
||||
public static ClientHotKeyManager Instance => _instance.Value; |
||||
private ClientHotKeyManager() { } |
||||
#endregion |
||||
|
||||
#region 存储结构 |
||||
private readonly ConcurrentDictionary<HotKey, HotKeyRecord> _hotKeys = |
||||
new ConcurrentDictionary<HotKey, HotKeyRecord>(); |
||||
private readonly ConcurrentDictionary<HotKey, HotKeyManager> _manager = |
||||
new ConcurrentDictionary<HotKey, HotKeyManager>(); |
||||
// private HotKeyManager _hotKeyManager = new HotKeyManager(); |
||||
#endregion |
||||
|
||||
#region 公共方法 |
||||
/// <summary> |
||||
/// 注册热键 |
||||
/// </summary> |
||||
/// <param name="hotKey">热键</param> |
||||
/// <param name="handler">事件</param> |
||||
/// <param name="registrant">来源类</param> |
||||
/// <exception cref="ArgumentNullException">非法参数</exception> |
||||
/// <exception cref="InvalidOperationException">重复注册</exception> |
||||
public void Register(HotKey hotKey, EventHandler<KeyPressedEventArgs> 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 |
||||
{ |
||||
throw new InvalidOperationException($"HotKey {hotKey} already registered!"); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// 释放热键 |
||||
/// </summary> |
||||
/// <param name="hotKey"></param> |
||||
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 _); |
||||
} |
||||
} |
||||
/// <summary> |
||||
/// 热键是否注册 |
||||
/// </summary> |
||||
/// <param name="hotKey"></param> |
||||
/// <returns></returns> |
||||
public bool ContainsHotKey(HotKey hotKey) => _hotKeys.ContainsKey(hotKey); |
||||
|
||||
/// <summary> |
||||
/// 刷新热键 |
||||
/// </summary> |
||||
/// <param name="hotKey"></param> |
||||
/// <param name="newHandler"></param> |
||||
/// <param name="newRegistrant"></param> |
||||
/// <exception cref="ArgumentNullException"></exception> |
||||
private void RefreshHotKey(HotKey hotKey, EventHandler<KeyPressedEventArgs> 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<KeyPressedEventArgs> Handler { get; } |
||||
public object Registrant { get; } |
||||
|
||||
public HotKeyRecord(HotKey hotKey, EventHandler<KeyPressedEventArgs> handler, object registrant) |
||||
{ |
||||
HotKey = hotKey; |
||||
Handler = handler; |
||||
Registrant = registrant; |
||||
} |
||||
} |
||||
#endregion |
||||
} |
||||
@ -0,0 +1,24 @@ |
||||
using System.Windows.Input; |
||||
using GlobalHotKey; |
||||
|
||||
namespace SparkClient.Model.Helper; |
||||
|
||||
public class ClientHotKeys |
||||
{ |
||||
/// <summary> |
||||
/// 快速开始检测 |
||||
/// </summary> |
||||
public static readonly HotKey QuickAnewDetectHotKey = new HotKey(Key.Q, ModifierKeys.Control | ModifierKeys.Alt); |
||||
/// <summary> |
||||
/// 关闭检测结果页 |
||||
/// </summary> |
||||
public static readonly HotKey CloseResultHotKey = new HotKey(Key.E, ModifierKeys.Control | ModifierKeys.Alt); |
||||
/// <summary> |
||||
/// 检测结果页 切换详细数据页和数据模型页 |
||||
/// </summary> |
||||
public static readonly HotKey SwitchPagesHotKey = new HotKey(Key.D1, ModifierKeys.Control); |
||||
/// <summary> |
||||
/// 心箭图渲染 |
||||
/// </summary> |
||||
public static readonly HotKey ArrowAndHeartHotKey = new HotKey(Key.D2, ModifierKeys.Control); |
||||
} |
||||
Loading…
Reference in new issue