Подтвердить что ты не робот

С# Как перевести виртуальный код ключа на char?

Я пытаюсь сопоставить виртуальный код ключа с char.

Мой код использует ProcessCmdKey для прослушивания WM_KEYDOWN, который дает мне доступ к нажатой клавише. Например, когда я нажимаю одиночную кавычку, я получаю ключ из 222, который я хочу, чтобы он отображался в keychar 39, который представляет... вы догадались, что это... одинарная кавычка.

Мой контекст dev: -.net Framework 2.0 - UserControl размещен во многих местах

Знаете ли вы ответ на вопрос?

4b9b3361

Ответ 1

Разве это не класс System.Windows.Form.KeysConverter для?

KeysConverter kc = new KeysConverter();
string keyChar = kc.ConvertToString(keyData);

Ответ 2

Да, я использовал метод MapVirtualKey. Но я ожидал более подробной информации о том, как его использовать: какая директива DllImport, какая enum специфична для сопоставления с символами и т.д.

Мне не нравятся эти ответы, где вы Google, как 5 секунд, а затем просто предлагаете решение: реальная задача состоит в том, чтобы собрать все части и не тратить время на тонны страниц MSDN без образца или другие форумы кодирования, чтобы получить ваш ответ. Не обижайтесь на цоколе, но ваш ответ (даже хороший) был безразличным, так как у меня был этот ответ даже до публикации моего вопроса на форуме!

Итак, вы идете, я собираюсь опубликовать то, что я искал - готовое решение С#:

1- Поместите эту директиву в свой класс:

[DllImport("user32.dll")]
static extern int MapVirtualKey(uint uCode, uint uMapType);

2- Извлеките char следующим образом:

  protected override bool ProcessCmdKey(ref Message msg, Keys keyData)      
  {
     const int WM_KEYDOWN = 0x100;

     if (msg.Msg == WM_KEYDOWN)
     {            
        // 2 is used to translate into an unshifted character value 
        int nonVirtualKey = MapVirtualKey((uint)keyData, 2);

        char mappedChar = Convert.ToChar(nonVirtualKey);
     }

     return base.ProcessCmdKey(ref msg, keyData);
  }

Спасибо за заботу... и наслаждайтесь!

Ответ 3

После прочтения и тестирования некоторых из представленных ответов я подумал, что предлагаю альтернативу.

Как упоминалось MM, System.Windows.KeysConverter не предоставляет символьное представление ключа, а скорее имя перечисления, например. "Enter" вместо '\n'.

Метод MapVirtualKey, предложенный Horas, в ответ на его собственный вопрос, является хорошей отправной точкой, но по-прежнему не поддерживает ни маскировки, ни введенные символы с клавишей сдвига, например '!', '$' и ' > '.

Альтернативой методу MapVirtualKey, который я использую, является метод расширения для класса Keys:

public static char ToChar(this Keys key)
{
    char c = '\0';
    if((key >= Keys.A) && (key <= Keys.Z))
    {
        c = (char)((int)'a' + (int)(key - Keys.A));
    }

    else if((key >= Keys.D0) && (key <= Keys.D9))
    {
        c = (char)((int)'0' + (int)(key - Keys.D0));
    }

    return c;
}

Метод, показанный выше, обеспечит поддержку буквенно-цифровых символов. Поддержка дополнительных символов может быть реализована с помощью оператора switch или таблицы поиска.

Ответ 4

Я искал что-то подобное, но мне нужен был символ, сопоставленный с текущей раскладкой клавиатуры. Поскольку ни один из вышеперечисленных ответов не выполнил мои требования, вот что я придумал.


        public string KeyCodeToUnicode(Keys key)
        {
            byte[] keyboardState = new byte[255];
            bool keyboardStateStatus = GetKeyboardState(keyboardState);

            if (!keyboardStateStatus)
            {
                return "";
            }

            uint virtualKeyCode = (uint)key;
            uint scanCode = MapVirtualKey(virtualKeyCode, 0);
            IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);

            StringBuilder result = new StringBuilder();
            ToUnicodeEx(virtualKeyCode, scanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier);

            return result.ToString();
        }

        [DllImport("user32.dll")]
        static extern bool GetKeyboardState(byte[] lpKeyState);

        [DllImport("user32.dll")]
        static extern uint MapVirtualKey(uint uCode, uint uMapType);

        [DllImport("user32.dll")]
        static extern IntPtr GetKeyboardLayout(uint idThread);

        [DllImport("user32.dll")]
        static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);

Ответ 5

KeysConverter получает имя ключа, а не клавиши "текст", ex: "Num2" вместо "2" MapVirtualKey будет работать на английском языке, но для неанглийских состояний документации с использованием MapVirtualKeyEx, но для этого требуется идентификатор локали этот идентификатор загружается LoadKeyBoardLayout, для которого требуется постоянный идентификатор культуры но после нахождения правильных значений id это не сработало, поскольку я попробовал это, так что, наконец, я сбросил все это.

Ответ 6

Я только что написал сообщение об улучшении Иван Петров, чтобы отобразить строковое представление нажатых комбинаций клавиш в WPF, см. мой код ниже:

public static string GetKeyString(Key key, ModifierKeys modifiers)
{
    string result = "";
    if (key != Key.None)
    {
        // Setup modifiers
        if (modifiers.HasFlag(ModifierKeys.Control))
            result += "Ctrl + ";
        if (modifiers.HasFlag(ModifierKeys.Alt))
            result += "Alt + ";
        if (modifiers.HasFlag(ModifierKeys.Shift))
            result += "Shift + ";
        // Get string representation
        string keyStr = key.ToString();
        int keyInt = (int)key;
        // Numeric keys are returned without the 'D'
        if (key >= Key.D0 && key <= Key.D9)
            keyStr = char.ToString((char)(key - Key.D0 + '0'));
        // Char keys are returned directly
        else if (key >= Key.A && key <= Key.Z)
            keyStr = char.ToString((char)(key - Key.A + 'A'));
        // If the key is a keypad operation (Add, Multiply, ...) or an 'Oem' key, P/Invoke
        else if ((keyInt >= 84 && keyInt <= 89) || keyInt >= 140)
            keyStr = KeyCodeToUnicode(key);
        result += keyStr;
    }
    return result;
}

private static string KeyCodeToUnicode(Key key)
{
    byte[] keyboardState = new byte[255];
    bool keyboardStateStatus = GetKeyboardState(keyboardState);

    if (!keyboardStateStatus)
    {
        return "";
    }

    uint virtualKeyCode = (uint)KeyInterop.VirtualKeyFromKey(key);
    uint scanCode = MapVirtualKey(virtualKeyCode, 0);
    IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);

    StringBuilder result = new StringBuilder();
    ToUnicodeEx(virtualKeyCode, scanCode, new byte[255], result, (int)5, (uint)0, inputLocaleIdentifier);

    return result.ToString();
}

[DllImport("user32.dll")]
static extern bool GetKeyboardState(byte[] lpKeyState);

[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);

[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);

[DllImport("user32.dll")]
static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);