2022-10-23 11:02:31 +13:00
|
|
|
|
// <copyright file="KeyboardHook.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
|
|
|
|
|
2023-04-17 00:17:33 +12:00
|
|
|
|
namespace SystemTrayMenu.Helpers
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
|
|
|
|
using System;
|
2023-05-25 09:47:49 +12:00
|
|
|
|
using System.Windows;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
using System.Windows.Input;
|
2023-05-25 09:47:49 +12:00
|
|
|
|
using System.Windows.Interop;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
2023-05-26 10:34:31 +12:00
|
|
|
|
// TODO: Move this whole class into mainMenu to spare creating additional Win32 window handles by using Menu's Window directly.
|
2023-05-25 09:47:49 +12:00
|
|
|
|
internal class KeyboardHook : IDisposable
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2023-05-25 09:47:49 +12:00
|
|
|
|
private readonly HwndSourceHook hook;
|
|
|
|
|
private readonly HwndSource hwnd;
|
2023-05-26 10:34:31 +12:00
|
|
|
|
private readonly Window window = new();
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private int currentId;
|
|
|
|
|
|
|
|
|
|
public KeyboardHook()
|
|
|
|
|
{
|
2023-05-25 09:47:49 +12:00
|
|
|
|
hwnd = HwndSource.FromHwnd(new WindowInteropHelper(window).EnsureHandle());
|
|
|
|
|
hook = new HwndSourceHook(WndProc);
|
|
|
|
|
hwnd.AddHook(hook);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A hot key has been pressed.
|
|
|
|
|
/// </summary>
|
2023-05-23 09:57:54 +12:00
|
|
|
|
internal event Action<Key, ModifierKeys>? KeyPressed;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
2023-05-25 09:47:49 +12:00
|
|
|
|
// On regular App.Dispose the handle was already invalidated
|
|
|
|
|
if (hwnd.Handle != IntPtr.Zero)
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2023-05-25 09:47:49 +12:00
|
|
|
|
// unregister all the registered hot keys.
|
|
|
|
|
for (int i = currentId; i > 0; i--)
|
|
|
|
|
{
|
2023-05-26 10:34:31 +12:00
|
|
|
|
GlobalHotkeys.UnregisterHotkey(hwnd.Handle, i);
|
2023-05-25 09:47:49 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hwnd.RemoveHook(hook);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-25 09:47:49 +12:00
|
|
|
|
hwnd.Dispose();
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-26 10:34:31 +12:00
|
|
|
|
internal void RegisterHotKey(ModifierKeys modifiers, Key key) => currentId = GlobalHotkeys.RegisterHotkeyLocal(hwnd.Handle, currentId + 1, modifiers, key);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
2023-05-26 10:34:31 +12:00
|
|
|
|
internal void RegisterHotKey(string hotKeyString) => currentId = GlobalHotkeys.RegisterHotkeyLocal(hwnd.Handle, currentId + 1, hotKeyString);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
2023-05-25 09:47:49 +12:00
|
|
|
|
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2023-05-25 09:47:49 +12:00
|
|
|
|
const int WmHotkey = 0x0312;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
2023-05-25 09:47:49 +12:00
|
|
|
|
// check if we got a hot key pressed.
|
|
|
|
|
if (msg == WmHotkey)
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2023-05-25 09:47:49 +12:00
|
|
|
|
// get the keys.
|
|
|
|
|
ModifierKeys modifiers = (ModifierKeys)((int)lParam & 0xFFFF);
|
|
|
|
|
int virtualKeyCode = ((int)lParam >> 16) & 0xFFFF;
|
|
|
|
|
Key key = KeyInterop.KeyFromVirtualKey(virtualKeyCode);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
2023-05-25 09:47:49 +12:00
|
|
|
|
// invoke the event to notify the parent.
|
|
|
|
|
KeyPressed?.Invoke(key, modifiers);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
2023-05-25 09:47:49 +12:00
|
|
|
|
|
|
|
|
|
handled = false;
|
|
|
|
|
return IntPtr.Zero;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|