在后台捕获键盘按键

31
我有一个在后台运行的应用程序。每当用户随时按下 F12 键时,我必须生成一些事件。所以我需要捕获按键操作。在我的应用程序中,如果用户在任何时候按下 F10,将执行某些事件。我不知道该怎么做?
有人知道如何做吗?
注: 这是一个WinForms应用程序。它不需要关注我的窗体。我的主窗口可能仍然在系统托盘中,但它仍然必须捕获按键操作。

可能是处理功能键按下的问题的重复。 - James Hill
什么类型的应用程序?“在后台运行”是什么意思?“任何时候”是什么意思(您的应用程序是否具有焦点)? - Wonko the Sane
你是使用表单来进行键盘按键操作吗?这是一个控制台应用程序吗? - DJ Burb
这是一个Winform应用程序。它不需要拥有焦点,我的主窗口可能在系统托盘中,但仍然必须捕获按键操作。 - ImonBayazid
1
@JamesHill:不是这个的重复,因为我们没有谈论相同类型的快捷键。 - Otiel
2个回答

55

您需要的是一个全局热键

  1. 在类的顶部导入所需的库:

// DLL libraries used to manage hotkeys
[DllImport("user32.dll")] 
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
在你的类中添加一个字段,用于在代码中引用快捷键:
const int MYACTION_HOTKEY_ID = 1;
  • 在您的 Windows 表单构造函数中注册热键:

    // Modifier keys codes: Alt = 1, Ctrl = 2, Shift = 4, Win = 8
    // Compute the addition of each combination of the keys you want to be pressed
    // ALT+CTRL = 1 + 2 = 3 , CTRL+SHIFT = 2 + 4 = 6...
    RegisterHotKey(this.Handle, MYACTION_HOTKEY_ID, 6, (int) Keys.F12);
    
    在您的类中添加以下方法来处理键入的按键:

  • protected override void WndProc(ref Message m) {
        if (m.Msg == 0x0312 && m.WParam.ToInt32() == MYACTION_HOTKEY_ID) {
            // My hotkey has been typed
    
            // Do what you want here
            // ...
        }
        base.WndProc(ref m);
    }
    

    2
    顺便说一下,我不是全局热键的忠实粉丝 - 我认为它们可能是“危险”的。如果两个应用程序注册了相同的键,会有意想不到的后果,除非非常小心地处理。即使您小心地处理自己的热键,也不能保证其他应用程序会做同样的事情。就像成为一个优秀的司机,但必须担心道路上的其他司机一样。 - Wonko the Sane
    1
    @WonkotheSane:我完全同意你的观点。这就是为什么(发给@DarkenShooter的消息)使用全局热键的应用程序应该提供一种让用户自定义其全局热键的方式(就像Skype或其他应用程序所做的那样)。 - Otiel
    1
    让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/26177/discussion-between-otiel-and-darkenshooter - Otiel
    2
    我正在尝试在Windows应用程序的main.cs中注册热键,因为我不想让它有任何形式,但是this.Handle在此上下文中不存在。有什么其他方法可以获得它吗? - peter.swallow
    2
    如何在控制台应用程序中使用?我没有这个.Handle。 - nim
    显示剩余9条评论

    19

    如果您在运行Otiel的解决方案时遇到问题:

    1. 您需要包含:

       using System.Runtime.InteropServices; //required for dll import
      
    2. 像我这样的新手还有一个疑问:“班级顶尖”真的意味着你所在班级的顶尖,而不是命名空间或构造函数之类的意思吗?

    3. public partial class Form1 : Form
      {
          [DllImport("user32.dll")]
          public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifers, int vlc);
      
          [DllImport("user32.dll")]
          public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
      }
      
    4. 您无需将user32.dll添加为项目的引用。WinForms始终会自动加载此dll。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接