2008-11-25 2 views
20

Я пытаюсь сопоставить виртуальный код ключа с символом.C# Как перевести виртуальный keycode на char?

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

Мой контекст DEV является: - .NET Framework 2.0 - UserControl размещены во многих местах

Вы знаете ответ на этот вопрос?

+1

[MapVirtualKey] (http://msdn.microsoft .com/en-us/library/ms646306 (VS.85) .aspx)()? – plinth 2008-11-25 20:50:51

ответ

20

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

Мне не нравятся эти ответы, где вы google, как 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); 
    } 

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

+0

Спасибо за следующее. Если вы уже посмотрели MapVirtualKey(), возможно, вы должны были включить это в свой вопрос (т. Е. «Я посмотрел на MapVirtualKey(), но я не знаю, как назвать его с C#). Для ваших будущих потребностей, вы можете найти http://www.pinvoke.net полезным. – plinth 2008-11-26 18:57:31

+1

И в случае MapVirtualKey, вот запись от pinvoke.net: http://www.pinvoke.net/default.aspx/user32/MapVirtualKey.html – plinth 2008-11-26 18:58:24

+1

Незначительная коррекция: MapVirtualKey фактически возвращает uint, а не int. Но спасибо за этот бит кода, это было именно то, что мне нужно для моего собственного проекта. – 2010-04-12 03:47:49

39

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

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

Забыл укажите контекст моего вопроса: - .net Framework 2.0 - UserControl Так что ответ на ваш ответ - нет. – Horas 2008-11-26 14:52:53

1

KeysConverter получает имя ключа не ключи «текст» экс: «NUM2» вместо «2» MapVirtualKey будет работать на английском, но и для неанглийских символов документации состояний с помощью MapVirtualKeyEx но требует локали идентификатор , что идентификатор загружен LoadKeyboardLayout, который требует культуру идентификатора постоянной , но затем после нахождения правильных значений идентификаторов он не работает, как я пробовал так, наконец, я бросил все этот

7

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

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

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

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

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, либо с помощью таблицы поиска.

6

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


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

1

Я только что написал улучшение Ivan Petrov answer для отображения строкового представления прессованных комбинаций клавиш в 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); 
Смежные вопросы