Reputation: 4989
Is there anyway to delete certain parts of a console window using the (Left,Top) coordinates used with Console.SetCursorPosition()?
Could you make a custom method for it?
Upvotes: 6
Views: 4690
Reputation: 961
I want to add something for anyone using .NET 9
(C# 13
) or later.
You can use ANSI Escape Codes
, particularly the Erase Function
-- ESC[0K = erase from cursor to end of line
-- within a loop
Since C# 13
, you can use the \e as a character literal escape sequence
Example (sexy) function:
static void ClearLines(int begin, int end) {
for (int i = begin; i < end; i++) {
Console.SetCursorPosition(0, i);
// \e = new ESCAPE character in C# 13 (.NET 9):
// https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#new-escape-sequence
// ESC[0K = erase from cursor to end of line:
// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#erase-functions
Console.Write("\e[0K");
}
}
Example usage
// Save cursor position somewhere in your code
(int leftBegin, int topBegin) = Console.GetCursorPosition();
// Your code here
// Left ending cursor position is not needed, so use a discard variable
(int _, int topEnd) = Console.GetCursorPosition();
// The sexy function
ClearLines(topBegin, topEnd);
// Reset cursor position to the desired saved position
Console.SetCursorPosition(leftBegin, topBegin);
Upvotes: 0
Reputation: 53699
If performance is a concern you can directly manipulate the console buffer. Unfortuantely this will require some interop, here is an example that I have adapted from a previous answer I gave. This will clear an area of the console buffer very quickly. It is a bit lengthy because of the interop, but if you wrap this nicely into a console helper class you can extend it to do all kinds of high performance console output.
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace ConsoleApplication1
{
class Program
{
[STAThread]
static void Main(string[] args)
{
Console.SetCursorPosition(0, 0);
for (int x = 0; x < 80 * 25; ++x)
{
Console.Write("A");
}
Console.SetCursorPosition(0, 0);
Console.ReadKey(true);
ClearArea(1, 1, 78, 23);
Console.ReadKey();
}
static void ClearArea(short left, short top, short width, short height)
{
ClearArea(left, top, width, height, new CharInfo() { Char = new CharUnion() { AsciiChar = 32 } });
}
static void ClearArea(short left, short top, short width, short height, CharInfo charAttr)
{
using (SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero))
{
if (!h.IsInvalid)
{
CharInfo[] buf = new CharInfo[width * height];
for (int i = 0; i < buf.Length; ++i)
{
buf[i] = charAttr;
}
SmallRect rect = new SmallRect() { Left = left, Top = top, Right = (short)(left + width), Bottom = (short)(top + height) };
WriteConsoleOutput(h, buf,
new Coord() { X = width, Y = height },
new Coord() { X = 0, Y = 0 },
ref rect);
}
}
}
[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)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteConsoleOutput(
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 char 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;
}
}
}
Upvotes: 5
Reputation: 1499770
Silky's comment is the right answer:
For example:
public static void ClearArea(int top, int left, int height, int width)
{
ConsoleColor colorBefore = Console.BackgroundColor;
try
{
Console.BackgroundColor = ConsoleColor.Black;
string spaces = new string(' ', width);
for (int i = 0; i < height; i++)
{
Console.SetCursorPosition(left, top + i);
Console.Write(spaces);
}
}
finally
{
Console.BackgroundColor = colorBefore;
}
}
Note that this will restore the background colour, but not the previous cursor location.
Upvotes: 7