我怎样才能写出快速的彩色输出到控制台?

我想知道是否有另一种( 更快 )的方式使用C#.net输出文本到控制台应用程序窗口,而不是使用简单的WriteBackgroundColorForegroundColor方法和属性? 我了解到,每个单元格都有一个背景颜色和一个前景色,我想caching/缓冲/写比使用上述方法更快。

也许有一些使用Out缓冲区的帮助,但我不知道如何将颜色编码到stream中,如果这是颜色数据所在的位置。

这是一个基于文本的逆向游戏,我想实现在哪里使用标准颜色和ASCII字符来布局游戏。

请帮忙 :)

更新:

输出和缓冲区可能不是我所需要的。 似乎有一个屏幕缓冲区拥有的控制台。 我不知道如何访问它,也许我只是运气不好,除非我导入一些dll。

更新:添加一个示例
如果你准备做一些P / Invoke的东西,这可能会有所帮助。

基本上,如果你得到一个控制台缓冲区的句柄,那么你可以使用标准的Win32 APIs来操纵缓冲区,甚至可以把整个缓冲区closures屏幕,并把它传送到控制台。

唯一棘手的部分是获取控制台缓冲区的句柄。 我没有在.NET中试过这个,但是在过去的几年中,你可以通过使用CreateFile(你需要P / Invoke这个)来获得当前控制台的句柄,并打开“CONOUT $”,然后你可以使用句柄是返回到其他API的传递。

P /调用CreateFile
http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html

您可以使用WriteConsoleOutput将所有字符及其属性从内存缓冲区移到控制台缓冲区。
http://msdn.microsoft.com/en-us/library/ms687404(VS.85).aspx

你可以把一个很好的库放在一起,提供对控制台缓冲区的低级访问。

因为我正试图让我的.NET再次受到伤害,所以我想我会试试这个,看看我能否得到它的工作。 这里是一个样例,将填满所有字母AZ的屏幕,并运行所有的forground属性0-15。 我想你会对这个performance留下深刻的印象。 我会说实话,我没有花太多时间回顾这段代码,所以错误检查是零,这里或那里可能有一个小错误,但它应该让你去与其余的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(); } } } 

如果查看Console属性的实现以更改控制台颜色,则它们将从委托给kernel32.dll的SetConsoleTextAttribute方法中。 该方法以字符属性作为input来设置前景色和背景色。

从几个MSDN文档页面,每个屏幕缓冲区(其中一个控制台有一个)具有字符信息logging的二维数组,每个字符信息logging由CHAR_INFO表示。 这决定了每个angular色的颜色。 您可以使用SetConsoleTextAttribute方法来处理此操作,但这适用于写入控制台的任何新文本 – 您无法操作控制台上已存在的文本。

除非在控制台文本颜色属性(看起来不太可能)中有一个较低级别的钩子,否则我认为你使用这些方法卡住了。


你可以尝试的一件事是创build一个新的屏幕缓冲区,写入,然后使用SetConsoleActiveScreenBuffer将其切换为控制台的当前缓冲区。 这可能会产生更快的输出,因为您将把所有输出写入非活动缓冲区。