I'm trying to translate a virtual key code with ToAsciiEx() and write it to a debug file. For some reason, the output file contains a load of random trash bytes interspersed with the key codes I want to log.
I'm importing ToAsciiEx() like this:
[DllImport("user32.dll")]
static extern int ToAsciiEx(uint uVirtKey, uint uScanCode, byte[] lpKeyState, [Out] StringBuilder lpChar, uint uFlags, IntPtr hkl);
And the code:
byte[] state = new byte[256];
GetKeyboardState(state);
StringBuilder s = new StringBuilder(new String('\0', 32), 32);
int ret = ToAsciiEx((uint)vkCode, 0, state, s, 0, IntPtr.Zero);
string k = "";
if (ret == 1 && s.Length > 0)
{
k = s.ToString();
}
var logFile = "DebugLog.txt";
var logPath = Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%") "\\" logFile;
using (StreamWriter sw = new StreamWriter(logPath, true))
{
sw.Write(k);
}
Passing the virtual key codes for 'Test', I get this: TSÕà[Õ-ÕØé¿eê¿sê¿tê¿
Could this be an encoding issue? Or is ToAsciiEx() not writing a null-terminator perhaps?
Thanks!
CodePudding user response:
The return value from ToAsciiEx
tells you how many characters were copied to the output, but you never use that information to trim the StringBuilder
.
The Windows API has no idea what a .NET StringBuilder
class is, and doesn't change its length. It's writing data into a memory space that was prepared for it by the magic of p/invoke.... and then p/invoke copies the contents into the StringBuilder
. But s
still has the length it was created with.
Try k = s.ToString(0, ret);