C# Detect ESC press key anywhere

前端 未结 3 1813
执念已碎
执念已碎 2020-12-20 08:16

I have a C# windowed application running and I want to close it when I press ESC from anywhere, even when my application does not have focus. How can I implement this?

相关标签:
3条回答
  • 2020-12-20 08:25

    if you want you can set global hook with http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C

    0 讨论(0)
  • 2020-12-20 08:29

    For those looking for a complete solution to detect global key presses and also make key presses, I've figured it all out and put the code in pastebin.com to "never" be deleted. Note especially InterceptKeys.cs here (do a Ctrl+F):

    http://pastebin.com/u7FUhgYr

    ^ This code is complete, but it's sub-optimal.


    Then I improved the code a bit (one change is the new SendKeys function I created which sends whatever key presses/releases you want - much easier to use!). This class here, MakroKeys:

    http://pastebin.com/Dedx6hRw

    has two static functions that can be used to convert from string to System.Windows.Forms.Keys and vice versa (which would be useful if you want the user to be able to input their own key via text and/or display the currently pressed key via text); and this has the improved MainForm.cs code to go with it (containing the SendKeys function):

    http://pastebin.com/BXzmWeMK

    (Note the MakroKeys.GetKey("lcontrolkey") call, which demonstrates the usage of that functionality.)


    With all of this combined you can do some pretty amazing things. Note also that because this is importing DLL's and calling Windows API functions, you can do this rather easily in e.g. c++ too. You're welcome, world. ;)

    0 讨论(0)
  • 2020-12-20 08:41

    Use this class:

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace myNameSpace
    {
        class InterceptKeys
        {
            private const int WH_KEYBOARD_LL = 13;
            private const int WM_KEYDOWN = 0x0100;
            private const int WM_ALTDOWN = 0x0104;
            private static LowLevelKeyboardProc _proc = HookCallback;
            private static IntPtr _hookID = IntPtr.Zero;
    
            public static void Start()
            {
                _hookID = SetHook(_proc);
            }
    
            public static void Stop()
            {
                UnhookWindowsHookEx(_hookID);
            }
    
            public static event KeyEventHandler OnKeyDown;
    
            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 || wParam == (IntPtr)WM_ALTDOWN))
                {
                    var vkCode = (Keys)Marshal.ReadInt32(lParam);
                    OnKeyDown(null, new KeyEventArgs(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);
        }
    }
    

    In this way:

    myNameSpace.InterceptKeys.OnKeyDown+= new KeyEventHandler(myKeyDown);
    
    myNameSpace.InterceptKeys.Start();
    

    that onKeyDown can be like this:

    void myKeyDown(object sender, KeyEventArgs e)
    {
        // Some code for closing you form
        // or any thing you need after press Esc
        // with e.KeyCode
    };
    
    0 讨论(0)
提交回复
热议问题