I've seen this method that can clear a line without flicker, but is there a way to do the same to the whole console? (instead of using Console.Clear)
CodePudding user response:
You can use Console.SetCursorPosition
and then override everything that you need to:
public static void Main()
{
for (int i = 0; i < 100; i )
{
Console.SetCursorPosition(0, 0);
Console.WriteLine("Index = " i);
System.Threading.Thread.Sleep(500);
}
}
You can also create your own function to do it automatically:
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;
}
CodePudding user response:
You can use Console.WindowLeft
/ Console.WindowTop
/ Console.WindowHeight
/ Console.WindowWidth
msdn to get the size of the currently visible region of the screen buffer.
Then you just need to replace each of those characters with a space like the answer you linked demonstrated.
e.g.:
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);
}
this will clear everything currently visible on the screen and return the cursor back to its original position.
If you want the cursor to move to the top left corner instead, you can do the following:
Console.SetCursorPosition(Console.WindowLeft, Console.WindowTop);
this might still result in flickering though, since it'll take some time to clear all the lines.
If you want to avoid flickering completely the only way is to draw whatever you want to display off-screen and then copy over the entire screen at once. That'll completely get rid of any flickering.
You can accomplish this by calling SetCursorPosition()
with a position that's outside your WindowLeft
/ WindowTop
/ WindowHeight
/ WindowWidth
rect (but still within BufferHeight
/ BufferWidth
).
Then draw an entire window worth of content.
Then call Console.MoveBufferArea()
to copy the content over into the current window area.
CodePudding user response:
If you can use the latest Visual Studio along with C# 9. I would recommend using some source-generators with the CsWin32 package if this is a windows only project.
I use this to blit to the console. Extremely performant.
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
);
}
}
My NativeMethods.txt
file:
CreateFile
WriteConsoleOutput
Ofc, you don't have to use those libraries. It's just nicer now. I previously set up my own pinvoke calls to Kernel32.dll.
CodePudding user response:
Do an void with all things without cleared line and just do that
Console.Clear();
TitleWithoutSometing();