C# - System.Windows.Forms.Keys - 如何保持应用程序的热键在一个地方 [英] C# - System.Windows.Forms.Keys - How to keep application hotkeys in one place

查看:1657
本文介绍了C# - System.Windows.Forms.Keys - 如何保持应用程序的热键在一个地方的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序数热键。所有的热键序列中的应用范围(因此,例如F12键总是火一样的单任务)是唯一的。在少数地方有喜欢这里处理:

I have few "hotkeys" in my application. All "hotkeys" sequences are unique in application scope (so for example F12 key will always fire the same single task). In few places there are handled like here:

        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文件:

But I have idea to keep all keyboard shortcuts used in my app in one place. I was thinking to put them in Constants.cs file:

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



但如何在这个序列的情况下,实现这一目标:
e.Modifiers ==键.Shift&功放;&安培; e.KeyCode == Keys.Up

But how to achieve this in case of this sequence: e.Modifiers == Keys.Shift && e.KeyCode == Keys.Up

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

All advices how to store all application "hotkeys" definitions in one place are welcome :) So one day if I need to change Keys.F12 to Keys.F10 I will be able to just edit it in one place instead of search&replace tool..

推荐答案

这个完整的解决方案是使用某种形式的命令管理,在这里您可以定义应用程序范围的命令和(可选)分配热键给他们的。

A complete solution to this would be to use some form of Command Management, where you define application-wide commands and (optionally) assign hot-keys to them.

WPF有命令管理的支持内置的,你可以推出自己没有太多的精力。

WPF has support for Command Management built-in, and you can roll out your own without too much effort.

如果您不希望走这条路线,你可以创建对于关键信息的应用范围过滤器,以及工作与那些。

If you don't want to go down that route, you can create an application-wide filter for key messages, and work with those.

下面是一个KeyStore类代码。它是一个单例类充当密钥的消息过滤器

Below is code for a KeyStore class. It's a singleton class that acts as a message filter for keys.

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

要使用它,首先分配键过滤器的应用程序类。在Main()方法(可能在Program.cs文件),添加以下行之前Application.Run():

To use it, first assign the key filter to the Application class. In your Main() method (probably in the Program.cs file), add the following line before Application.Run():

Application.AddMessageFilter(KeyStore.Instance);

请确保此行Application.Run之前插入()。这个注册密钥库作为重点处理程序

Make sure this line is inserted before Application.Run(). This registers the KeyStore as a key handler.

然后,您可以在Form_Load添加密钥到你想要的密钥库的任何地方,比如你的主要形式:

Then, you can add keys to the KeyStore anywhere you want, for example in the Form_Load of your main form:

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

这注册了两个组合:F12和控制+ S

This registers two combinations: F12 and Control+S.

然后,注册事件处理程序,以便您可以捕获CloseApp和保存按键。

Then, register an event handler so you can capture the CloseApp and Save key presses.

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

在我的示例代码中,我用MessageBox.Show(),以证明该事件被触发:

In my example code, I used MessageBox.Show() to prove that the event was fired:

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

您可以注册或注销随意的事件处理程序,当窗体打开和关闭例如,或有应用范围的处理程序。这是给你的。

You can register or unregister event handlers at will, when forms are opened and closed for example, or have application-wide handlers. It's up to you.

因为密钥库是单身,你可以在应用程序中的任意位置添加关键定义。你可以这样做在main()方法,调用Application.Run()之前,或者你可以添加一些代码来从配置文件加载定义。

Because the KeyStore is a singleton, you can add the key definitions from anywhere in your application. You can do it in the Main() method, before calling Application.Run(), or you can add some code to load definitions from a configuration file.

这篇关于C# - System.Windows.Forms.Keys - 如何保持应用程序的热键在一个地方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