有谁知道如何在控制台应用程序中使用RegisterHotKey / UnregisterHotKey API调用?我假设设置/删除热键是相同的,但是当按下键时如何回拨电话?
我看到的每个示例都是针对Winforms的,并使用protected override void WndProc(ref Message m){...},对我来说不可用。
protected override void WndProc(ref Message m){...}
更新: 下面是我所拥有的,但从未成功过。我认为这可能是因为加载ConsoleShell时,它确实阻止了进一步的执行,但是即使我放入SetupHotkey了另一个线程也没有任何反应。有什么想法吗?
SetupHotkey
class Program { static void Main(string[] args) { new Hud().Init(args); } } class Hud { int keyHookId; public void Init(string[] args) { SetupHotkey(); InitPowershell(args); Cleanup(); } private void Cleanup() { HotKeyManager.UnregisterHotKey(keyHookId); } private void SetupHotkey() { keyHookId = HotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Control); HotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(HotKeyManager_HotKeyPressed); } void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e) { //never executed System.IO.File.WriteAllText("c:\\keyPressed.txt", "Hotkey pressed"); } private static void InitPowershell(string[] args) { var config = RunspaceConfiguration.Create(); ConsoleShell.Start(config, "", "", args); } }
您可以做的是在控制台应用程序中创建一个隐藏窗口,该窗口用于处理热键通知并引发事件。
这里的代码演示了原理。这里是有关在控制台应用程序中处理消息的文章,使用它您应该能够增强HotKeyManager使其在控制台应用程序中运行。
对HotKeyManager的以下更新将创建一个后台线程,该线程运行消息循环并处理Windows消息。
using System; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Threading; namespace ConsoleHotKey { public static class HotKeyManager { public static event EventHandler<HotKeyEventArgs> HotKeyPressed; public static int RegisterHotKey(Keys key, KeyModifiers modifiers) { _windowReadyEvent.WaitOne(); int id = System.Threading.Interlocked.Increment(ref _id); _wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, id, (uint)modifiers, (uint)key); return id; } public static void UnregisterHotKey(int id) { _wnd.Invoke(new UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal), _hwnd, id); } delegate void RegisterHotKeyDelegate(IntPtr hwnd, int id, uint modifiers, uint key); delegate void UnRegisterHotKeyDelegate(IntPtr hwnd, int id); private static void RegisterHotKeyInternal(IntPtr hwnd, int id, uint modifiers, uint key) { RegisterHotKey(hwnd, id, modifiers, key); } private static void UnRegisterHotKeyInternal(IntPtr hwnd, int id) { UnregisterHotKey(_hwnd, id); } private static void OnHotKeyPressed(HotKeyEventArgs e) { if (HotKeyManager.HotKeyPressed != null) { HotKeyManager.HotKeyPressed(null, e); } } private static volatile MessageWindow _wnd; private static volatile IntPtr _hwnd; private static ManualResetEvent _windowReadyEvent = new ManualResetEvent(false); static HotKeyManager() { Thread messageLoop = new Thread(delegate() { Application.Run(new MessageWindow()); }); messageLoop.Name = "MessageLoopThread"; messageLoop.IsBackground = true; messageLoop.Start(); } private class MessageWindow : Form { public MessageWindow() { _wnd = this; _hwnd = this.Handle; _windowReadyEvent.Set(); } protected override void WndProc(ref Message m) { if (m.Msg == WM_HOTKEY) { HotKeyEventArgs e = new HotKeyEventArgs(m.LParam); HotKeyManager.OnHotKeyPressed(e); } base.WndProc(ref m); } protected override void SetVisibleCore(bool value) { // Ensure the window never becomes visible base.SetVisibleCore(false); } private const int WM_HOTKEY = 0x312; } [DllImport("user32", SetLastError=true)] private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); [DllImport("user32", SetLastError = true)] private static extern bool UnregisterHotKey(IntPtr hWnd, int id); private static int _id = 0; } public class HotKeyEventArgs : EventArgs { public readonly Keys Key; public readonly KeyModifiers Modifiers; public HotKeyEventArgs(Keys key, KeyModifiers modifiers) { this.Key = key; this.Modifiers = modifiers; } public HotKeyEventArgs(IntPtr hotKeyParam) { uint param = (uint)hotKeyParam.ToInt64(); Key = (Keys)((param & 0xffff0000) >> 16); Modifiers = (KeyModifiers)(param & 0x0000ffff); } } [Flags] public enum KeyModifiers { Alt = 1, Control = 2, Shift = 4, Windows = 8, NoRepeat = 0x4000 } }
这是从控制台应用程序使用HotKeyManager的示例
using System; using System.Windows.Forms; namespace ConsoleHotKey { class Program { static void Main(string[] args) { HotKeyManager.RegisterHotKey(Keys.A, KeyModifiers.Alt); HotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(HotKeyManager_HotKeyPressed); Console.ReadLine(); } static void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e) { Console.WriteLine("Hit me!"); } } }