【发布时间】:2022-01-01 08:43:45
【问题描述】:
我见过this方法可以清线不闪烁, 但是有没有办法对整个控制台做同样的事情? (而不是使用 Console.Clear)
【问题讨论】:
我见过this方法可以清线不闪烁, 但是有没有办法对整个控制台做同样的事情? (而不是使用 Console.Clear)
【问题讨论】:
在没有明确界限的情况下对所有事物做空,然后就这样做
Console.Clear();
TitleWithoutSometing();
【讨论】:
您可以使用Console.WindowLeft / Console.WindowTop / Console.WindowHeight / Console.WindowWidth msdn 来获取屏幕缓冲区当前可见区域的大小。
然后,您只需将这些字符中的每一个替换为您所链接的答案所示的空格即可。
例如:
public static void ClearVisibleRegion()
{
int cursorTop = Console.CursorTop;
int cursorLeft = Console.CursorLeft;
for(int y = Console.WindowTop; y < Console.WindowTop + Console.WindowHeight; y++) {
Console.SetCursorPosition(Console.WindowLeft, y);
Console.Write(new string(' ', Console.WindowWidth);
}
Console.SetCursorPosition(cursorLeft, cursorTop);
}
这将清除屏幕上当前可见的所有内容并将光标返回到其原始位置。
如果您希望光标移动到左上角,您可以执行以下操作:
Console.SetCursorPosition(Console.WindowLeft, Console.WindowTop);
这可能仍会导致闪烁,因为清除所有线条需要一些时间。
如果您想完全避免闪烁,唯一的方法是绘制您想要在屏幕外显示的任何内容,然后一次复制整个屏幕。这将完全消除任何闪烁。
您可以通过调用SetCursorPosition() 来完成此操作,其位置在您的WindowLeft / WindowTop / WindowHeight / WindowWidth rect 之外(但仍在BufferHeight / BufferWidth 之内)。
然后绘制整个窗口的内容。
然后调用Console.MoveBufferArea()将内容复制到当前窗口区域。
【讨论】:
您可以使用Console.SetCursorPosition,然后覆盖您需要的所有内容:
public static void Main()
{
for (int i = 0; i < 100; i++)
{
Console.SetCursorPosition(0, 0);
Console.WriteLine("Index = " + i);
System.Threading.Thread.Sleep(500);
}
}
您也可以创建自己的函数来自动完成:
public static void ClearConsole()
{
Console.SetCursorPosition(0, 0);
Console.CursorVisible = false;
for (int y = 0; y<Console.WindowHeight; y++)
Console.Write(new String(' ', Console.WindowWidth));
Console.SetCursorPosition(0, 0);
Console.CursorVisible = true;
}
【讨论】:
Console.BufferHeight。
Console.Write() 将其写出来以避免写入之间的刷新。但恕我直言Console.MoveBufferArea() 将是最好的解决方案,因为它基本上保证了整个区域将立即更新 - 但这需要相当多的额外代码才能使其工作:)
如果您可以使用最新的 Visual Studio 和 C# 9。如果这是一个仅限 Windows 的项目,我建议您使用一些带有 CsWin32 包的源代码生成器。
我用它来传送到控制台。性能极佳。
using Windows.Win32;
using Windows.Win32.System.Console;
public static void ClearConsole()
{
var rows = (short)Console.WindowHeight;
var cols = (short)Console.WindowWidth;
SafeFileHandle h = PInvoke.CreateFile("CONOUT$",
Windows.Win32.Storage.FileSystem.FILE_ACCESS_FLAGS.FILE_GENERIC_READ | Windows.Win32.Storage.FileSystem.FILE_ACCESS_FLAGS.FILE_GENERIC_WRITE,
Windows.Win32.Storage.FileSystem.FILE_SHARE_MODE.FILE_SHARE_WRITE,
null,
Windows.Win32.Storage.FileSystem.FILE_CREATION_DISPOSITION.OPEN_EXISTING,
Windows.Win32.Storage.FileSystem.FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL,
null
);
if (!h.IsInvalid)
{
var screenBuffer = new CHAR_INFO[rows * cols];
var writeRegion = new SMALL_RECT
{
Left = 0,
Top = 0,
Right = (short)(cols),
Bottom = (short)(rows)
};
for (int y = 0; y < rows; y++)
{
for (int x = 0; x < cols; x++)
{
screenBuffer[y * cols + x].Attributes = (byte)Console.BackgroundColor;
//buf[y * cols + x].Char.UnicodeChar = '';
}
}
PInvoke.WriteConsoleOutput(
h,
screenBuffer[0],
new COORD { X = cols, Y = rows },
new COORD(),
ref writeRegion
);
}
}
我的NativeMethods.txt 文件:
CreateFile
WriteConsoleOutput
Ofc,您不必使用这些库。现在好多了。我之前设置了自己的对 Kernel32.dll 的 pinvoke 调用。
【讨论】: