Reputation: 23253
I've been trying to use System-Wide/Global HotKeys in my latest WPF/C# project. Lucky for me, I came upon this wonderful class, here - http://www.codeproject.com/Tips/274003/Global-Hotkeys-in-WPF.
The only problem is, I can't get it to work. I've been banging my head with this since last week, and the weird thing is, I'm getting no errors. Here's my code, any ideas why?
HotKey hotkey = new HotKey((System.Windows.Interop.HwndSource)System.Windows.Interop.HwndSource.FromVisual(App.Current.MainWindow));
//hotkey.Modifiers = list[i]._HotkeyA.Modifier; hotkey.Key = list[i]._HotkeyA._Key;
hotkey.Modifiers = HotKey.ModifierKeys.Shift; hotkey.Key = Key.F2;
hotkey.HotKeyPressed += new EventHandler<HotKeyEventArgs>(delegate(Object o, HotKeyEventArgs e)
{
Console.WriteLine("Congratulations, Cap'n.");
System.Windows.Forms.MessageBox.Show("YAAY HOTKEY HAZ BEEN TEH PRESSEDS!");
});
hotkey.Enabled = true;
Thanks in advance!
Upvotes: 2
Views: 1702
Reputation: 1449
The following implementation Uses the WPF ComponentDispatcher class to Dispatch Windows Messages.
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
[Flags]
public enum ModifierKeyCodes : uint
{
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8
}
/// <summary>
/// Virtual Key Codes
/// </summary>
public enum VirtualKeyCodes : uint
{
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90
}
class KeyboardHook : IDisposable
{
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, ModifierKeyCodes fdModifiers, VirtualKeyCodes vk);
#region Fields
WindowInteropHelper host;
bool IsDisposed = false;
int Identifier;
public Window Window { get; private set; }
public VirtualKeyCodes Key { get; private set; }
public ModifierKeyCodes Modifiers { get; private set; }
#endregion
public KeyboardHook(Window Window, VirtualKeyCodes Key, ModifierKeyCodes Modifiers)
{
this.Key = Key;
this.Modifiers = Modifiers;
this.Window = Window;
host = new WindowInteropHelper(Window);
Identifier = Window.GetHashCode();
RegisterHotKey(host.Handle, Identifier, Modifiers, Key);
ComponentDispatcher.ThreadPreprocessMessage += ProcessMessage;
}
void ProcessMessage(ref MSG msg, ref bool handled)
{
if ((msg.message == 786) && (msg.wParam.ToInt32() == Identifier) && (Triggered != null))
Triggered();
}
public event Action Triggered;
public void Dispose()
{
if (!IsDisposed)
{
ComponentDispatcher.ThreadPreprocessMessage -= ProcessMessage;
UnregisterHotKey(host.Handle, Identifier);
Window = null;
host = null;
}
IsDisposed = true;
}
}
Disposing the Object Unregisters the HotKey. You need to hold a reference to the KeyboardHook class to prevent it from being unregistered.
Example:
// Registers a Hook to MyWindow - Ctrl+A and calls DoWork() when Triggered.
var KH = new KeyboardHook(MyWindow, VirtualKeyCodes.A, ModifierKeyCodes.Ctrl);
KH += () => DoWork();
// When you don't need the Hook
KH.Dispose();
Upvotes: 4
Reputation: 6094
Make sure you are holding a strong reference to that HotKey. From the link you provided that object has a finalizer that would set the Enabled to false which would unregister the hotkey.
Upvotes: 0