Files
Taskbar-Launcher/Services/HotkeyService.cs
2026-06-02 17:28:25 -04:00

117 lines
3.2 KiB
C#

using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
namespace TaskbarLauncher.Services;
public sealed class HotkeyService : IDisposable
{
private const int WmHotkey = 0x0312;
private const int HotkeyId = 9001;
private HwndSource? source;
private Window? window;
public event EventHandler? Pressed;
public void Register(string hotkey)
{
Unregister();
window = new Window
{
Width = 0,
Height = 0,
ShowInTaskbar = false,
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
Opacity = 0,
Left = -10000,
Top = -10000
};
window.SourceInitialized += (_, _) =>
{
var helper = new WindowInteropHelper(window);
source = HwndSource.FromHwnd(helper.Handle);
source?.AddHook(WndProc);
ParseHotkey(hotkey, out uint modifiers, out uint key);
RegisterHotKey(helper.Handle, HotkeyId, modifiers, key);
};
window.Show();
window.Hide();
}
public void Unregister()
{
if (window is not null)
{
var helper = new WindowInteropHelper(window);
if (helper.Handle != IntPtr.Zero)
{
UnregisterHotKey(helper.Handle, HotkeyId);
}
}
source?.RemoveHook(WndProc);
source = null;
window?.Close();
window = null;
}
public void Dispose()
{
Unregister();
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WmHotkey && wParam.ToInt32() == HotkeyId)
{
Pressed?.Invoke(this, EventArgs.Empty);
handled = true;
}
return IntPtr.Zero;
}
private static void ParseHotkey(string hotkey, out uint modifiers, out uint key)
{
modifiers = 0;
key = (uint)KeyInterop.VirtualKeyFromKey(Key.Space);
foreach (string part in hotkey.Split('+', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
{
if (part.Equals("Ctrl", StringComparison.OrdinalIgnoreCase) || part.Equals("Control", StringComparison.OrdinalIgnoreCase))
{
modifiers |= 0x0002;
}
else if (part.Equals("Alt", StringComparison.OrdinalIgnoreCase))
{
modifiers |= 0x0001;
}
else if (part.Equals("Shift", StringComparison.OrdinalIgnoreCase))
{
modifiers |= 0x0004;
}
else if (part.Equals("Win", StringComparison.OrdinalIgnoreCase))
{
modifiers |= 0x0008;
}
else if (Enum.TryParse(part, true, out Key parsedKey))
{
key = (uint)KeyInterop.VirtualKeyFromKey(parsedKey);
}
}
}
[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);
}