using System.Runtime.InteropServices; using System.Windows.Input; using PersonalToolBox.Models; using PersonalToolBox.Services; namespace PersonalToolBox.Helpers; /// /// 全局快捷键管理器,使用 Win32 API RegisterHotKey / UnregisterHotKey /// public class HotKeyManager { private IntPtr _hwnd; private int _nextId = 1; private readonly Dictionary _hotkeyMap = new(); private readonly ILogService _logService; private readonly IProcessExecutionService _processService; // ──────────────── Win32 API ──────────────── private const int WM_HOTKEY = 0x0312; private const uint MOD_ALT = 0x0001; private const uint MOD_CONTROL = 0x0002; private const uint MOD_SHIFT = 0x0004; private const uint MOD_WIN = 0x0008; [DllImport("user32.dll", SetLastError = true)] private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); [DllImport("user32.dll", SetLastError = true)] private static extern bool UnregisterHotKey(IntPtr hWnd, int id); // ──────────────── 构造函数 ──────────────── public HotKeyManager(ILogService logService, IProcessExecutionService processService) { _logService = logService; _processService = processService; } /// /// 设置窗口句柄(在 MainWindow.OnSourceInitialized 中调用) /// public void Initialize(IntPtr hwnd) { _hwnd = hwnd; } // ──────────────── 注册/注销 ──────────────── /// /// 批量注册所有工具的快捷键 /// public void RegisterAll(IEnumerable tools) { UnregisterAll(); foreach (var tool in tools.Where(t => !string.IsNullOrWhiteSpace(t.HotKey))) Register(tool); } /// /// 为单个工具注册快捷键 /// public void Register(ToolItem tool) { if (_hwnd == IntPtr.Zero) return; if (string.IsNullOrWhiteSpace(tool.HotKey)) return; if (!TryParseHotKey(tool.HotKey, out uint modifiers, out uint vk)) { _logService.Warning($"快捷键格式无效: {tool.HotKey}"); return; } int id = _nextId++; if (RegisterHotKey(_hwnd, id, modifiers, vk)) { _hotkeyMap[id] = tool; _logService.Info($"已注册快捷键: {tool.HotKey} → {tool.Name}"); } else { int err = Marshal.GetLastWin32Error(); _logService.Error($"快捷键注册失败: {tool.HotKey} (错误码: {err},可能与其他程序冲突)"); } } /// /// 注销所有已注册的快捷键 /// private void UnregisterAll() { foreach (var kvp in _hotkeyMap) UnregisterHotKey(_hwnd, kvp.Key); _hotkeyMap.Clear(); } // ──────────────── 消息处理 ──────────────── /// /// 由 WndProc 钩子调用,处理 WM_HOTKEY 消息 /// public bool TryHandleMessage(int msg, IntPtr wParam, IntPtr lParam) { if (msg != WM_HOTKEY) return false; int id = wParam.ToInt32(); if (_hotkeyMap.TryGetValue(id, out var tool)) { _logService.Info($"通过快捷键启动: {tool.Name}"); _ = _processService.ExecuteAsync(tool); } return true; } // ──────────────── 快捷键解析 ──────────────── /// /// 解析快捷键字符串(如 "Ctrl+Alt+T")为修饰键和虚拟键码 /// public static bool TryParseHotKey(string hotkey, out uint modifiers, out uint vk) { modifiers = 0; vk = 0; if (string.IsNullOrWhiteSpace(hotkey)) return false; var parts = hotkey.Split('+', StringSplitOptions.TrimEntries); if (parts.Length < 2) return false; // 解析修饰键(最后一段之前的部分) foreach (var part in parts.Take(parts.Length - 1)) { uint mod = part.ToUpperInvariant() switch { "CTRL" or "CONTROL" => MOD_CONTROL, "ALT" => MOD_ALT, "SHIFT" => MOD_SHIFT, "WIN" or "WINDOWS" => MOD_WIN, _ => 0 }; if (mod == 0) return false; modifiers |= mod; } if (modifiers == 0) return false; // 解析按键(最后一段) var keyStr = parts.Last(); if (keyStr.Length == 1) { vk = char.ToUpperInvariant(keyStr[0]); } else if (Enum.TryParse(keyStr, true, out var key)) { vk = (uint)KeyInterop.VirtualKeyFromKey(key); } else { return false; } return true; } /// /// 程序退出时清理所有快捷键 /// public void Dispose() { UnregisterAll(); } }