ReadConsoleOutputCharacter不能处理德语umlauts。

3
我正在使用这段代码直接从控制台读取内容。
    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;
    }

然而,对于德语umlauts(äüö),这并不能返回正确的字符。我想知道如何解决这个问题?

更新

正如Hans和Raymond指出的那样,答案在DLL导入中。 我所要做的就是将其更改为:

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

2
当你说它没有返回正确的字符时,它返回了什么?我猜想你没有指定 CharSet=CharSet.Unicode,所以你误解了代码页。 - Raymond Chen
1个回答

3

从SDK文档中得知:

此函数使用Unicode字符或控制台当前代码页的8位字符。控制台的代码页最初默认为系统的OEM代码页。要更改控制台的代码页,请使用SetConsoleCP或SetConsoleOutputCP函数,或使用chcp或mode con cp select=命令。

由于您没有在[ DllImport ]属性中指定CharSet,因此您将获得8位字符。您可以通过读取byte[]并使用Console.OutputEncoding.GetString()进行转换来使其正常工作。但是请使用CharSet.Unicode,让Windows为您进行转换。


非常感谢。我更新了我的答案,提供了解决方案。我只需要更改DLLImport以指定字符集。所以结果是所有其他部分(例如从StringBuilder中读取)实际上可以保持不变。您考虑更新您的答案,这样我就可以接受它了吗? - Christoph
啊,抱歉。我看错了。你的意思是,如果我不指定它,我就必须将其读入一个byte[]并手动处理。如果我指定它,代码可以保持不变。你是这个意思吧? - Christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接