看起来您正在尝试在系统中创建一个全局热键,并且您的应用程序应该在按下时做出响应。
您将需要两个 Win32 API 函数注册热键 http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx and 注销热键 http://msdn.microsoft.com/en-us/library/windows/desktop/ms646327%28v=vs.85%29.aspx.
看着你的using System.Windows.Input
,看来您正在尝试使用 WPF 来做到这一点,这是可能的。
让我们从相当基本的 P/Invokes 开始:
using System.Runtime.InteropServices;
internal static class NativeMethods
{
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr windowHandle, int hotkeyId, uint modifierKeys, uint virtualKey);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr windowHandle, int hotkeyId);
}
现在,当您注册您的Window
,发生的情况是WM_热键 http://msdn.microsoft.com/en-us/library/windows/desktop/ms646279%28v=vs.85%29.aspx消息被发送到应用程序的消息泵。但是,WPF 将此消息泵从您手中抽象出来,因此您需要添加一个HwndSourceHook
来利用它。
我们如何做到这一切?让我们首先初始化我们的HwndSourceHook
代表。将此片段添加到您的MainWindow
:
using System.Windows.Interop;
static readonly int MyHotKeyId = 0x3000;
static readonly int WM_HOTKEY = 0x312;
void InitializeHook()
{
var windowHelper = new WindowInteropHelper(this);
var windowSource = HwndSource.FromHwnd(windowHelper.Handle);
windowSource.AddHook(MessagePumpHook);
}
IntPtr MessagePumpHook(IntPtr handle, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_HOTKEY)
{
if ((int)wParam == MyHotKeyId)
{
// The hotkey has been pressed, do something!
handled = true;
}
}
return IntPtr.Zero;
}
好的,现在我们已准备好应对WM_HOTKEY
信息。但是,我们仍然需要注册我们的热键!让我们添加另外几个初始化方法:
void InitializeHotKey()
{
var windowHelper = new WindowInteropHelper(this);
// You can specify modifiers such as SHIFT, ALT, CONTROL, and WIN.
// Remember to use the bit-wise OR operator (|) to join multiple modifiers together.
uint modifiers = (uint)ModifierKeys.None;
// We need to convert the WPF Key enumeration into a virtual key for the Win32 API!
uint virtualKey = (uint)KeyInterop.VirtualKeyFromKey(Key.A);
NativeMethods.RegisterHotKey(windowHelper.Handle, MyHotKeyId, modifiers, virtualKey);
}
void UninitializeHotKey()
{
var windowHelper = new WindowInteropHelper(this);
NativeMethods.UnregisterHotKey(windowHelper.Handle, MyHotKeyId);
}
好吧!我们把这些放在哪里?不要将它们放在构造函数中!为什么?因为Handle
将0
并且无效!把它们放在这里(在MainWindow
):
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
InitializeHook();
InitializeHotKey();
}
您可以注册多个热键、取消注册和重新注册新热键……这取决于您。只要记住这一点each hotkey 必须有一个唯一的ID注册到它。这才有意义,因为你的消息泵钩子必须知道which热键导致WM_HOTKEY
信息!
当应用程序关闭时取消注册所有热键也是一个很好的做法。