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;
|
2023-05-22 07:13:18 +12:00
|
|
|
|
using SystemTrayMenu.DllImports;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
using SystemTrayMenu.UserInterface.HotkeyTextboxControl;
|
|
|
|
|
using SystemTrayMenu.Utilities;
|
|
|
|
|
|
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;
|
|
|
|
|
private readonly Window window = new(); // TODO: Try using mainMenu to spare creating additional Win32 window handle?
|
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--)
|
|
|
|
|
{
|
|
|
|
|
NativeMethods.User32UnregisterHotKey(hwnd.Handle, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-23 09:57:54 +12:00
|
|
|
|
internal void RegisterHotKey(string hotKeyString)
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2023-05-23 09:57:54 +12:00
|
|
|
|
ModifierKeys modifiers = HotkeyControl.HotkeyModifiersFromString(hotKeyString);
|
2023-05-25 09:47:49 +12:00
|
|
|
|
Key key = HotkeyControl.HotkeyFromString(hotKeyString);
|
|
|
|
|
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
|
|
|
|
|
int nextId = currentId + 1;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
|
2023-05-25 09:47:49 +12:00
|
|
|
|
if (!NativeMethods.User32RegisterHotKey(hwnd.Handle, nextId, (uint)modifiers, (uint)virtualKeyCode))
|
2022-10-23 11:02:31 +13:00
|
|
|
|
{
|
2023-05-22 07:13:18 +12:00
|
|
|
|
string errorHint = NativeMethods.GetLastErrorHint();
|
|
|
|
|
throw new InvalidOperationException(Translator.GetText("Could not register the hot key.") + " (" + errorHint + ")");
|
2022-10-23 11:02:31 +13:00
|
|
|
|
}
|
2023-05-25 09:47:49 +12:00
|
|
|
|
|
|
|
|
|
currentId = nextId;
|
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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|