2011-11-22 16 views
1

我一直在尝试在我最新的WPF/C#项目中使用系统范围/全局热键。对我来说幸运的是,我来到了这个美妙的课堂,在这里 - http://www.codeproject.com/Tips/274003/Global-Hotkeys-in-WPF试图在WPF/C中使用(系统范围)热键#

唯一的问题是,我不能得到它的工作。自从上周以来,我一直在抨击我的头脑,奇怪的是,我没有犯错。这是我的代码,任何想法为什么?

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; 

在此先感谢!

+0

我已经使用命令和结合的办法,在这里一个例子http://stackoverflow.com/questions/2382916/binding-a-wpf-shortcut-key-to-a -command-in-the-viewmodel – kenny

+0

谢谢,但我的意思是全系统的热键。 – mattsven

+0

你使用System.Windows.Input.Key.F2或它的WindowsForms“兄弟”吗? – Tigran

回答

0

确保您持有对该热键的强烈参考。从您提供的链接中,该对象具有一个终结器,它将Enabled设置为false,这将取消注册该热键。

+0

请注意,如果这不是问题,请发布一个更完整的使用片段 - 即您创建热键的位置等。 – AndrewS

1

以下实现使用WPF ComponentDispatcher类来分派Windows消息。

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; 
} 
} 

处置对象取消注册热键。 您需要保留对KeyboardHook类的引用,以防止其未注册。

例子:

// 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(); 
+0

好!我有一段时间没有使用C#,但这看起来很方便。 – mattsven