2011-05-20 43 views
3

我在我的應用程序中沒有幾個「熱鍵」。所有「熱鍵」序列在應用範圍內都是唯一的(例如F12鍵總是會觸發相同的單個任務)。在一些地方有像這裏處理:C# - System.Windows.Forms.Keys - 如何將應用程序熱鍵保存在一個地方

 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,我將能夠在一個地方進行編輯,而不是搜索&替換工具..

回答

4

完整解決方案重要的是使用某種形式的命令管理,您可以在其中定義應用程序範圍的命令並(可選)爲它們分配熱鍵。

WPF支持內置命令管理,並且您可以在不付出太多努力的情況下自行推出。

如果您不想沿着這條路線走,您可以爲關鍵信息創建應用程序範圍的過濾器,並使用這些過濾器。

以下是KeyStore類的代碼。它是一個單例類,充當鍵的消息過濾器。

/// <summary> 
/// The KeyStoreEventHandler is used by the KeyPress event of the KeyStore 
/// class. It notifies listeners of a named key press. 
/// </summary> 
/// <param name="name">The name of the key.</param> 
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<Keys, string> _definitions; 

    // The KeyPressed Event 
    public event KeyStoreEventHandler KeyPress; 

    /// <summary> 
    /// Adds a key definition to the store. 
    /// </summary> 
    /// <param name="name">The name of the key.</param> 
    /// <param name="key">The key</param> 
    /// <param name="modifiers">The modifiers (shift, control)</param> 
    public void AddKeyDefinition(string name, Keys key, Keys modifiers) 
    { 
     Keys combined = key | modifiers; 

     _definitions[combined] = name; 
    } 

    /// <summary> 
    /// The filter message. 
    /// </summary> 
    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; 
    } 

    /// <summary> 
    /// Compares a key against the definitions, and raises an event 
    /// if there is a match. 
    /// </summary> 
    /// <param name="key">The key</param> 
    /// <returns>True if the key was one of the defined key combinations.</returns> 
    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; 
    } 

    /// <summary> 
    /// Attempt to handle a modifier key, and return a boolean indicating if a modifier key was 
    /// handled. 
    /// </summary> 
    /// <param name="key">The key</param> 
    /// <param name="isDown">True if the key is pressed; False if it is released.</param> 
    /// <returns>True if a modifier key was selected; False otherwise.</returns> 
    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; 
    } 

    /// <summary> 
    /// Raises the KeyPress event. 
    /// </summary> 
    /// <param name="name">The name of the key.</param> 
    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); 

    } 

    /// <summary> 
    /// Returns the singleton instance. 
    /// </summary> 
    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<Keys, string>(); 
    } 
} 

要使用它,首先將鍵過濾器分配給Application類。在您的Main()方法(在Program.cs文件可能),Application.Run()之前添加以下行:

Application.AddMessageFilter(KeyStore.Instance); 

確保此行Application.Run之前插入()。這將KeyStore註冊爲密鑰處理程序。

然後,您可以在主窗體的Form_Load鍵添加到您想要的任何地方密鑰庫,例如:

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

此註冊了兩個組合:F12和控制+ S。

然後,註冊一個事件處理程序,以便捕獲CloseApp和Save鍵。

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

在我的示例代碼中,我用MessageBox.Show(),以證明該事件被觸發:

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

可以註冊或當形式打開和關閉註銷隨意,事件處理程序例如,或者具有應用程序範圍的處理程序。隨你便。

因爲KeyStore是一個單身人士,所以您可以在應用程序的任何位置添加密鑰定義。在調用Application.Run()之前,您可以在Main()方法中執行此操作,也可以添加一些代碼以從配置文件加載定義。

+0

Thx Edwin爲這樣的完整解決方案!問候! – binball 2011-05-21 21:32:49

相關問題