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();
}
}