From 6855b6299f5267414c289d20aa2154cb6f47989e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E5=82=91?= Date: Sun, 18 Jun 2023 18:19:51 +0800 Subject: [PATCH] Add Kot key utils from https://github.com/jie65535/KeyGo --- .../GrasscutterTools/GrasscutterTools.csproj | 3 + Source/GrasscutterTools/Utils/AppHotKey.cs | 61 ++++ Source/GrasscutterTools/Utils/HotKey.cs | 298 ++++++++++++++++++ Source/GrasscutterTools/Utils/HotKeyItem.cs | 77 +++++ 4 files changed, 439 insertions(+) create mode 100644 Source/GrasscutterTools/Utils/AppHotKey.cs create mode 100644 Source/GrasscutterTools/Utils/HotKey.cs create mode 100644 Source/GrasscutterTools/Utils/HotKeyItem.cs diff --git a/Source/GrasscutterTools/GrasscutterTools.csproj b/Source/GrasscutterTools/GrasscutterTools.csproj index 85a670f..cdffa18 100644 --- a/Source/GrasscutterTools/GrasscutterTools.csproj +++ b/Source/GrasscutterTools/GrasscutterTools.csproj @@ -280,9 +280,12 @@ True True + + + diff --git a/Source/GrasscutterTools/Utils/AppHotKey.cs b/Source/GrasscutterTools/Utils/AppHotKey.cs new file mode 100644 index 0000000..4228120 --- /dev/null +++ b/Source/GrasscutterTools/Utils/AppHotKey.cs @@ -0,0 +1,61 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace GrasscutterTools.Utils +{ + public static class AppHotKey + { + /// + /// 注册热键 + /// + /// 窗口句柄 + /// 热键ID + /// 组合键 + /// 热键 + public static void RegKey(IntPtr hwnd, int hotKey_id, KeyModifiers keyModifiers, Keys key) + { + if (!RegisterHotKey(hwnd, hotKey_id, keyModifiers, key)) + throw new Win32Exception(); + } + + /// + /// 注销热键 + /// + /// 窗口句柄 + /// 热键ID + public static void UnRegKey(IntPtr hwnd, int hotKey_id) + { + //注销Id号为hotKey_id的热键设定 + UnregisterHotKey(hwnd, hotKey_id); + } + + //如果函数执行成功,返回值不为0。 + //如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。 + [DllImport("user32.dll", SetLastError = true)] + private static extern bool RegisterHotKey( + IntPtr hWnd, //要定义热键的窗口的句柄 + int id, //定义热键ID(不能与其它ID重复) + KeyModifiers fsModifiers, //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效 + Keys vk //定义热键的内容 + ); + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool UnregisterHotKey( + IntPtr hWnd, //要取消热键的窗口的句柄 + int id //要取消热键的ID + ); + + //定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值) + [Flags] + public enum KeyModifiers + { + None = 0, + Alt = 1, + Ctrl = 2, + Shift = 4, + WindowsKey = 8 + } + } +} \ No newline at end of file diff --git a/Source/GrasscutterTools/Utils/HotKey.cs b/Source/GrasscutterTools/Utils/HotKey.cs new file mode 100644 index 0000000..af68967 --- /dev/null +++ b/Source/GrasscutterTools/Utils/HotKey.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Windows.Forms; +using System.Xml.Serialization; + +namespace GrasscutterTools.Utils +{ + /// + /// KeyGo 核心功能类 + /// + public class KeyGo + { + #region Member + + private static int _RegMaxID; + + [XmlIgnore] + public IntPtr FormHandle { get; set; } + + public List Items { get; set; } = new List(); + + #endregion Member + + #region FILE IO + + /// + /// Loads the XML. + /// + /// The file path. + /// + public static KeyGo LoadXml(string filePath) + { + KeyGo data = null; + if (File.Exists(filePath)) + { + XmlSerializer formatter = new XmlSerializer(typeof(KeyGo)); + using (var stream = File.OpenRead(filePath)) + { + if (stream.Length > 0) + { + data = formatter.Deserialize(stream) as KeyGo; + } + } + } + return data; + } + + /// + /// Saves the XML. + /// + /// The file path. + public void SaveXml(string filePath) + { + if (!File.Exists(filePath)) + Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + + XmlSerializer formatter = new XmlSerializer(typeof(KeyGo)); + using (var stream = File.Create(filePath)) + { + formatter.Serialize(stream, this); + } + } + + #endregion FILE IO + + #region HotKey Register + + /// + /// Regs all key. + /// + public void RegAllKey() + { + foreach (var item in Items) + { + if (!item.Enabled) + continue; + + try + { + RegKey(item); + } + catch (Exception) + { + // 忽视异常,外部通过ID是否被设置判断执行结果 + } + } + } + + /// + /// Uns the reg all key. + /// + public void UnRegAllKey() + { + foreach (var item in Items) + { + try + { + UnRegKey(item); + } + catch (Exception) + { + // 忽视异常,外部通过ID是否被设置判断执行结果 + } + } + } + + /// + /// 注册热键 - 成功后,会设置 HotKeyID + /// + /// The item. + /// + /// item + /// or + /// HotKey - 热键不能为空! + /// + /// + /// 功能键不能为空! + /// or + /// 快捷键不能为空! + /// + public void RegKey(HotKeyItem item) + { + if (item is null) + throw new ArgumentNullException(nameof(item)); + if (string.IsNullOrWhiteSpace(item.HotKey)) + throw new ArgumentNullException(nameof(item.HotKey), "热键不能为空!"); + + // 如果注册过该热键,ID不为0。卸载热键会将ID置零。 + if (item.HotKeyID != 0) + return; + + int id = Interlocked.Increment(ref _RegMaxID); + + var keys = item.HotKey.Split('+'); + Keys keyCode = Keys.None; + AppHotKey.KeyModifiers keyModifiers = AppHotKey.KeyModifiers.None; + foreach (var key in keys) + { + switch (key.ToLower()) + { + case "ctrl": + keyModifiers |= AppHotKey.KeyModifiers.Ctrl; + break; + + case "shift": + keyModifiers |= AppHotKey.KeyModifiers.Shift; + break; + + case "alt": + keyModifiers |= AppHotKey.KeyModifiers.Alt; + break; + + case "win": + keyModifiers |= AppHotKey.KeyModifiers.WindowsKey; + break; + + default: + keyCode = (Keys)Enum.Parse(typeof(Keys), key); + break; + } + } + + if (keyModifiers == AppHotKey.KeyModifiers.None) + throw new InvalidOperationException("功能键不能为空!"); + if (keyCode == Keys.None) + throw new InvalidOperationException("快捷键不能为空!"); + + AppHotKey.RegKey(FormHandle, id, keyModifiers, keyCode); + item.HotKeyID = id; + } + + /// + /// 注销热键 - 完成后,会清零 HotKeyID + /// + /// The item. + /// item + public void UnRegKey(HotKeyItem item) + { + if (item is null) + throw new ArgumentNullException(nameof(item)); + if (item.HotKeyID == 0) + return; + + AppHotKey.UnRegKey(FormHandle, item.HotKeyID); + item.HotKeyID = 0; + } + + #endregion HotKey Register + + #region HotKey Trigger + + /// + /// 热键触发时调用 + /// + public event EventHandler HotKeyTriggerEvent; + + private bool OnHotKeyTrigger(HotKeyItem item) + { + var args = new HotKeyTriggerEventArgs { HotKeyItem = item }; + HotKeyTriggerEvent?.Invoke(this, args); + return args.Handle; + } + + /// + /// Processes the hotkey. + /// + /// The hot key identifier. + public void ProcessHotkey(int hotKey_id) + { + var hotkey = Items.Find(k => k.HotKeyID == hotKey_id); + if (hotkey != null) + { + //Console.WriteLine($"ID:{hotkey.HotKeyID} Keys:{hotkey.HotKey} ProcessName:{hotkey.ProcessName}\nStartupPath:{hotkey.StartupPath}"); + ++hotkey.TriggerCounter; + // 触发事件,若被外部处理,则内部不再执行 + OnHotKeyTrigger(hotkey); + } + } + + #endregion HotKey Trigger + + #region HotKey Manager + + /// + /// 添加一个新热键 + /// + /// The item. + /// + /// item + /// or + /// HotKey - 热键不能为空! + /// + /// + /// 功能键不能为空! + /// or + /// 快捷键不能为空! + /// + public void AddHotKey(HotKeyItem item) + { + if (item is null) + throw new ArgumentNullException(nameof(item)); + + if (item.Enabled) + RegKey(item); + Items.Add(item); + } + + /// + /// 删除一个热键 + /// + /// The item. + public void DelHotKey(HotKeyItem item) + { + if (item is null) + throw new ArgumentNullException(nameof(item)); + + if (item.HotKeyID != 0) + UnRegKey(item); + Items.Remove(item); + } + + /// + /// 修改热键 + /// + /// The item. + public void ChangeHotKey(HotKeyItem item) + { + if (item is null) + throw new ArgumentNullException(nameof(item)); + + // 重新注册 + if (item.HotKeyID != 0) + UnRegKey(item); + if (item.Enabled) + RegKey(item); + } + + #endregion HotKey Manager + } + + /// + /// 热键触发事件参数 + /// + public class HotKeyTriggerEventArgs + { + public HotKeyItem HotKeyItem { get; set; } + + /// + /// 获取或设置该事件是否已经被处理 + /// + /// + /// true if handle; otherwise, false. + /// + public bool Handle { get; set; } + } +} diff --git a/Source/GrasscutterTools/Utils/HotKeyItem.cs b/Source/GrasscutterTools/Utils/HotKeyItem.cs new file mode 100644 index 0000000..5781409 --- /dev/null +++ b/Source/GrasscutterTools/Utils/HotKeyItem.cs @@ -0,0 +1,77 @@ +using System; +using System.Xml.Serialization; + +namespace GrasscutterTools.Utils +{ + /// + /// 热键项 + /// + public class HotKeyItem + { + /// + /// Gets or sets the hot key identifier. + /// + /// + /// The hot key identifier. + /// + [XmlIgnore] + public int HotKeyID { get; set; } + + /// + /// Gets or sets the name of the Tag. + /// + /// + /// The name of the Tag. + /// + public string Tag { get; set; } + + /// + /// Gets or sets the Commands. + /// + /// + /// The Commands. + /// + public string Commands { get; set; } + + /// + /// Gets or sets the hot key. + /// 组合键之间使用+隔开,例如:"Ctrl+Shift+W" + /// + /// + /// The hot key. + /// + public string HotKey { get; set; } + + /// + /// Gets or sets a value indicating whether this is enabled. + /// + /// + /// true if enabled; otherwise, false. + /// + public bool Enabled { get; set; } = true; + + /// + /// Gets or sets the trigger counter. + /// + /// + /// The trigger counter. + /// + public int TriggerCounter { get; set; } + + /// + /// Gets or sets the creation time. + /// + /// + /// The creation time. + /// + public DateTime CreationTime { get; set; } = DateTime.Now; + + /// + /// Gets or sets the last modified time. + /// + /// + /// The last modified time. + /// + public DateTime LastModifiedTime { get; set; } = DateTime.Now; + } +} \ No newline at end of file