代码之家  ›  专栏  ›  技术社区  ›  nothrow

不通过标准输出写入控制台窗口

  •  2
  • nothrow  · 技术社区  · 14 年前

    编辑:我知道可以写入stderr,不过,是否可以在控制台上为stderr设置光标位置?

    3 回复  |  直到 14 年前
        1
  •  6
  •   Tim Robinson    14 年前

    你可以写信给我 Console.Error ,虽然可以重定向,但它与stdout是分开的。

    可以在控制台上设置stderr的光标位置吗?

    编辑 :假设stderr尚未重定向,请参阅 Console.CursorTop Console.CursorLeft . 有 various other members on the Console class 你可能会觉得有用。

    WriteConsole 功能。据我所知,.NETFramework没有直接写入控制台窗口的方法。

        2
  •  0
  •   Timwi    14 年前

    如果我运行您的程序并重定向它的StandardOutput和StandardError,那么在没有控制台的情况下,您的写操作会发生什么?

    出于这个原因,答案很可能是你不能(除了可能使用疯狂的黑客,这可能涉及WindowsAPI,你说你不想使用)。

    把console窗口看作是一个UI元素,它允许用户查看程序的stdout/stderr(并提供stdin)。它并不是为了别的目的而存在的。

        3
  •  0
  •   Ryan    8 年前

    实际上,我最终实现了低级别 WriteConsoleOutput 不久前,作为基于终端的俄罗斯方块实现的一部分,我写了一篇文章,因为用 Console.BackgroundColor Console.Write ,对于全屏刷新来说太慢了。执行原始缓冲区输出是 许多的

    注意,这会将文本写入屏幕上的某个位置(例如5、10),但不会自行更新或跟踪光标位置—使用此方法写入将更新文本缓冲区并显示输出,但光标不会移动。您需要使用其他方法手动移动并跟踪控制台光标,这应该不会太困难。

    这是我的密码:

    主互操作类:

    public static class LowLevelConsole {
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private 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)]
        private 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) {
                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 ushort Attributes;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct SmallRect {
            public short Left;
            public short Top;
            public short Right;
            public short Bottom;
        }
    
    
        [STAThread]
        public static void Write(string line, CharacterAttribute attribute, short xLoc, short yLoc) {
            SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
    
            short writeHeight = 1;
            short writeWidth = (short)line.Length;
    
            if (!h.IsInvalid) {
                CharInfo[] buf = new CharInfo[writeWidth * writeHeight];
                SmallRect rect = new SmallRect() { Left = xLoc, Top = yLoc, Right = (short)(writeWidth + xLoc), Bottom = (short)(writeHeight + yLoc) };
    
                for (int i = 0; i < writeWidth; i++) {
                    buf[i].Attributes = (ushort)attribute;
                    buf[i].Char.UnicodeChar = line[i];
                }
    
                bool b = WriteConsoleOutput(h, buf, new Coord() { X = writeWidth, Y = writeHeight }, new Coord() { X = 0, Y = 0 }, ref rect);
            }
        }
    
        [STAThread]
        public static bool WriteBuffer(CharInfo[,] buffer) { // returns true of success
            SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
    
            if (!h.IsInvalid) {
                short BufferWidth = (short)buffer.GetLength(0);
                short BufferHeight = (short)buffer.GetLength(1);
                CharInfo[] buf = new CharInfo[BufferWidth * BufferHeight];
                SmallRect rect = new SmallRect() { Left = 0, Top = 0, Right = BufferWidth, Bottom = BufferHeight };
    
    
                for (int y = 0; y < BufferHeight; y++) {
                    for (int x = 0; x < BufferWidth; x++) {
                        buf[y * BufferWidth + x] = buffer[x, y];
                    }
                }
                return WriteConsoleOutput(h, buf, new Coord() { X = BufferWidth, Y = BufferHeight }, new Coord() { X = 0, Y = 0 }, ref rect);
            }
            return false;
        }
    }
    

    Character attributes :

    [Flags]
    public enum CharacterAttribute : ushort {
        FOREGROUND_BLUE = 0x0001,
        FOREGROUND_GREEN = 0x0002,
        FOREGROUND_RED = 0x0004,
        FOREGROUND_INTENSITY = 0x0008,
        BACKGROUND_BLUE = 0x0010,
        BACKGROUND_GREEN = 0x0020,
        BACKGROUND_RED = 0x0040,
        BACKGROUND_INTENSITY = 0x0080,
        COMMON_LVB_LEADING_BYTE = 0x0100,
        COMMON_LVB_TRAILING_BYTE = 0x0200,
        COMMON_LVB_GRID_HORIZONTAL = 0x0400,
        COMMON_LVB_GRID_LVERTICAL = 0x0800,
        COMMON_LVB_GRID_RVERTICAL = 0x1000,
        COMMON_LVB_REVERSE_VIDEO = 0x4000,
        COMMON_LVB_UNDERSCORE = 0x8000
    }
    

    测试代码:

    class Program {
        static void Main(string[] args) {
            // write to location 0,0
            LowLevelConsole.Write("Some test text", CharacterAttribute.BACKGROUND_BLUE | CharacterAttribute.FOREGROUND_RED, 0, 0);
            // write to location 5,10
            LowLevelConsole.Write("another test at a different location", 
                CharacterAttribute.FOREGROUND_GREEN | CharacterAttribute.FOREGROUND_BLUE,
                5, 10);
            Console.ReadLine();            
        }
    }