【问题标题】:Best approach to add keyboard "Shortcuts/Hotkeys" to control my application添加键盘“快捷方式/热键”来控制我的应用程序的最佳方法
【发布时间】:2019-03-05 09:42:24
【问题描述】:

我正在开发一个桌面应用程序,我希望允许用户通过键盘控制其功能,还允许他根据自己的观点将默认控制器更改为自定义控制器。

我的问题是,解决这个问题并为此问题提供适当解决方案的最佳方法是什么?

【问题讨论】:

  • 您想处理任何其他自定义控制器吗?因为我猜你不能只为所有东西做一个通用代码
  • 我想要的例如:如果我为我的应用程序中的某个功能分配的默认控制器是按钮“A”,而用户想要将其更改为按钮“B”就像发生了什么例如在游戏中。
  • 嗬,所以它更像是更改快捷键而不是更改控制器,并没有这样理解。我可能对如何做有一个想法(使用字典),我会尝试一下,如果效果很好,请发布答案。
  • 是的,正在更改快捷键,我正在等待您的想法,谢谢,所以再次为您澄清一下,问题可能如下: 1- 在应用程序中分配要控制的某些功能从键盘“像电脑游戏”。 2- 让用户能够根据需要更改快捷方式。

标签: c# .net desktop-application


【解决方案1】:

您可以使用字典将每个键绑定到一个动作

我的方法是使用 Dictionary,其中 Key 是实际的 Keybord Keys,而 value 是代表您的一个功能的 int?可以绑定到自定义输入。

Dictionnary<Keys, int?> shortcutDictionnary = new Dictionary<Keys, int?>();
// Add a new Keys
shortcutDictionary.Add(Keys.A, 1);
// Change a Keys value (change shortcut bounded to it)
shortcutDictionary[Keys.A] = 4;

要将这些 int? 与这些功能相匹配,您只需使用 switch

int? num = null;
if (this.shortcutDictionary.TryGetValue(keyPressed, out num))
{
    switch (num)
    {
        case 1:
            attack();
            break;
        case 2:
            defend();
            break;
        case 3:
            hide();
            break;
        case 4:
            dance();
            break;
        default:
            Console.WriteLine("Key not bounded");
            break;
    }
}

我还在下面的代码中使用 enum,而不是直接使用 Keys 用于我的 Dictionary
这样,我可以选择哪些 Keys 可以有界,哪些不能。

我的代码由 Winform 应用程序编写,例如,我只使用了 4 个 Keys(A、B、C、D)可以绑定,一个可以轻松更改绑定(L ),但我相信您可以弄清楚如何使用任何其他方法轻松更改绑定。此外,当我使用 WindowsForm 时,我必须设置 KeyPreview = true。
这是我的代码:

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Project
{
    public enum UsableKeys
    {
        A = Keys.A,
        B = Keys.B,
        C = Keys.C,
        D = Keys.D,
    }

    public partial class Form1 : Form
    {
        Dictionary<UsableKeys, int?> shortcutDictionary = new Dictionary<UsableKeys, int?>();

        public Form1()
        {
            InitializeComponent();

            foreach (UsableKeys key in Enum.GetValues(typeof(UsableKeys)))
            {
                // You may add default shortcut here
                this.shortcutDictionary.Add(key, null);
            }
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            UsableKeys keyPressed = (UsableKeys)e.KeyCode;
            if (this.shortcutDictionary.ContainsKey(keyPressed))
            {
                executeAction(keyPressed);

                e.Handled = true;
                e.SuppressKeyPress = true;
            }
            else if (e.KeyCode == Keys.L)
            {
                switch (this.shortcutDictionary[UsableKeys.A])
                {
                    case 1:
                        this.shortcutDictionary[UsableKeys.A] = 4;
                        this.shortcutDictionary[UsableKeys.B] = 3;
                        this.shortcutDictionary[UsableKeys.C] = 2;
                        this.shortcutDictionary[UsableKeys.D] = 1;
                        break;
                    case null:
                        this.shortcutDictionary[UsableKeys.A] = 1;
                        this.shortcutDictionary[UsableKeys.B] = 2;
                        this.shortcutDictionary[UsableKeys.C] = 3;
                        this.shortcutDictionary[UsableKeys.D] = 4;
                        break;
                    case 4:
                        this.shortcutDictionary[UsableKeys.A] = null;
                        this.shortcutDictionary[UsableKeys.B] = null;
                        this.shortcutDictionary[UsableKeys.C] = null;
                        this.shortcutDictionary[UsableKeys.D] = null;
                        break;
                }

                e.Handled = true;
                e.SuppressKeyPress = true;
            }
        }

        private void executeAction(UsableKeys keyPressed)
        {
            int? num = null;
            if (this.shortcutDictionary.TryGetValue(keyPressed, out num))
            {
                switch (num)
                {
                    case 1:
                        attack();
                        break;
                    case 2:
                        defend();
                        break;
                    case 3:
                        hide();
                        break;
                    case 4:
                        dance();
                        break;
                    default:
                        Console.WriteLine("Key not bounded");
                        break;
                }
            }
        }

        private void attack()
        {
            Console.WriteLine("Player swing his word");
        }

        private void defend()
        {
            Console.WriteLine("Player raise his shield");
        }

        private void hide()
        {
            Console.WriteLine("Player sneak around");
        }

        private void dance()
        {
            Console.WriteLine("Player start to dance");
        }
    }
}

