Как я могу преобразовать 'System.Windows.Input.Key' в 'System.Windows.Forms.Keys'?

Я разрабатываю приложение в WPF, но некоторые компоненты написаны с использованием WinForms. Я не хочу, чтобы эти компоненты извлекали жесты клавиш из части WPF и конвертировали их в перечисление ключей (используется в WinForms).

Для этого есть встроенный конвертер? (вероятно, нет). Вы знаете способ "проще, чем большой коммутатор"?

5 ответов

Решение
Keys formsKey = ...;
Key wpfKey = ...;
wpfKey = KeyInterop.KeyFromVirtualKey((int)formsKey);
formsKey = (Keys)KeyInterop.VirtualKeyFromKey(wpfKey);

Класс KeyInterop - это "ключ" плюс тот факт, что Windows Forms Keys Перечисление имеет те же целочисленные значения, что и коды виртуальных ключей Win 32.

На тот случай, если люди все еще сталкиваются с проблемой модификаторов 7 лет спустя, вот мое решение, которое сработало до сих пор:

public static class KeyEventExts
{
    public static System.Windows.Forms.KeyEventArgs ToWinforms(this System.Windows.Input.KeyEventArgs keyEventArgs)
    {
        // So far this ternary remained pointless, might be useful in some very specific cases though
        var wpfKey = keyEventArgs.Key == System.Windows.Input.Key.System ? keyEventArgs.SystemKey : keyEventArgs.Key;
        var winformModifiers = keyEventArgs.KeyboardDevice.Modifiers.ToWinforms();
        var winformKeys = (System.Windows.Forms.Keys)System.Windows.Input.KeyInterop.VirtualKeyFromKey(wpfKey);
        return new System.Windows.Forms.KeyEventArgs(winformKeys | winformModifiers);
    }

    public static System.Windows.Forms.Keys ToWinforms(this System.Windows.Input.ModifierKeys modifier)
    {
        var retVal = System.Windows.Forms.Keys.None;
        if(modifier.HasFlag(System.Windows.Input.ModifierKeys.Alt))
        {
            retVal |= System.Windows.Forms.Keys.Alt;
        }
        if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Control))
        {
            retVal |= System.Windows.Forms.Keys.Control;
        }
        if (modifier.HasFlag(System.Windows.Input.ModifierKeys.None))
        {
            // Pointless I know
            retVal |= System.Windows.Forms.Keys.None;
        }
        if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Shift))
        {
            retVal |= System.Windows.Forms.Keys.Shift;
        }
        if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Windows))
        {
            // Not supported lel
        }
        return retVal;
    }
}

Если вы хотите преобразовать модификаторы, используйте SystemKey, если вы смотрите на KeyEventArgs:

System.Windows.Input.KeyEventArgs args;
System.Windows.Input.Key wpfKey= args.Key == Key.System ? args.SystemKey : args.Key;
formsKey = (System.Windows.Forms.Keys)KeyInterop.VirtualKeyFromKey(wpfKey);

Опираясь на отличный ответ Сэма Харвелла, чтобы принять во внимание модификаторы, если вы хотите перейти от wpf к winforms и включить ключи-модификаторы, вы можете сделать это:

      Keys formsKey = ...;
System.Windows.Input.Key wpfKey = ...;

wpfKey = KeyInterop.KeyFromVirtualKey((int)formsKey);
formsKey = (Keys)KeyInterop.VirtualKeyFromKey(wpfKey);

if (System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftShift) ||
    System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.RightShift))
    formsKey |= Keys.Shift;
if (System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftAlt) ||
    System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.RightAlt))
    formsKey |= Keys.Alt;
if (System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftCtrl) ||
    System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.RightCtrl))
    formsKey |= Keys.Control;

Или, если вы хотите перейти с winforms на wpf:

      var isShift = (keys & Keys.LShiftKey) == Keys.LShiftKey || (keys & Keys.RShiftKey) == Keys.RShiftKey;
var isAlt = (keys & Keys.Alt) == Keys.Alt;
var isCtrl = (keys & Keys.LControlKey) == Keys.LControlKey || (keys & Keys.RControlKey) == Keys.RControlKey;

Чтобы преобразовать WPFKeyперечисление к соответствующим WinFormsKeysперечисление использовать статический член TryParse из Enum учебный класс:

Enum.TryParse(wpfKeyEnum.ToString(), out System.Windows.Forms.Keys winFormsKeyEnum)

Модификаторы WPF (перечисление ModifierKeys) можно преобразовать таким же образом, за исключением ключа Windows. В отличие отWindows.Input.ModifierKeys перечисление WPF Windows.Forms.Keys перечисление различает левую и правую клавиши Windows и определяет соответствующие LWin ан RWin поля.

Этот метод преобразования работает в обоих направлениях.

пример

Пример преобразует Key а также ModifierKeys перечисления события включения ключа WPF в соответствующие WinForms Keys перечисление.

От Windows.Input.Key Чтобы System.Windows.Forms.Keys

private void OnPreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{ 
  // Convert key
  if (Enum.TryParse(e.Key.ToString(), out System.Windows.Forms.Keys winFormsKey))
  {
    MessageBox.Show(winFormsKey + "=" + (int) winFormsKey); // A=65
  }
}

От Windows.Input.ModifierKeys Чтобы System.Windows.Forms.Keys

private void OnPreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{ 
  ModifierKeys modifiers = e.KeyboardDevice.Modifiers;

  IEnumerable<ModifierKeys> pressedModifierKeys  = Enum.GetValues(modifiers.GetType())
    .Cast<ModifierKeys>()
    .Where(modifiers.HasFlag);

  // The ModifierKeys enumeration has a FlagsAttribute attribute
  foreach (ModifierKeys modifier in pressedModifierKeys)
  {
    if (Enum.TryParse(modifier.ToString(), out System.Windows.Forms.Keys winFormsModifierKey))
    {
      MessageBox.Show(winFormsModifierKey + "=" + (int) winFormsModifierKey); // Alt=262144
    }
  }
}
Другие вопросы по тегам