[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);
None.
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.
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.
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);
Do you know one? Please contribute it!