如何创build不受窗口限制的键盘快捷键

我正在创build一个C#应用程序,可能是WinForm,但最好是控制台应用程序,即使应用程序不在前台,也需要捕获键盘快捷键。 如何做到这一点,我知道这是可能的,即即宋鸟可以做到这一点。

这个键盘快捷键的forms是ctrl + - >我到目前为止没有任何代码,因为我甚至没有关于如何在全球范围内注册键盘快捷键的想法。

你应该使用RegisterHotkey而不是键盘钩子。

当你想要一个全局热键时使用全局键盘钩子是api的滥用。 它也有负面的性能影响,因为每个关键点在到达目标程序之前都需要由您的程序进行处理。

这里有一个示例代码,我希望能帮助…(祝你好运!!!)

用法:

_hotKey0 = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler); 

  // ****************************************************************** private void OnHotKeyHandler(HotKey hotKey) { SystemHelper.SetScreenSaverRunning(); } 

类:

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Mime; using System.Runtime.InteropServices; using System.Text; using System.Windows; using System.Windows.Input; using System.Windows.Interop; namespace UnManaged { public class HotKey : IDisposable { private static Dictionary<int, HotKey> _dictHotKeyToCalBackProc; [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc); [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id); public const int WmHotKey = 0x0312; private bool _disposed = false; public Key Key { get; private set; } public KeyModifier KeyModifiers { get; private set; } public Action<HotKey> Action { get; private set; } public int Id { get; set; } // ****************************************************************** public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> action, bool register = true) { Key = k; KeyModifiers = keyModifiers; Action = action; if (register) { Register(); } } // ****************************************************************** public bool Register() { int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key); Id = virtualKeyCode + ((int)KeyModifiers * 0x10000); bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode); if (_dictHotKeyToCalBackProc == null) { _dictHotKeyToCalBackProc = new Dictionary<int, HotKey>(); ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage); } _dictHotKeyToCalBackProc.Add(Id, this); Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode); return result; } // ****************************************************************** public void Unregister() { HotKey hotKey; if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey)) { UnregisterHotKey(IntPtr.Zero, Id); } } // ****************************************************************** private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled) { if (!handled) { if (msg.message == WmHotKey) { HotKey hotKey; if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey)) { if (hotKey.Action != null) { hotKey.Action.Invoke(hotKey); } handled = true; } } } } // ****************************************************************** // Implement IDisposable. // Do not make this method virtual. // A derived class should not be able to override this method. public void Dispose() { Dispose(true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SupressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } // ****************************************************************** // Dispose(bool disposing) executes in two distinct scenarios. // If disposing equals true, the method has been called directly // or indirectly by a user's code. Managed and unmanaged resources // can be _disposed. // If disposing equals false, the method has been called by the // runtime from inside the finalizer and you should not reference // other objects. Only unmanaged resources can be _disposed. protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this._disposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if (disposing) { // Dispose managed resources. Unregister(); } // Note disposing has been done. _disposed = true; } } } // ****************************************************************** [Flags] public enum KeyModifier { None = 0x0000, Alt = 0x0001, Ctrl = 0x0002, NoRepeat = 0x4000, Shift = 0x0004, Win = 0x0008 } // ****************************************************************** } 

一种可能的方法是使用Windows挂钩。 但是为了做到这一点,你需要创建一个本地DLL,并在其中编写回调函数来安装为一个钩子。

查找SetWindowsHookEx作为起点。 网上还有很多关于如何使用它的样本。

这可以通过一个低级键盘钩子通过Windows钩子陷阱WH_KEYBOARD_LL完成 。

这是一个关于在C#中设置全局钩子的CodeProject文章,它演示了整个过程。