tags:

views:

106

answers:

3

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?

+1  A: 

Silky's comment is the right answer:

  • Set an appropriate background colour
  • Loop for each line you wish to clear part of:
    • Set the cursor position to left hand side
    • Write out a string of spaces of the right width

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.

Jon Skeet
Wil this delete whole lines? Because my program is an old school astroids game and im trying to make the ship move so i have to delete its last location.
@shorty876: No, it will just overwrite the width you specify.
Jon Skeet
Ok, my idea is not gonna work..ive tried out other things but its time to move on. you get acepted answer for the clear and understandable code
+2  A: 

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;
    }   
  }
}
Chris Taylor
A: 

I tried Jon Skeet's way but it doesnt work...

    int shipL1Left1 = 4;
    int shipL1Top1 =  18;

    int shipL1Left2 = 1;
    int shipL1Top2  = 18;


    int shipL2Left = 0;
    int shipL2Top  = 19;

    int shipL3Left = 0;
    int shipL3Top  = 20;

    int shipL4Left = 0;
    int shipL4Top  = 21;

    public void shipMovement()
    {
        ConsoleKeyInfo keypress;
        keypress = Console.ReadKey(); // read keystrokes



        if (keypress.Key == ConsoleKey.RightArrow)
        {

            shipL1Left1 = shipL1Left1 + 2;
            shipL1Left2 = shipL1Left2 + 2;
            shipL2Left  = shipL2Left  + 2;
            shipL3Left  = shipL3Left  + 2;
            shipL4Left  = shipL4Left  + 2;
            MainClass.ClearArea(shipL1Top1,shipL1Left1,80,24);
            MainClass.ClearArea(shipL1Top2,shipL1Top2,80,24);
            MainClass.ClearArea(shipL3Top,shipL3Left,80,24);
            MainClass.ClearArea(shipL4Top,shipL4Left,80,24);
        }

Error being:

Unhandled Exception: System.ArgumentOutOfRangeException: Value must be positive and below the buffer height. Parameter name: top

@shorty876: You've misunderstood the parameters to my method. How big is your ship? Presumably it's not 24 lines long... currently this is going to try to clear lines 21-44 for ship 4, for example.
Jon Skeet