Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert keycode to char/string

I'm trying to convert System.Windows.Forms.Keys to string/char using :

KeysConverter converter = new KeysConverter();
string text = converter.ConvertToString(keyCode);
Console.WriteLine(text);

But it returned "OemPeriod" for "." and "Oemcomma" for ",". Is there any way to get the exact character?

like image 974
programmer1490 Avatar asked Apr 19 '14 12:04

programmer1490


2 Answers

What you are trying to achieve is no trivial task by any means. There is the keyboard mapping (keyboard layout) that windows (for example) uses to translate keyboard keys to actual characters. Here is how I was able to achieve this:


    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);
like image 159
Ivan Petrov Avatar answered Oct 04 '22 15:10

Ivan Petrov


This is probably what you really want (bit late, but hope this will help someone else), converting the keycode directly to the character the key prints.

First add this directive into your class:

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int ToUnicode(
    uint virtualKeyCode, 
    uint scanCode,
    byte[] keyboardState,
    StringBuilder receivingBuffer, 
    int bufferSize, 
    uint flags
);

Then use this if you just want to ignore the shift modifier

StringBuilder charPressed = new StringBuilder(256);
ToUnicode((uint)keyCode, 0, new byte[256], charPressed, charPressed.Capacity, 0);

Now just call charPressed.ToString() to get your key.

If you want the shift modifier, you can use something like this to make it easier

static string GetCharsFromKeys(Keys keys, bool shift)    
{
    var buf = new StringBuilder(256);
    var keyboardState = new byte[256];
    if (shift)
    {
        keyboardState[(int)Keys.ShiftKey] = 0xff;
    }
        ToUnicode((uint)keys, 0, keyboardState, buf, 256, 0);
        return buf.ToString();
}
like image 27
8176135 Avatar answered Oct 04 '22 17:10

8176135