Как прочитать пользовательские сочетания клавиш от пользователя в WPF? - PullRequest
11 голосов
/ 26 января 2010

В моем приложении я хочу позволить пользователям настраивать сочетания клавиш так же, как это делается в настройках клавиатуры 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 ярлыки от пользователя? Есть ли лучший, более надежный способ записи ярлыков от пользователя?

Ответы [ 2 ]

25 голосов
/ 25 ноября 2010

Хитрость заключается в использовании свойства 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 эффективно захватывается текстовым полем, прежде чем оно достигнет меню, что, по-видимому, вам нужно.

0 голосов
/ 25 ноября 2010

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

<Window.InputBindings>
  <KeyBinding Command="YourCommnad"
              Gesture="CTRL+C" />
</Window.InputBindings>
...