Click here to Skip to main content
15,891,431 members
Articles / Desktop Programming / Win32

Clearing the Console Screen using API

Rate me:
Please Sign up or sign in to vote.
4.81/5 (8 votes)
1 Apr 2010CPL15 min read 40.6K   1   37  
Learn how to clear the console screen via API calls. In addition, learn some console techniques such as moving the text around the screen.
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace Magic.Samples.ConsoleSample
{
    /// <summary>
    /// Console horizontal text alignment.
    /// </summary>
    public enum ConsoleTextAlignment
    {
        /// <summary>
        /// Text is left aligned.
        /// </summary>
        Left,
        /// <summary>
        /// Text is right aligned.
        /// </summary>
        Right,
        /// <summary>
        /// Text is centered.
        /// </summary>
        Center
    }

    /// <summary>
    /// Console standard devices.
    /// </summary>
    public enum ConsoleStandardDevice
    {
        /// <summary>
        /// The input device.
        /// </summary>
        Input = SafeNativeMethods.STD_INPUT_HANDLE,
        /// <summary>
        /// The output device.
        /// </summary>
        Output = SafeNativeMethods.STD_OUTPUT_HANDLE,
        /// <summary>
        /// The error device (usually the output device.)
        /// </summary>
        Error = SafeNativeMethods.STD_ERROR_HANDLE
    }

    /// <summary>
    /// Extension methods for the console.
    /// </summary>
    public static class ConsoleExtensions
    {
        /// <summary>
        /// Clears the screen buffer.
        /// </summary>
        public static void ClearScreen()
        {
            // Clearing the screen starting from the first cell
            COORD location = new COORD();
            location.X = 0;
            location.Y = 0;

            ClearScreen(location);
        }
        /// <summary>
        /// Clears the screen buffer starting from a specific location.
        /// </summary>
        /// <param name="location">The location of which to start clearing the screen buffer.</param>
        public static void ClearScreen(COORD location)
        {
            // Clearing the screen starting from the specified location
            // Setting the character to a white space means clearing it
            // Setting the count to 0 means clearing to the end, not a specific length
            FillConsoleBuffer(location, 0, SafeNativeMethods.WHITE_SPACE);
        }

        /// <summary>
        /// Fills a specific cells with a specific character starting from a specific location.
        /// </summary>
        /// <param name="location">The location of which to start filling.</param>
        /// <param name="count">The number of cells starting from the location to fill.</param>
        /// <param name="character">The character to fill with.</param>
        public static void FillConsoleBuffer(COORD location, uint count, char character)
        {
            // Getting the console output device handle
            IntPtr handle = GetStandardDevice(ConsoleStandardDevice.Output);

            uint length;

            // If count equals 0 then user require clearing all the screen
            if (count == 0)
            {
                // Getting console screen buffer info
                CONSOLE_SCREEN_BUFFER_INFO info = GetBufferInfo(ConsoleStandardDevice.Output);
                // All the screen
                length = (uint)(info.dwSize.X * info.dwSize.Y);
            }
            else
                length = count;

            // The number of written characters
            uint numChars;

            // Calling the Win32 API function
            SafeNativeMethods.FillConsoleOutputCharacter(handle, character, length, location, out numChars);

            // Setting the console cursor position
            SetCursorPosition(location);
        }

        /// <summary>
        /// Rettrieves a handle for a specific device.
        /// </summary>
        /// <param name="device">The device of which to retrieve the handle for.</param>
        /// <returns>The handle for the specified device.</returns>
        public static IntPtr GetStandardDevice(ConsoleStandardDevice device)
        {
            // Calling the Win32 API function
            return SafeNativeMethods.GetStdHandle((int)device);
        }

        /// <summary>
        /// Writes an empty line to the console buffer on the current position of the cursor.
        /// </summary>
        public static void WriteLine()
        {
            WriteLine(string.Empty);
        }
        /// <summary>
        /// Writes specific text followed by a line terminator to the console buffer on the current position of the cursor.
        /// </summary>
        /// <param name="txt">The text to write.</param>
        public static void WriteLine(string txt)
        {
            WriteLine(txt, ConsoleTextAlignment.Left);
        }
        /// <summary>
        /// Writes specific text followed by a line terminator to the console buffer on the current position of the cursor with the specified line alignemnt.
        /// </summary>
        /// <param name="txt">The text to write.</param>
        /// <param name="alignment">The horizontal alignment of the text.</param>
        public static void WriteLine(string txt, ConsoleTextAlignment alignment)
        {
            Write(txt + Environment.NewLine, alignment);
        }
        /// <summary>
        /// Writes specific text to the console buffer on the current position of the cursor.
        /// </summary>
        /// <param name="txt">The text to write.</param>
        public static void Write(string txt)
        {
            Write(txt, ConsoleTextAlignment.Left);
        }
        /// <summary>
        /// Writes specific text to the console buffer on the current position of the cursor with the specified line alignment.
        /// </summary>
        /// <param name="txt">The text to write.</param>
        /// <param name="alignment">The horizontal alignment of the text.</param>
        public static void Write(string txt, ConsoleTextAlignment alignment)
        {
            if (alignment == ConsoleTextAlignment.Left)
                InternalWrite(txt);
            else
            {
                // Determining the location of which to begin writing
                CONSOLE_SCREEN_BUFFER_INFO info = GetBufferInfo(ConsoleStandardDevice.Output);

                COORD pos = new COORD();

                if (alignment == ConsoleTextAlignment.Right)
                    pos.X = (short)(info.dwSize.X - txt.Length);
                else // Center
                    pos.X = (short)((info.dwSize.X - txt.Length) / 2);

                pos.Y = info.dwCursorPosition.Y;

                // Changing the cursor position
                SetCursorPosition(pos);

                // Now writing on the current position
                InternalWrite(txt);
            }
        }
        /// <summary>
        /// Writing a specific text to the console output buffer starting from the current cursor position.
        /// </summary>
        /// <param name="txt">The text to write.</param>
        private static void InternalWrite(string txt)
        {
            // Required for the WriteConsole() function
            // It is the number of characters written
            uint count;
            // Getting the output handle
            IntPtr handle = GetStandardDevice(ConsoleStandardDevice.Output);
            // Calling the Win32 API function
            SafeNativeMethods.WriteConsole(handle, txt, (uint)txt.Length, out count, 0);
        }

        /// <summary>
        /// Shows or hides the cursor.
        /// </summary>
        /// <param name="show">Specifies whether to show the cursor or not.</param>
        public static void ShowCursor(bool show)
        {
            CONSOLE_CURSOR_INFO info;
            // Getting the output device
            IntPtr handle = GetStandardDevice(ConsoleStandardDevice.Output);

            // Getting the cursor info
            SafeNativeMethods.GetConsoleCursorInfo(handle, out info);

            // Determining the visibility of the cursor
            info.bVisible = show;

            // Setting the cursor info
            SafeNativeMethods.SetConsoleCursorInfo(handle, ref info);
        }

        /// <summary>
        /// Read the next line from the input device.
        /// </summary>
        /// <returns></returns>
        public static string ReadText()
        {
            // The buffer
            // Maximum number of characters is 256
            StringBuilder buffer = new StringBuilder(256);
            // Required for the function call
            uint count;
            // Getting the input device that's used for receiving user input
            SafeNativeMethods.ReadConsole(GetStandardDevice(ConsoleStandardDevice.Input), buffer,
                (uint)buffer.Capacity, out count, 0);
            // Returning the user input cutting up the line terminator
            return buffer.ToString().Substring(0, (int)(count - Environment.NewLine.Length));
        }

        /// <summary>
        /// Retrieves the buffer info of the specified device.
        /// </summary>
        /// <param name="device">The device of which to retrieve its information.</param>
        /// <returns>The buffer info of the specified device.</returns>
        public static CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo(ConsoleStandardDevice device)
        {
            // Returning the handle for the selected device
            IntPtr handle = GetStandardDevice(device);

            // Getting console screen buffer information
            CONSOLE_SCREEN_BUFFER_INFO info;
            SafeNativeMethods.GetConsoleScreenBufferInfo(handle, out info);

            return info;
        }

        /// <summary>
        /// Sets the cursor position in the buffer.
        /// </summary>
        /// <param name="pos">The coordinates of which to move the cursor to.</param>
        public static void SetCursorPosition(COORD pos)
        {
            // Getting the console output device handle
            IntPtr handle = SafeNativeMethods.GetStdHandle(SafeNativeMethods.STD_OUTPUT_HANDLE);

            // Moving the cursor to the new location
            SafeNativeMethods.SetConsoleCursorPosition(handle, pos);
        }

        /// <summary>
        /// Writes the buffer information to the screen.
        /// </summary>
        /// <param name="info">The information of which to write.</param>
        public static void WriteBufferInfo(CONSOLE_SCREEN_BUFFER_INFO info)
        {
            // Discovering console screen buffer information
            WriteLine("Console Buffer Info:");
            WriteLine("--------------------");

            WriteLine("Cursor Position:");
            WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "\t{0}, {1}",
                info.dwCursorPosition.X, info.dwCursorPosition.Y));

            // Is this information right?
            WriteLine("Maximum Window Size:");
            WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "\t{0}, {1}",
                info.dwMaximumWindowSize.X,
                info.dwMaximumWindowSize.Y));

            // Is this information right?
            WriteLine("Screen Buffer Size:");
            WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "\t{0}, {1}",
                info.dwSize.X, info.dwSize.Y));

            WriteLine("Screen Buffer Bounds:");
            WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "\t{0}, {1}, {2}, {3}",
                info.srWindow.Left, info.srWindow.Top,
                info.srWindow.Right, info.srWindow.Bottom));

            WriteLine("--------------------");
        }

        /// <summary>
        /// Writes the specific text followed by a line terminator to the left and moves it to the far right.
        /// </summary>
        /// <param name="txt">The text of which to write.</param>
        public static void MoveText(string txt)
        {
            // First, writing the text
            WriteLine(txt);

            // Getting the handle for the output device
            IntPtr handle = GetStandardDevice(ConsoleStandardDevice.Output);

            // Getting the screen buffer info for the output device
            CONSOLE_SCREEN_BUFFER_INFO screenInfo = GetBufferInfo(ConsoleStandardDevice.Output);

            // Selecting the text to be moved
            SMALL_RECT rect = new SMALL_RECT();
            rect.Left = 0; // The 1st cell
            rect.Top = (short)(screenInfo.dwCursorPosition.Y - 1); // The row of the text
            rect.Bottom = (short)(rect.Top); // Only a single line

            while (true)
            {
                // Moving to the right
                rect.Right = (short)(rect.Left + (txt.Length - 1));

                // Do not move it nore if we are in the far right of the buffer
                if (rect.Right == (screenInfo.dwSize.X - 1))
                    break;

                // The character to fill the empty cells created after the move with
                CHAR_INFO charInfo = new CHAR_INFO();
                charInfo.Char = SafeNativeMethods.WHITE_SPACE; // For clearing the cells

                // Calling the API function
                SafeNativeMethods.ScrollConsoleScreenBuffer(handle, ref rect, IntPtr.Zero, new COORD() { X = (short)(rect.Left + 1), Y = rect.Top }, ref charInfo);

                // Blocking the thread for the user to see the effect
                System.Threading.Thread.Sleep(100);

                // Moving the rectangle
                rect.Left++;
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Public License Version 1.0 (CPL)


Written By
Technical Lead
Egypt Egypt
Mohammad Elsheimy is a developer, trainer, and technical writer currently hired by one of the leading fintech companies in Middle East, as a technical lead.

Mohammad is a MCP, MCTS, MCPD, MCSA, MCSE, and MCT expertized in Microsoft technologies, data management, analytics, Azure and DevOps solutions. He is also a Project Management Professional (PMP) and a Quranic Readings college (Al-Azhar) graduate specialized in Quranic readings, Islamic legislation, and the Arabic language.

Mohammad was born in Egypt. He loves his machine and his code more than anything else!

Currently, Mohammad runs two blogs: "Just Like [a] Magic" (http://JustLikeAMagic.com) and "مع الدوت نت" (http://WithdDotNet.net), both dedicated for programming and Microsoft technologies.

You can reach Mohammad at elsheimy[at]live[dot]com

Comments and Discussions