如何在C#控制台应用程序中捕获修改器(ctrl,alt,shift)按键作为单键按下?

时间:2018-06-04 21:21:32

标签: c# .net console-application

Console.ReadKey仅在按下“普通”键时捕获输入,然后将修饰符(如果有)作为键信息的一部分附加。如何将单个修改键按下作为输入?

2 个答案:

答案 0 :(得分:1)

this link提供了一种解决方案。我对上述代码进行了一些编辑,以作为您问题的答案。

运行此代码:

  1. 创建Console Application
  2. 添加对System.Windows.Forms.dll程序集
  3. 的引用
  4. 粘贴此代码并进行测试。
  5. 代码:

    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 wParam, 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", CharSet = CharSet.Auto, SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool UnhookWindowsHookEx(IntPtr hhk);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, 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();
        }
    }
    

答案 1 :(得分:0)

您是否在控制台应用程序中?这是WinForm代码:

here复制。试试这个:

private void YourControl_KeyDown(object sender, KeyEventArgs e)
{ 
    if (e.KeyCode  == Keys.Menu)
    {
        //YourCode
        e.Handled = true;
    }
}

private void YourControl_KeyUp(object sender, KeyEventArgs e)
{ 
    if (e.KeyData == Keys.Menu)
    {
        //YourCode
        e.Handled = true;
    }
}

也许还有Control和Shift的修饰符?如果没有,我担心您需要使用计时器并反复检查状态,或者全局键盘钩可能会捕获它。

修饰键不会引发标准的KeyPress事件。