¿Cómo puedo escribir una salida de color rápida a la consola?

Quiero aprender si hay otra forma ( más rápida ) de enviar texto a la ventana de la aplicación de la consola usando C # .net que con los métodos y propiedades simples Write , BackgroundColor y ForegroundColor . Aprendí que cada celda tiene un color de fondo y un color de primer plano, y me gustaría almacenar en caché / memoria intermedia / escribir más rápido que con los métodos mencionados.

Tal vez haya alguna ayuda para usar el búfer Out, pero no sé cómo codificar los colores en la transmisión, si es allí donde residen los datos de color.

Esto es para un juego basado en texto retrostyle que quiero implementar donde hago uso de los colores estándar y los personajes ascii para diseñar el juego.

Por favor ayuda 🙂

Actualizar:

El Out y el buffer probablemente no sean lo que necesito perder. Parece que hay un buffer de pantalla que es propiedad de la consola. No sé cómo acceder a él, tal vez me quede sin suerte a menos que importe algunos dlls.

Actualización: agregó una muestra
Si está preparado para hacer algunas cosas de P / Invoke, esto podría ayudar.

Básicamente, si maneja el búfer de la consola, puede usar las API estándar de Win32 que manipulan el búfer, incluso crea todo el búfer de la pantalla y lo envía a la consola.

La única parte difícil es obtener el identificador para el buffer de la consola. No he probado esto en .NET, pero en años pasados, usted podría obtener el control de la consola actual usando CreateFile (necesitará P / Invocar esto) y abrir “CONOUT $”, entonces puede usar el manejador que es volver a pasar a las otras API.

P / Invoke para CreateFile
http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html

Y puede usar WriteConsoleOutput para mover todos los caracteres y sus atributos de un búfer de memoria al búfer de la consola.
http://msdn.microsoft.com/en-us/library/ms687404(VS.85).aspx

Probablemente pueda armar una buena biblioteca para proporcionar acceso de menor nivel al búfer de la consola.

Como estoy tratando de volver a rayar mi .NET, pensé que podría intentarlo y ver si podía hacerlo funcionar. Aquí hay una muestra que llenará la pantalla con todas las letras AZ y recorrerá todos los atributos forground 0-15. Creo que quedarás impresionado con el rendimiento. Seré honesto, no pasé mucho tiempo revisando este código así que la comprobación de errores es cero y podría haber un pequeño error aquí o allá, pero debería funcionar con el rest de las API.

using System; using System.IO; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace ConsoleApplication1 { class Program { [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 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)] 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 short Attributes; } [StructLayout(LayoutKind.Sequential)] public struct SmallRect { public short Left; public short Top; public short Right; public short Bottom; } [STAThread] static void Main(string[] args) { SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); if (!h.IsInvalid) { CharInfo[] buf = new CharInfo[80 * 25]; SmallRect rect = new SmallRect() { Left = 0, Top = 0, Right = 80, Bottom = 25 }; for (byte character = 65; character < 65 + 26; ++character) { for (short attribute = 0; attribute < 15; ++attribute) { for (int i = 0; i < buf.Length; ++i) { buf[i].Attributes = attribute; buf[i].Char.AsciiChar = character; } bool b = WriteConsoleOutput(h, buf, new Coord() { X = 80, Y = 25 }, new Coord() { X = 0, Y = 0 }, ref rect); } } } Console.ReadKey(); } } } 

Si observa la implementación de las propiedades de la consola para alterar los colores de la consola, delegará en el método SetConsoleTextAttribute de kernel32.dll . Este método toma atributos de caracteres como entrada para establecer los colores de primer plano y de fondo.

Desde varias páginas de documentación de MSDN, cada búfer de pantalla (de los cuales una consola tiene uno) tiene una matriz bidimensional de registros de información de caracteres, cada uno representado por un CHAR_INFO . Esto es lo que determina el color de cada personaje. Puede manipular esto utilizando el método SetConsoleTextAttribute , pero esto se aplica a cualquier texto nuevo que se escriba en la consola; no puede manipular el texto existente que ya está en la consola.

A menos que haya un gancho de nivel inferior en las propiedades de color de texto de la consola (lo cual no parece probable), creo que estás atascado usando estos métodos.


Una cosa que podría intentar es crear un nuevo búfer de pantalla, escribirlo y luego cambiarlo para que sea el búfer actual de la consola usando SetConsoleActiveScreenBuffer . Esto puede producir una salida más rápida ya que estará escribiendo toda la salida en un buffer inactivo.