清除整个控制台不闪烁 c#
Clear whole Console Without flicker c#
我见过this可以清除一行不闪烁的方法,
但是有没有办法对整个控制台做同样的事情?
(而不是使用 Console.Clear)
对所有没有清除线的东西做一个空白,然后就这样做
Console.Clear();
TitleWithoutSometing();
您可以使用Console.WindowLeft
/ Console.WindowTop
/ Console.WindowHeight
/ Console.WindowWidth
msdn 获取屏幕缓冲区当前可见区域的大小。
然后您只需要用 space 替换每个字符,就像您链接的答案所展示的那样。
例如:
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);
}
这将清除屏幕上当前可见的所有内容,并且return光标回到原来的位置。
如果你想让光标移动到左上角,你可以这样做:
Console.SetCursorPosition(Console.WindowLeft, Console.WindowTop);
这可能仍然会导致闪烁,因为清除所有行需要一些时间。
如果你想完全避免闪烁,唯一的方法是在屏幕外绘制任何你想显示的内容,然后立即复制到整个屏幕。这将完全消除任何闪烁。
您可以通过使用 WindowLeft
/ WindowTop
/ WindowHeight
/ WindowWidth
矩形之外的位置调用 SetCursorPosition()
来完成此操作(但仍在BufferHeight
/ BufferWidth
).
然后绘制完整的 window 内容。
然后调用Console.MoveBufferArea()
将内容复制到当前window区域。
您可以使用 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;
}
如果您可以将最新的 Visual Studio 与 C# 9 一起使用。如果这是一个仅 windows 的项目,我建议您将一些源代码生成器与 CsWin32 包一起使用。
我用它来 blit 到控制台。性能极佳。
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
当然,您不必使用这些库。现在好多了。我之前设置了自己的 pinvoke 调用 Kernel32.dll.
我见过this可以清除一行不闪烁的方法, 但是有没有办法对整个控制台做同样的事情? (而不是使用 Console.Clear)
对所有没有清除线的东西做一个空白,然后就这样做
Console.Clear();
TitleWithoutSometing();
您可以使用Console.WindowLeft
/ Console.WindowTop
/ Console.WindowHeight
/ Console.WindowWidth
msdn 获取屏幕缓冲区当前可见区域的大小。
然后您只需要用 space 替换每个字符,就像您链接的答案所展示的那样。
例如:
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);
}
这将清除屏幕上当前可见的所有内容,并且return光标回到原来的位置。
如果你想让光标移动到左上角,你可以这样做:
Console.SetCursorPosition(Console.WindowLeft, Console.WindowTop);
这可能仍然会导致闪烁,因为清除所有行需要一些时间。
如果你想完全避免闪烁,唯一的方法是在屏幕外绘制任何你想显示的内容,然后立即复制到整个屏幕。这将完全消除任何闪烁。
您可以通过使用 WindowLeft
/ WindowTop
/ WindowHeight
/ WindowWidth
矩形之外的位置调用 SetCursorPosition()
来完成此操作(但仍在BufferHeight
/ BufferWidth
).
然后绘制完整的 window 内容。
然后调用Console.MoveBufferArea()
将内容复制到当前window区域。
您可以使用 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;
}
如果您可以将最新的 Visual Studio 与 C# 9 一起使用。如果这是一个仅 windows 的项目,我建议您将一些源代码生成器与 CsWin32 包一起使用。
我用它来 blit 到控制台。性能极佳。
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
当然,您不必使用这些库。现在好多了。我之前设置了自己的 pinvoke 调用 Kernel32.dll.