Как прочитать пользовательское сочетание клавиш в WPF?

В моем приложении я хочу позволить пользователям настраивать сочетания клавиш, как это делается в параметрах клавиатуры Visual Studio. Пользователь может выделить пустое текстовое поле, а затем ввести любой ярлык, который он хочет назначить команде.

Ближе всего к тому, чтобы заставить его работать, я подписался на событие TextBox.PreviewKeyDown, установив его как обработанное, чтобы предотвратить фактический ввод текста в текстовое поле. Затем я игнорирую события KeyDown, связанные с клавишами-модификаторами (есть ли более чистый способ определить, является ли Key ключом-модификатором?).

// Code-behind
private void ShortcutTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    // The text box grabs all input
    e.Handled = true;

    if (e.Key == Key.LeftCtrl || 
        e.Key == Key.RightCtrl || 
        e.Key == Key.LeftAlt ||
        e.Key == Key.RightAlt || 
        e.Key == Key.LeftShift ||
        e.Key == Key.RightShift)
        return;

    string shortcutText = "";
    if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
        shortcutText += "Ctrl+";
    if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
        shortcutText += "Shift+";
    if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
        shortcutText += "Alt+";
    _ShortcutTextBox.Text = shortcutText + e.Key.ToString();

}

Вышеупомянутое работает для любого сочетания клавиш, начиная с Ctrl и Ctrl + Shift, но не работает для любых сочетаний клавиш Alt. Для e.Key всегда устанавливается значение Key.System, когда я нажимаю сочетание клавиш, содержащее Alt.

Как я могу записать Alt-ярлыки от пользователя? Есть ли лучший и более надежный способ записи ярлыков пользователя?


person Anthony Brien    schedule 25.01.2010    source источник
comment
Мне кажется, что клавиша Alt используется WPF для попытки захвата комбинации клавиш Alt, чтобы сосредоточиться на элементе управления, который привязан к метке с помощью мнемонического ярлыка (например, Alt + F для меню _File или Alt + O для _OK кнопка). Может быть, есть способ предотвратить или отменить это?   -  person Anthony Brien    schedule 24.11.2010


Ответы (2)


Уловка заключается в использовании SystemKey свойство, если установлено свойство Key кому: Key.System:

private void ShortcutTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    // The text box grabs all input.
    e.Handled = true;

    // Fetch the actual shortcut key.
    Key key = (e.Key == Key.System ? e.SystemKey : e.Key);

    // Ignore modifier keys.
    if (key == Key.LeftShift || key == Key.RightShift
        || key == Key.LeftCtrl || key == Key.RightCtrl
        || key == Key.LeftAlt || key == Key.RightAlt
        || key == Key.LWin || key == Key.RWin) {
        return;
    }

    // Build the shortcut key name.
    StringBuilder shortcutText = new StringBuilder();
    if ((Keyboard.Modifiers & ModifierKeys.Control) != 0) {
        shortcutText.Append("Ctrl+");
    }
    if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0) {
        shortcutText.Append("Shift+");
    }
    if ((Keyboard.Modifiers & ModifierKeys.Alt) != 0) {
        shortcutText.Append("Alt+");
    }
    shortcutText.Append(key.ToString());

    // Update the text box.
    _ShortcutTextBox.Text = shortcutText.ToString();
}

Я добавил левую и правую Windows клавиши в список модификаторов, потому что они иногда появлялись в имени сочетания клавиш, когда сложная (Ctrl+Shift+Alt) комбинация клавиш была набрана из сеанса терминального сервера. Однако они никогда не присутствуют в Keyboard.Modifiers, поскольку они зарезервированы для глобальных ярлыков, поэтому я не обрабатываю их там.

Я также использовал StringBuilder, чтобы не создавать слишком много string экземпляры.

Это решение работает с любой комбинацией клавиш, кроме Shift+Alt (модификатор Alt в этом случае не отображается). Однако это может быть артефактом моей среды сервера терминалов, поэтому ваш опыт может отличаться.

Наконец, я добавил _File меню в окно, чтобы увидеть, что произойдет, и комбинация клавиш Alt+F эффективно захватывается текстовым полем, прежде чем попадет в меню, что, похоже, именно то, что вы хотите.

person Frédéric Hamidi    schedule 25.11.2010
comment
+1, лучшее решение, чем мое. Не знал о Key key = (e.Key == Key.System? E.SystemKey: e.Key); обманывать :) - person Fredrik Hedblad; 25.11.2010

Привет,
если You used WPF-Command в своем приложении вы можете использовать это:

<Window.InputBindings>
  <KeyBinding Command="YourCommnad"
              Gesture="CTRL+C" />
</Window.InputBindings>
person Rev    schedule 25.11.2010
comment
Это не отвечает на вопрос. Вопрос в том, как читать комбинацию клавиш в текстовом поле, а не в том, как определять горячие клавиши в XAML. - person Alexandru Dicu; 07.02.2013
comment
Хотя это не отвечает на вопрос об исходном плакате, на самом деле это тот ответ, который я искал, когда наткнулся на эту ветку через поиск в Google. Просто хочу, чтобы другие люди знали, что в 2016 году это отличное решение для привязки всего окна. - person Kikootwo; 01.11.2016