C# 使用WriteConsoleOutput使用c编写Unicode#

C# 使用WriteConsoleOutput使用c编写Unicode#,c#,windows,unicode,console,C#,Windows,Unicode,Console,我试图使用kernel32.dll中的WriteConsoleOutput函数,但是我无法正确显示unicode字符,它们总是显示为错误的字符 我已尝试使用: Console.OutputEncoding = System.Text.Encoding.UTF8; 将此更改为编码.Unicode也不起作用 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetConsoleOutputCP(u

我试图使用kernel32.dll中的
WriteConsoleOutput
函数,但是我无法正确显示unicode字符,它们总是显示为错误的字符

我已尝试使用:

Console.OutputEncoding = System.Text.Encoding.UTF8;
将此更改为
编码.Unicode也不起作用

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleOutputCP(uint wCodePageID);

public void SetCP(){
   SetConsoleOutputCP(65001);
}
我尝试过使用以上两种方法,每种方法都是单独使用的,而没有一种方法使用几乎所有的值组合

我也在所有字体之间切换(包括真正的字体),但是没有一种字体能够正确显示字符

下面是我用来使用WriteConsoleOutput的代码

[DllImport("kernel32.dll", SetLastError = true, EntryPoint = "WriteConsoleOutputW", CharSet = CharSet.Unicode)]
static extern bool WriteConsoleOutputW(SafeFileHandle hConsoleOutput, CharInfo[] lpBuffer, Coord dwBufferSize, Coord dwBufferCoord, ref SmallRect lpWriteRegion);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(string fileName, [MarshalAs(UnmanagedType.U4)] uint fileAccess, [MarshalAs(UnmanagedType.U4)] uint fileShare, IntPtr securityAttributes, [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] int flags, IntPtr template);

private static readonly SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

public static void RegionWrite(string s, int x, int y, int width, int height)
{           
    if (!h.IsInvalid)
    {
        int length = width * height;

        // Pad any extra space we have
        string fill = s + new string(' ', length - s.Length);

        // Grab the background and foreground as integers
        int bg = (int) Console.BackgroundColor;
        int fg = (int) Console.ForegroundColor;

        // Make background and foreground into attribute value
        short attr = (short)(fg | (bg << 4));

        CharInfo[] buf = fill.Select(c => 
        {
            CharInfo info = new CharInfo();

            // Give it our character to write
            info.Char.UnicodeChar = c;

            // Use our attributes
            info.Attributes = attr;

            // Return info for this character
            return info;

        }).ToArray();

        // Make everything short so we don't have to cast all the time
        short sx = (short) x;
        short sy = (short) y;
        short swidth = (short) width;
        short sheight = (short) height;

        // Make a buffer size out our dimensions
        Coord bufferSize = new Coord(swidth, sheight);

        // Not really sure what this is but its probably important
        Coord pos = new Coord(0, 0);

        // Where do we place this?
        SmallRect rect = new SmallRect() { Left = sx, Top = sy, Right = (short) (sx + swidth), Bottom = (short) (sy + sheight) };

        bool b = WriteConsoleOutputW(h, buf, bufferSize, pos, ref rect);
    }
    else
    {
        throw new Exception("Console handle is invalid.");
    }

}
以下是我的结构:

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

    public Coord(short X, short Y)
    {
        this.X = X;
        this.Y = Y;
    }
}

[StructLayout(LayoutKind.Explicit)]
public struct CharUnion
{
    [FieldOffset(0)] public char UnicodeChar;
    [FieldOffset(0)] public byte AsciiChar;
}

[StructLayout(LayoutKind.Explicit)]
public struct CharInfo
{
    [FieldOffset(0)] public CharUnion Char;
    [FieldOffset(2)] public short Attributes;
}

[StructLayout(LayoutKind.Sequential)]
public struct SmallRect
{
    public short Left;
    public short Top;
    public short Right;
    public short Bottom;
}
我想我把
WriteConsoleOutput
的一个变量搞糟了,但经过几个小时的搜索,我真的不知道哪里出了问题。是否需要使用一些内部集合编码功能


nvm修复了它

简单解决方案,更改

[StructLayout(LayoutKind.Explicit)]
public struct CharUnion
{
    [FieldOffset(0)] public char UnicodeChar;
    [FieldOffset(0)] public byte AsciiChar;
}


这是因为它将默认为ANSI,这意味着您的unicode字符将自动转换为ANSI,因此┬ 进入,

简单解决方案,更改

[StructLayout(LayoutKind.Explicit)]
public struct CharUnion
{
    [FieldOffset(0)] public char UnicodeChar;
    [FieldOffset(0)] public byte AsciiChar;
}


这是因为它将默认为ANSI,这意味着您的unicode字符将自动转换为ANSI,因此┬ 进入,

您应该使用
Console.outpunecoding=System.Text.Encoding.Unicode
并忘记代码页。@MatthewWatson我已经尝试过了,这没有什么区别。您还需要在
CharInfo
的声明中指定
Charset.Unicode
,否则它将默认为ANSI:
[StructLayout(LayoutKind.Explicit,Charset=Charset.Unicode)]
(也可能在其他一些结构中,但不确定这些结构).Ugh facepalm,非常感谢。不要在问题内部发布答案。如果您有问题的答案,请将其作为答案发布。您应该使用
Console.OutputEncoding=System.Text.Encoding.Unicode;
并忘记代码页。@MatthewWatson我已经尝试过了这一点,它没有任何区别。您还需要指定
Charset.Unicode
CharInfo
的声明中,否则它将默认为ANSI:
[StructLayout(LayoutKind.Explicit,CharSet=CharSet.Unicode)]
(也可能在其他一些结构中,但不确定这些结构).Ugh facepalm,非常感谢。不要在问题内部发布答案。如果您有问题的答案,请将其作为答案发布。我还必须在其他方法上添加CharSet属性(如
WriteConsoleOutput
)才能使其工作。我还必须在其他方法上添加CharSet属性(如
WriteConsoleOutput
)让它工作
[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
public struct CharUnion
{
    [FieldOffset(0)] public char UnicodeChar;
    [FieldOffset(0)] public byte AsciiChar;
}