Console.ReadKey仅在按下“普通”键时捕获输入,然后将修饰符(如果有)作为键信息的一部分附加.如何将单个修改键按下作为输入?
解决方法
在
this link中提供了一个解决方案.我对上述代码进行了一些编辑,以作为您问题的答案.
要运行此代码:
>创建控制台应用程序@H_301_9@>添加对System.Windows.Forms.dll程序集的引用@H_301_9@>粘贴此代码并进行测试.
码:
using System; using System.Diagnostics; using System.Windows.Forms; using System.Runtime.InteropServices; class Program { class InterceptKeys { // https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/ private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private static LowLevelKeyboardProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL,proc,GetModuleHandle(curModule.ModuleName),0); } } private delegate IntPtr LowLevelKeyboardProc(int nCode,IntPtr wParam,IntPtr lParam); private static IntPtr HookCallback(int nCode,IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { int vkCode = Marshal.ReadInt32(lParam); OnKeyDown?.Invoke(new KeyEventArgs((Keys)vkCode)); } return CallNextHookEx(_hookID,nCode,wParam,lParam); } [DllImport("user32.dll",CharSet = CharSet.Auto,SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook,LowLevelKeyboardProc lpfn,IntPtr hMod,uint dwThreadId); [DllImport("user32.dll",SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll",SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk,int nCode,IntPtr lParam); [DllImport("kernel32.dll",SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); private static event OnKeyDownDelegate OnKeyDown = null; public delegate void OnKeyDownDelegate(KeyEventArgs e); public static void SetupHook(OnKeyDownDelegate OnKeyDown) { InterceptKeys.OnKeyDown = OnKeyDown; System.Threading.Tasks.Task.Run(() => { _hookID = SetHook(_proc); Application.Run(); UnhookWindowsHookEx(_hookID); }); } public static void ReleaseHook() { Application.Exit(); } } static void KeyDown(KeyEventArgs e) { Console.WriteLine("Hook: "+ e.KeyCode); } static void Main() { InterceptKeys.SetupHook(KeyDown); while (true) { ConsoleKey key = Console.ReadKey(true).Key; Console.WriteLine("ReadKey: "+ key); if (key == ConsoleKey.Escape) break; } InterceptKeys.ReleaseHook(); } }