C#-System.Windows.Forms.Keys-如何将应用程序热键保持在一个位置

本文关键字:位置 一个 Keys- Forms Windows 应用程序 C#-System | 更新日期: 2023-09-27 17:57:29

我的应用程序中几乎没有"热键"。所有"热键"序列在应用范围内都是唯一的(例如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.修饰符==键。Shift&e.KeyCode==钥匙向上

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

C#-System.Windows.Forms.Keys-如何将应用程序热键保持在一个位置

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

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注册为密钥处理程序。

然后,您可以将密钥添加到任何您想要的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()来证明该事件被触发:

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

您可以随意注册或注销事件处理程序,例如在打开和关闭窗体时,或者具有应用程序范围的处理程序。这取决于你。

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

相关文章: