#c# #winforms #keyboard-shortcuts
#c# #winforms #сочетания клавиш
Вопрос:
Как я могу программно получить список сочетаний клавиш, которые используются в моем приложении? У меня есть winform со многими меню и пунктами меню (включая динамически генерируемые пункты меню), которым назначены сочетания клавиш.
На самом деле мне было трудно отслеживать все сочетания клавиш, и я подумал, что было бы неплохо отобразить список для пользователя.
Комментарии:
1. Даже если бы вы могли это сделать (и я не могу придумать надежный способ добиться этого) Вероятно, для написания этого потребуется больше времени, чем для простого просмотра каждой формы и аудита
2. Вы можете использовать
SendInput
метод и попробовать в цикле.3. Вы пробовали перечислять пункты меню и извлекать их свойства коротких клавиш и определять значения (неудобно, потому что это флаги, но выполнимо, потому что все это часть перечисления ключей). Обратите внимание, вы, конечно, не сказали, что используете ToolStripMenuItem, но я бы также отметил, что если вы используете и установили свойство ShortcutKeyDisplayString для каждого, вы можете использовать это, если это просто для отображения списка пользователю
4. @CaiusJard в частности, я думал о меню toolstrip, не был уверен, существуют ли сочетания клавиш в другом месте
Ответ №1:
Я вижу несколько проблем в вашем требовании:
- Для
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
, содержит ли свойство амперсанд.
Я сделаю это как методы расширения для MenuStrip
и ToolStripItem
. Строка меню имеет главное меню в качестве элементов ToolStripItems в свойстве Items
; элемент ToolStripItem имеет подменю в свойстве DropDownItems
.
Если вы не знакомы с методами расширения, см. раздел Методы расширения демистифицированные
Сначала класс для ввода результатов:
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 != 'amp;') // skip until amp;
.Skip(1) // skip the amp;
.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);