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