【问题标题】:C# Detect ESC press key anywhereC#在任何地方检测ESC按键
【发布时间】:2014-10-31 23:48:10
【问题描述】:

我有一个 C# 窗口应用程序正在运行,我想在任何地方按 ESC 时关闭它,即使我的应用程序没有焦点。我该如何实现?

我发现了一些连接键盘,它是低级控制,我不知道也不明白。

【问题讨论】:

  • 我知道如何在键盘对焦时挂机,但我想知道如何在键盘不对焦时挂机。谢谢您的回复
  • 如果你想注册一个全局热键,看这里:stackoverflow.com/questions/48935/…
  • 如果您需要全局有效的热键,RegisterHotKey 是您的最佳选择。不要使用键盘挂钩。但强烈建议不要将 ESC 用作全局热键,因为它在大多数应用程序中都是重要的本地热键。
  • 你的意思是如果我RegisterHotKey其他应用程序就不能用了吧?
  • 您可以查看全局低级挂钩,而不是使用热键。查看差异并选择更合适的。

标签: c# keyboard


【解决方案1】:

【讨论】:

    【解决方案2】:

    使用这个类:

    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);
        }
    }
    

    这样:

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

    那个onKeyDown可以是这样的:

    void myKeyDown(object sender, KeyEventArgs e)
    {
        // Some code for closing you form
        // or any thing you need after press Esc
        // with e.KeyCode
    };
    

    【讨论】:

    • 这对我来说似乎很有趣,我可以问一个简单的问题,这个代码是在 c# 中用于 sharpdevelop 还是在 Visual Studio 中用于 c#
    • 找不到类型或命名空间名称“DllImportAttribute”(您是否缺少 using 指令或程序集引用?)
    • 好的,我忘记使用系统了;使用 System.Diagnostics;使用 System.Runtime.InteropServices;使用 System.Windows.Forms;
    • += 代表是什么意思?
    • 好的,我修改了一些代码,所以你现在可以拥有你的keyCode了:)
    【解决方案3】:

    对于那些寻求检测全局按键并进行按键操作的完整解决方案的人,我已经想通了,并将代码放在 pastebin.com 中以“永不”删除。在这里特别注意 InterceptKeys.cs(按 Ctrl+F):

    http://pastebin.com/u7FUhgYr

    ^ 这段代码是完整的,但不是最理想的。


    然后我稍微改进了代码(一个变化是我创建的新 SendKeys 函数,它发送您想要的任何按键/释放 - 更易于使用!)。这里的这个类,MakroKeys:

    http://pastebin.com/Dedx6hRw

    有两个静态函数,可用于从字符串转换为 System.Windows.Forms.Keys,反之亦然(如果您希望用户能够通过文本和/或显示输入自己的密钥,这将很有用当前通过文本按下的键);这有改进的 MainForm.cs 代码(包含 SendKeys 函数):

    http://pastebin.com/BXzmWeMK

    (注意 MakroKeys.GetKey("lcontrolkey") 调用,它演示了该功能的用法。)


    结合所有这些,您可以做一些非常了不起的事情。另请注意,由于这是导入 DLL 并调用 Windows API 函数,因此您可以在例如c++ 也是。不客气,世界。 ;)

    【讨论】:

      猜你喜欢
      • 2016-03-07
      • 2017-05-30
      • 1970-01-01
      • 2017-05-01
      • 2010-12-17
      • 2014-01-10
      • 2018-07-25
      • 1970-01-01
      • 2017-01-14
      相关资源
      最近更新 更多