C # Как перевести виртуальный код клавиши на символ? - PullRequest
23 голосов
/ 25 ноября 2008

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

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

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

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

Ответы [ 6 ]

41 голосов
/ 26 ноября 2008

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

KeysConverter kc = new KeysConverter();
string keyChar = kc.ConvertToString(keyData);
21 голосов
/ 26 ноября 2008

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

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

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

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

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

2- Получите свой символ следующим образом:

  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);
  }

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

8 голосов
/ 05 августа 2016

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


        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);

7 голосов
/ 27 февраля 2015

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

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

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

Альтернативой методу 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 или таблицы поиска.

2 голосов
/ 12 июля 2017

Я только что написал улучшение Ответ Ивана Петрова для отображения строкового представления комбинаций нажатых клавиш в 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);
1 голос
/ 24 октября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...