清除整个控制台不闪烁 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.