首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WriteConsoleOutput()来自不显示文本的Kernel32

WriteConsoleOutput()来自不显示文本的Kernel32
EN

Stack Overflow用户
提问于 2018-04-17 14:32:15
回答 1查看 364关注 0票数 1

我目前正在编写一个小的实用程序库,以帮助提高写入控制台时的性能,而且我还面临一个问题,在这个问题上,它实际上无法输出任何文本。下面是我的代码:

代码语言:javascript
复制
public static class QuickDraw
{
    private static short Width => (short)Console.WindowWidth;
    private static short Height => (short)Console.WindowHeight;

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

    private static Kernel32.Coord Cursor =>
        new Kernel32.Coord((short)Console.CursorLeft, (short)Console.CursorTop);

    private static Kernel32.SmallRect WriteRegion =>
        new Kernel32.SmallRect() { Left = 0, Top = 0, Right = Width, Bottom = Height };
    private static Kernel32.Coord BufferSize =>
        new Kernel32.Coord(Width, Height);
    private static Kernel32.Coord BufferCoord =>
        new Kernel32.Coord(0, 0);

    public static void Write(char[] text, ConsoleColor fg, ConsoleColor bg)
    {
        Kernel32.CharInfo[] buffer = new Kernel32.CharInfo[Width * Height];
        Kernel32.Coord cursor = Cursor;

        for (int i = 0; i < text.Length; i++)
        {
            if (text[i] == '\n')
            {
                cursor.X = 0;
                cursor.Y++;
            }
            else
            {
                int index = (cursor.Y * Width) + cursor.X;

                // Set character
                buffer[index].Char.AsciiChar = (byte)text[i];

                // Set color
                // (Crazy heckin bitwise crap, don't touch.)
                buffer[index].Attributes = (short)((int)fg | ((int)bg | (2 << 4)));

                // Increment cursor
                cursor.X++;
            }

            // Make sure that cursor does not exceed bounds of window
            if (cursor.X >= Width)
            {
                cursor.X = 0;
                cursor.Y++;
            }
            if (cursor.Y >= Height)
            {
                cursor.Y = 0;
            }
        }

        var writeRegion = WriteRegion;
        Kernel32.WriteConsoleOutput(Handle, buffer, BufferSize, BufferCoord, ref writeRegion);

        Console.SetCursorPosition(cursor.X, cursor.Y);
    }
}

// Taken from https://stackoverflow.com/a/2754674/7937949
internal static class Kernel32
{
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public 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);

    [DllImport("Kernel32.dll", SetLastError = true)]
    public static extern bool WriteConsoleOutput(
        SafeFileHandle hConsoleOutput,
        CharInfo[] lpBuffer,
        Coord dwBufferSize,
        Coord dwBufferCoord,
        ref SmallRect lpWriteRegion);

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

        public Coord(short x, short y)
        {
            X = x;
            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(2)] 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;
    }
}

我主要是从this post获取实现,添加了一个新的类来简化它的使用。我不太清楚我的问题出在哪里,因为我的调试器工作不正常,但我很确定它在我的QuickDraw实现中。

当我尝试使用QuickDraw.Write()时,光标移动到它试图打印的任何字符串的末尾,但实际上什么也没有显示出来。我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-17 15:27:44

首先,你没有正确地复制代码。有一些错误。

  1. 在CharInfo变化中 [FieldOffset(2)] public CharUnion Char;[FieldOffset(0)] public CharUnion Char;
  2. $CONOUT更改为此CONOUT$
  3. 首先设置属性,然后设置AsciiChar

当然,如果您想要正确的前景/背景色表示,那么您必须删除2 << 4。我甚至不知道你为什么把它放在那里。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49880854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档