使用此代码,输出将类似于:

// Press A, B, C or D
"Key not bounded"
// Press L
// Press A
"Player swing his word"
// Press B
"Player raise his shield"
// Press C
"Player sneak around"
// Press D
"Player start to dance"
// Press L
// Press A
"Player start to dance"
// Press B
"Player sneak around"
// Press C
"Player raise his shield"
// Press D
"Player swing his sword"
// Press L
// Press A, B, C or D
"Key not bounded"

在运行时更改键绑定的示例:

// Create a new Dictionary for shortcuts
Dictionary<UsableKeys, int?> shortcutDictionary = new Dictionary<UsableKeys, int?>();
// Add a pair key/value that bind A to attack()
shortcutDictionary.Add(UsableKey.A, 1);
// Add a pair Key/value that bind B to defend()
shortcutDictionary.Add(UsableKey.B, 2);
// Now, if you press A, attack() will be called
shortcutDictionary[UsableKey.A] = 2;
// Now if you press A or B, defend() will be called
shortcutDictionary[UsableKey.B] = null;
// Now B isn't bind to any function, so only A is binded to defend();

使用此方法,您不能将多个函数绑定到一个 Keys,而您可以将多个 Keys 绑定到一个函数(如果要反转,只需交换Dictionary 的键/值并调整代码以匹配此)。
我不知道这是否是执行此操作的最佳方式,但它不是意大利面条式代码,而且效果很好。

【讨论】:

  • 好的,现在还有两个问题可以讨论;第一个是我们如何允许用户在运行时修改控制器以及如何保存用户修改,我建议可以通过 XML 文件保存修改
  • @AhmadShaarawi 要保存它,您可以创建一个包含信息的文件,或者尝试嵌入一个数据库并将其保存在那里(使用这种方法,字典在保存前的选项菜单以外的其他地方不再相关更改,您只需要更新数据库)。要在运行时更改快捷方式(假设您没有使用数据库),您只需更改字典的值。我将在我的回答中为此添加一个更详细的示例。
  • ops,我想我没有说清楚,我的意思是让应用程序用户在他使用应用程序时更改他处理的控制器
  • 感谢您的想法,它帮助我在此基础上构建了我的方法,但做了一些修改
  • @AhmadShaarawi 昨天没有看到您的评论,但是要更改快捷方式,您只需构建一个函数,客户端发送一个键和一个 int 并像我的示例中那样更改它^^ I不知道您希望我确切地向您展示您应该如何做(例如在控制台程序中,这是展示它的最简单方法)。但如果我的回答能帮助您找到解决方案,我很高兴。
猜你喜欢
  • 2011-08-14
  • 1970-01-01
  • 2010-09-28
  • 2010-11-25
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多