ToUnicode (user32)
Last changed: -174.107.131.200

.
Summary

C# Signature:

[DllImport("user32.dll")]
static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte [] lpKeyState,
   [Out, MarshalAs(UnmanagedType.LPWStr,SizeConst=64)] StringBuilder pwszBuff, int cchBuff,
   uint wFlags);

User-Defined Types:

None.

Notes:

Depending on the actual Size of the String which needs to be translated, one must be careful to adjust the SizeConst of the pwszBuff. I had weird memory problems until I nailed the size which seems plausible because the size is passed with the parameter cchBuff anyway.

Alternatively:

[DllImport("USER32.DLL", CharSet=CharSet.Unicode)]
public static extern int ToUnicode(uint virtualKey, uint scanCode, byte[] keyStates, [MarshalAs(UnmanagedType.LPArray)] [Out] char[] chars, int charMaxCount, uint flags);

and pass it char[] instead of StringBuilder.

Tips & Tricks:

The trick is to make sure that "chars" is marshaled as UNICODE string. This can be done either by setting UnmanagedType.LPWStr or by CharSet=CharSet.Unicode.

Sample Code:

    readonly byte[] keyStates = new byte[0x100];
    readonly char[] chars = new char[1];

    char OnKeyEvent(uint wVirtKey, uint wScanCode) {
        if (GetKeyboardState(m_keyStates)) {
        int r = ToUnicode(wVirtKey, wScanCode, keyStates, chars, chars.Length, 0);
        if (r == -1) {
            // ("ToUnicode: dead key");
        } else if (r == 0) {
            // ("ToUnicode: key has no Unicode value");
        } else if (r == 1) {
            return m_chars[0];
        } else {
            // ("ToUnicode: unexpected return value: " + r);
        }
        }
        return '\0';
    }

    [DllImport("USER32.DLL")]
    public static extern bool GetKeyboardState([MarshalAs(UnmanagedType.LPArray)] [Out] byte[] values);

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern int ToUnicode(uint virtualKey, uint scanCode, byte[] keyStates, [MarshalAs(UnmanagedType.LPArray)] [Out] char[] chars, int charMaxCount, uint flags);

Alternative Managed API:

Do you know one? Please contribute it!

Documentation
ToUnicode on MSDN