-
Does Avalonia have global hotkey capability? On Windows, technically, I could use RegisterHotKey to do that, but I'm not sure how to hook into the Avalonia WinProc procedure handling in order to get the WM_HOTKEY message. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
This should work: #8650 (comment) |
Beta Was this translation helpful? Give feedback.
-
For anyone finding this in the future, if you don't want to hack into Avalonia with reflection or use unsafe code, you can do this by just opening your own window with CreateWindowEx. For example: public static class User32Hotkey
{
static WindowProc _wndProcDelegate;
static HWND _hwnd;
static Dictionary<int, Action> _registeredKeys = new();
static User32Hotkey()
{
CreateMessageWindow();
}
public static IDisposable Create(Key key, ModifierKeys modifiers, Action execute)
{
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
var id = virtualKeyCode + ((int)modifiers * 0x10000);
if (_registeredKeys.ContainsKey(id))
throw new InvalidOperationException("Hot key with this key combination is already registered by this application.");
if (!RegisterHotKey(_hwnd, id, (HotKeyModifiers)modifiers, (uint)virtualKeyCode))
throw new Win32Exception();
_registeredKeys.Add(id, execute);
return Disposable.Create(() =>
{
UnregisterHotKey(_hwnd, id);
_registeredKeys.Remove(id);
});
}
private static void CreateMessageWindow()
{
// Ensure that the delegate doesn't get garbage collected by storing it as a field.
_wndProcDelegate = new WindowProc(WndProc);
WNDCLASSEX wndClassEx = new WNDCLASSEX
{
cbSize = (uint)Marshal.SizeOf<WNDCLASSEX>(),
lpfnWndProc = _wndProcDelegate,
hInstance = GetModuleHandle(null),
lpszClassName = "YourAppNameOrSomething" + Guid.NewGuid(),
};
ushort atom = RegisterClassEx(wndClassEx);
if (atom == 0)
throw new Win32Exception();
_hwnd = CreateWindowEx(0, (IntPtr)atom, null, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (_hwnd.IsNull)
throw new Win32Exception();
}
private static IntPtr WndProc(HWND hwnd, uint uMsg, IntPtr wParam, IntPtr lParam)
{
if (uMsg == (uint)WindowMessage.WM_HOTKEY && _registeredKeys.TryGetValue((int)wParam, out var action))
{
action();
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
} |
Beta Was this translation helpful? Give feedback.
-
Does anyone have a solution for Linux/X11 for implementing global hotkeys? |
Beta Was this translation helpful? Give feedback.
This should work: #8650 (comment)