C# – System.Windows.Forms.Keys – 如何将应用程序热键保存在一个地方

我的应用程序中没有“热键”。 所有“热键”序列在应用范围内都是唯一的(例如,F12键将始终触发相同的单个任务)。 在很少的地方像这里处理:

if (e.Modifiers == Keys.Shift && e.KeyCode == Keys.Delete) { this.Close(); } if (e.Modifiers == Keys.Shift && e.KeyCode == Keys.Up) { if (Program.PerformLogin()) { frmConfigurationSetup frmSetup = new frmConfigurationSetup(); frmSetup.Show(); } } if (e.KeyCode == Keys.F12) { frmAbout formAbout = new frmAbout(); formAbout.Show(); } 

但我有想法将我的应用程序中使用的所有键盘快捷键保存在一个地方。 我想把它们放在Constants.cs文件中:

  public const System.Windows.Forms.Keys ShowAboutForm = System.Windows.Forms.Keys.F12; 

但是如何在这个序列的情况下实现这个:e.Modifiers == Keys.Shift && e.KeyCode == Keys.Up

所有建议如何将所有应用程序“热键”定义存储在一个地方是受欢迎的:)所以有一天,如果我需要将Keys.F12更改为Keys.F10,我将能够在一个地方编辑它而不是搜索和替换工具..

对此的完整解决方案是使用某种forms的命令管理,您可以在其中定义应用程序范围的命令,并(可选)为其分配热键。

WPF支持内置的Command Management,您可以不费力地推出自己的命令。

如果您不想沿着该路线前进,可以为关键消息创建应用程序范围的filter,并使用它们。

下面是KeyStore类的代码。 它是一个单例类,充当键的消息filter。

 ///  /// The KeyStoreEventHandler is used by the KeyPress event of the KeyStore /// class. It notifies listeners of a named key press. ///  /// The name of the key. public delegate void KeyStoreEventHandler(string name); class KeyStore : IMessageFilter { // Interop [DllImport("user32.dll")] static extern short GetKeyState(Keys key); // Windows message constants private const int WM_KEYDOWN = 0x100; private const int WM_KEYUP = 0x101; // The singleton instance private static KeyStore s_instance = null; // The modifier keys private bool _shift = false; private bool _control = false; // The definitions private Dictionary _definitions; // The KeyPressed Event public event KeyStoreEventHandler KeyPress; ///  /// Adds a key definition to the store. ///  /// The name of the key. /// The key /// The modifiers (shift, control) public void AddKeyDefinition(string name, Keys key, Keys modifiers) { Keys combined = key | modifiers; _definitions[combined] = name; } ///  /// The filter message. ///  public bool PreFilterMessage(ref Message m) { bool handled = false; Keys key = Keys.None; switch (m.Msg) { case WM_KEYUP: key = (Keys)m.WParam; handled = HandleModifier(key, false); break; case WM_KEYDOWN: key = (Keys)m.WParam; handled = HandleModifier(key, true); if (false == handled) { // If one of the defined keys was pressed then we // raise an event. handled = HandleDefinedKey(key); } break; } return handled; } ///  /// Compares a key against the definitions, and raises an event /// if there is a match. ///  /// The key /// True if the key was one of the defined key combinations. private bool HandleDefinedKey(Keys key) { bool handled = false; Keys combined = key; if (_shift) combined |= Keys.Shift; if (_control) combined |= Keys.Control; // If we have found a matching combination then we // raise an event. string name = null; if (true == _definitions.TryGetValue(combined, out name)) { OnKeyPress(name); handled = true; } return handled; } ///  /// Attempt to handle a modifier key, and return a boolean indicating if a modifier key was /// handled. ///  /// The key /// True if the key is pressed; False if it is released. /// True if a modifier key was selected; False otherwise. private bool HandleModifier(Keys key, bool isDown) { bool handled = false; switch (key) { case Keys.RControlKey: case Keys.ControlKey: _control = isDown; handled = true; break; case Keys.RShiftKey: case Keys.ShiftKey: _shift = isDown; handled = true; break; } return handled; } ///  /// Raises the KeyPress event. ///  /// The name of the key. private void OnKeyPress(string name) { // Raise event if (null != KeyPress) KeyPress(name); // Check if modifier keys were released in the mean time. _control = -127 == GetKeyState(Keys.ControlKey) || -127 == GetKeyState(Keys.RControlKey); _shift = -127 == GetKeyState(Keys.ShiftKey) || -127 == GetKeyState(Keys.RShiftKey); } ///  /// Returns the singleton instance. ///  public static KeyStore Instance { get { if (null == s_instance) s_instance = new KeyStore(); return s_instance; } } // The constructor is private because this is a singleton class. private KeyStore() { _definitions = new Dictionary(); } } 

要使用它,首先将键filter分配给Application类。 在Main()方法中(可能在Program.cs文件中),在Application.Run()之前添加以下行:

 Application.AddMessageFilter(KeyStore.Instance); 

确保在Application.Run()之前插入此行。 这将KeyStore注册为密钥处理程序。

然后,您可以在任何地方向KeyStore添加密钥,例如在主窗体的Form_Load中:

 KeyStore.Instance.AddKeyDefinition("CloseApp", Keys.F12, Keys.None); KeyStore.Instance.AddKeyDefinition("Save", Keys.S, Keys.Control); 

这会注册两种组合:F12和Control + S.

然后,注册一个事件处理程序,以便捕获CloseApp和Save按键。

 KeyStore.Instance.KeyPress += new KeyStoreEventHandler(KeyStore_KeyPress); 

在我的示例代码中,我使用MessageBox.Show()来certificate事件被触发:

 void KeyStore_KeyPress(string name) { MessageBox.Show(String.Format("Key '{0}' was pressed!", name)); } 

例如,当表单打开和关闭时,您可以随意注册或取消注册事件处理程序,或者具有应用程序范围的处理程序。 由你决定。

由于KeyStore是单例,因此您可以从应用程序的任何位置添加键定义。 您可以在调用Application.Run()之前在Main()方法中执行此操作,也可以添加一些代码以从配置文件加载定义。