You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.7 KiB
154 lines
5.7 KiB
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 |
|
{ |
|
Logger.Info($"快捷键注册跳过: [ Key = {hotKey.Key.GetName()}, Modifiers = {hotKey.Modifiers.ToSafeAbundantString()}, Handler = {handler.Method.Name}, From = {registrant.GetType().Name}]"); |
|
return; |
|
} |
|
} |
|
|
|
/// <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 |
|
} |