117 lines
3.2 KiB
C#
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);
|
|
}
|