如何以编程方式找到在 C# Winform 中分配的所有快捷键的列表?

How can I programmatically find a list of all Shortcut keys assigned in C# Winform?

如何以编程方式获取我的应用程序中使用的快捷键列表?我有一个 winform,其中有许多菜单和菜单项(包括动态生成的菜单项)已分配快捷键。

真的很难记住所有的快捷键并认为向用户显示一个列表会很好。

我发现你的要求有几个问题:

  • 对于File-New你必须输入<alt-F> <alt-N>;对于 Edit-Names,您需要输入 <Alt-E> <Alt-N>
  • 因此 <Alt-N> 在您的快捷方式集合中是不够的,您需要完整的组合:<alt-F> <alt-N> 用于菜单 File-New,<Alt-E> <Alt-N> 用于 Edit-Names
  • 如果设计者忘记在文件部分添加<alt-F>和在编辑部分添加<alt-E>怎么办?那么你将有两个 <alt-N> 快捷方式!
  • 快捷方式也适用于其他控件,例如按钮
  • <Ctrl-C><Ctrl-V> 等标准快捷方式怎么样?

假设您的快捷方式是唯一的,您只需要菜单项的快捷方式并且您希望它们来自根菜单。唉,class System.Windows.Forms.Shortcut 没有 <Alt-..> 快捷方式的值,所以我们只记住大写字符的快捷方式:所以“FN”表示 <alt-F> <alt-N>"

您需要用所有子菜单项迭代每个菜单项,并检查 Text 属性 是否包含符号。

我将把它作为 MenuStripToolStripItem 的扩展方法。菜单条的主菜单为 属性 Items 中的 ToolStripItems; ToolStripItem 在 属性 DropDownItems.

中有子菜单

如果您不熟悉扩展方法,请参阅 extension methods demystified

先class放结果:

using System.Windows.Forms;
class ShortCut
{
    public string ShortcutSequence {get; set;} = String.Empty;
    ToolStripItem ToolStripItem {get; set;}
}

如果没有快捷方式,则获取 ToolStripMenuItem 或默认值的快捷方式:

public static char GetShortcutCharOrDefault(this ToolStripMenuItem menuItem)
{
    // Return the character after the ampersand in property Text,
    // or null if there is no such thing
    return menuItem?.Text?.SkipWhile(c => c != '&') // skip until &
        .Skip(1)                                    // skip the &
        .Select(c => char.ToUpper(c))               // make the char uppercase
        .FirstOrDefault()                           // char after the ampersand
        ?? default(char);                           // or default char if no text
}

从一系列 ToolStripMenuItems 到一系列快捷方式。

public static IEnumerable<Shortcut> ToShortcuts(
    this IEnumerable<ToolStripMenuItem> menuItems,
    string parentShortcutSequence)
{
    // TODO: handle invalid input

    foreach (var menuItem in menuItems)
    {
        char shortcutCar = menuItem.GetShortcutChar();
        if (shortCutChar != default(char))
        {
           // This menuItem has a shortcut.
           var shortcut = new ShortCut
           {
               ShortcutSequence = parentShortcutSequence + shortcutChar,
               ToolstripItem = menuItem,
           }

           // return this shortcut
           yield return shortcut;

           // and check for the shortcuts of the sub menu items
           // recursively!
           var subShortcuts = menuItem.Items.ToShortcuts(shortcut.ShortcutSequence);
           foreach (var subShortcut in subShortcuts)
           {
               yield return subShortCut);
           }
        }
    }
}

用法:

MenuStrip mainMenuStrip = ...
IEnumerable<ToolStripItem> menus = mainMenuStrip.Items.Cast<ToolStripItem>();
IEnumerable<Shortcut> shortcuts = menus.ToShortCusts(String.Empty);