Christoph
Christoph

Reputation: 28095

ReadConsoleOutputCharacter does not work with German umlauts

I'm using this code to directly read from the Console.

    public char? ReadCharacterAt(int x, int y)
    {
        IntPtr consoleHandle = GetStdHandle(-11);
        if (consoleHandle == IntPtr.Zero)
        {
            return null;
        }
        var position = new Coord
        {
            X = (short)x,
            Y = (short)y
        };
        var result = new StringBuilder(1);
        uint read = 0;
        if (ReadConsoleOutputCharacter(consoleHandle, result, 1, position, out read))
        {
            return result[0];
        }
        else
        {
            return null;
        }
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool ReadConsoleOutputCharacter(IntPtr hConsoleOutput, [Out] StringBuilder lpCharacter, uint length, Coord bufferCoord, out uint lpNumberOfCharactersRead);

    [StructLayout(LayoutKind.Sequential)]
    public struct Coord
    {
        public short X;
        public short Y;
    }

However, for German umlauts (äüö) this does not return the correct character. I wonder how can I fix that?

UPDATE

As Hans and Raymond pointed out, the answer lays in the DLL import. All I had to do was changing it to:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]

Upvotes: 3

Views: 546

Answers (1)

Hans Passant
Hans Passant

Reputation: 942187

From the SDK docs:

This function uses either Unicode characters or 8-bit characters from the console's current code page. The console's code page defaults initially to the system's OEM code page. To change the console's code page, use the SetConsoleCP or SetConsoleOutputCP functions, or use the chcp or mode con cp select= commands.

You'll get 8-bit characters since you didn't specify the CharSet in the [DllImport] attribute. You could technically make it work by reading into byte[] and convert with Console.OutputEncoding.GetString(). But don't, use CharSet.Unicode to have Windows make the conversion for you.

Upvotes: 3

Related Questions