gpt4 book ai didi

c# - 如何将快速彩色输出写入控制台?

转载 作者:IT王子 更新时间:2023-10-29 03:55:39 37 4
gpt4 key购买 nike

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

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

这是我想要实现的基于文本的复古风格游戏,我使用标准颜色和 ascii 字符来布置游戏。

请帮忙:)

更新:

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

最佳答案

更新:添加了一个示例
如果您准备好执行一些 P/Invoke 操作,这可能会有所帮助。

基本上,如果您获得了控制台缓冲区的句柄,那么您就可以使用标准的 Win32 API 来操作缓冲区,甚至可以在屏幕外构建整个缓冲区并将其 blit 到控制台。

唯一棘手的部分是获取控制台缓冲区的句柄。我没有在 .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 再次从头开始,所以我想我会尝试一下,看看我是否可以让它工作。这是一个示例,它将用所有字母 A-Z 填充屏幕并遍历所有前景属性 0-15。我想你会对表演印象深刻。老实说,我没有花太多时间检查这段代码,所以错误检查为零,这里或那里可能有一些小错误,但它应该能让你继续使用其余的 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 WriteConsoleOutputW(
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 ushort 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 = WriteConsoleOutputW(h, buf,
new Coord() { X = 80, Y = 25 },
new Coord() { X = 0, Y = 0 },
ref rect);
}
}
}
Console.ReadKey();
}
}
}

Unicode 示例

using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace FastConsole
{
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 WriteConsoleOutputW(
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 ushort 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 (ushort character = 0x2551; character < 0x2551 + 26; ++character)
{
for (short attribute = 0; attribute < 15; ++attribute)
{
for (int i = 0; i < buf.Length; ++i)
{
buf[i].Attributes = attribute;
buf[i].Char.UnicodeChar = character;
}

bool b = WriteConsoleOutputW(h, buf,
new Coord() { X = 80, Y = 25 },
new Coord() { X = 0, Y = 0 },
ref rect);
Console.ReadKey();
}
}
}
Console.ReadKey();
}
}
}

关于c# - 如何将快速彩色输出写入控制台?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2754518/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com