6

I have a problem with a console project of C#. I want to use the whole console screen to write text in it. Meaning, for example, to "draw" a border along the border of the console. The problem is the unnecessary last character in the last line. How can I prevent it?

For a better understanding, I've added a picture of the unwanted character.Screenshot of the console

I draw it by filling a two dimensional array of chars and dumping it with the following method. yMax is the height and xMax the width of the console window.

private void DumpCharacters()
    {
        for (int y = 0; y < yMax - 1; y++)
        {
            string line = string.Empty;
            for (int x = 0; x < xMax; x++)
            {
                line += characters[x, y];
            }
            Console.SetCursorPosition(0, y);
            Console.Write(line);
        }
    }

I already tried to increase the height of the border, but then, the mentioned character overwrites the border at that position.

EDIT: Sorry for my unclear explanation. Of course I meant, like Attila Bujáki said, the jump to the last line. Is it possible to prevent this?

Marco Frost
  • 780
  • 3
  • 12
  • 25
  • 1
    This extra character is known as the 'cursor'. – Gusdor Jan 08 '14 at 15:09
  • Don't draw right bottom edge `╝` and it should be fine. – Sinatr Jan 08 '14 at 15:16
  • But I want to have the ╝ at the bottom right edge, @Sinatr. Isn't there any other possibility to prevent the console from the jump to the next line? – Marco Frost Jan 08 '14 at 15:21
  • You could put some info in that last line, to example "Version 1.0". – Sinatr Jan 08 '14 at 15:23
  • That would be a solution but feels not very professional to avoid this problem. – Marco Frost Jan 08 '14 at 15:26
  • This might be a silly question, but are there any newlines in your character matrix? – Phillip Scott Givens Jan 08 '14 at 15:31
  • Nope. That's the reason why I used an array of chars instead of a string array. – Marco Frost Jan 08 '14 at 15:33
  • It sounds to me that you have a character wrapping problem. You write the last character in the line, the screen buffer is the same length as the character array and the cursor wraps. Perhaps you can try doing some magic with [Console.MoveBufferArea](http://msdn.microsoft.com/en-us/library/zks4cwcf.aspx). Try writing the last character first and then moving it. This may cause some sort of flickering, but only when that character needs to be refreshed. – Phillip Scott Givens Jan 08 '14 at 15:55
  • Is it really necessary to "goof around" with the char array to avoid this behavior? Is the console output really that annoying? ^^ – Marco Frost Jan 08 '14 at 16:24
  • 1
    I feel your frustration. That is why I leave this in a comment and not as an official answer. It seems to me that System.Console does not directly support your use-case. I cannot even find a write right-to-left feature for you. – Phillip Scott Givens Jan 08 '14 at 17:23

3 Answers3

5

If you want to fill the whole console window with your characters a possible way to go is to move back your cursor to the 0,0 position.

Example:

Console.CursorVisible = false;
for(int i = 0; i < Console.WindowHeight * Console.WindowWidth; i ++)
{
     Console.Write((i / Console.WindowWidth) % 10);  // print your stuff
}
Console.SetCursorPosition(0, 0);

Console.ReadKey();

So you could do it like this in your method:

private void DumpCharacters()
    {
        for (int y = 0; y < yMax; y++)
        {
            string line = string.Empty;
            for (int x = 0; x < xMax; x++)
            {
                line += characters[x, y];
            }
            Console.SetCursorPosition(0, y);
            Console.Write(line);
        }
        Console.SetCursorPosition(0, 0);
    }

Notice that you don't have to substract one from yMax. It is because now you can use the last line of the Console screen too.

Console with an character border

Here is the full code to generate the desired outcome:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleChar
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "Stackoverflow - Super example";
            Console.CursorVisible = false;

            int yMax = Console.WindowHeight;
            int xMax = Console.WindowWidth;
            char[,] characters= new char[Console.WindowWidth, Console.WindowHeight];

            for (int i = 0; i < Console.WindowWidth; i++ )
            {
                for (int j = 0; j < Console.WindowHeight; j++)
                {
                    char currentChar = ' ';

                    if((i == 0) || (i == Console.WindowWidth - 1))
                    {
                        currentChar = '║';
                    }
                    else
                    {
                        if((j == 0) || (j == Console.WindowHeight - 1))
                        {
                            currentChar = '═';
                        }
                    }                    

                    characters[i, j] = currentChar;
                }
            }

            characters[0, 0] = '╔';
            characters[Console.WindowWidth-1, 0] = '╗';
            characters[0, Console.WindowHeight - 1] = '╚';
            characters[Console.WindowWidth - 1, Console.WindowHeight - 1] = '╝';

                for (int y = 0; y < yMax ; y++)
                {
                    string line = string.Empty;
                    for (int x = 0; x < xMax; x++)
                    {
                        line += characters[x, y];
                    }
                    Console.SetCursorPosition(0, y);
                    Console.Write(line);
                }
            Console.SetCursorPosition(0, 0);
        }
    }
}
Attila
  • 3,206
  • 2
  • 31
  • 44
  • So moving the cursor to 0,0 after writing the last character "╝" prevents the console to draw the last line? – Marco Frost Jan 08 '14 at 15:24
  • Actually the cursor moves to the next line (line after the last line we want to show), but then it immediately gets back to the position 0,0 so you won't see it anymore. Try it to see the results. I just did, it works fine for me. – Attila Jan 08 '14 at 15:26
  • Is the cursor postion 0,0 the first writable position? – Marco Frost Jan 08 '14 at 15:34
  • 0,0 is the top-left corner. Yes. That is the first. – Attila Jan 08 '14 at 15:37
  • Are there any "invisible" borders in a console window? Like columns you can't write to? – Marco Frost Jan 08 '14 at 15:49
  • Okay. I've double-checked my char array and adjusted my method like you suggested it. Now, the border is somewhat shifted to the top. See [here](http://s16.postimg.org/8kw556qyt/Example.png) – Marco Frost Jan 08 '14 at 16:18
  • I have implemented the whole thing. See the code example and my screenshot. I hope you can use my code to figure out what was wrong. Please take your time to up and/or accept my answer if it helped you. – Attila Jan 08 '14 at 20:17
  • 1
    Okay. The right border is drawn correctly now. The "problem" I had was not originated in the drawing of it but in the way I wait for an input. I use `Console.ReadKey(true);` for holding the console. Maybe that's the issue. Maybe that creates the new line. When removing this line, the border will be drawn a kind of correctly. Due to the rapid multiple drawing, it seems like the border is shivering. But that's another topic I think. :) – Marco Frost Jan 09 '14 at 12:02
4

Use CursorVisible property of Console

Console.CursorVisible = false;
Abdusalam Ben Haj
  • 5,343
  • 5
  • 31
  • 45
gleng
  • 6,185
  • 4
  • 21
  • 35
4

The accepted answer doesn't work if the Console buffer size is the same as the window size. As Phillip Scott Givens mentioned above, you have to use Console.MoveBufferArea writing to somewhere other than the bottom-right corner. This is the only way to solve the problem using the System.Console API even with Console.CursorVisible = false. Example code:

var w = Console.WindowWidth;
var h = Console.WindowHeight;
Console.SetBufferSize(w, h);

// Draw all but bottom-right 2 characters of box here ...

// HACK: Console.Write will automatically advance the cursor position at the end of each
// line which will push the buffer upwards resulting in the loss of the first line
var sourceReplacement = '═';
Console.SetCursorPosition(w - 2, h - 1); // bottom-right minus 1
Console.Write('╝');
// Move from bottom-right minus 1 to bottom-right overwriting the source
// with the replacement character
Console.MoveBufferArea(w - 2, h - 1, 1, 1, w - 1, h - 1,
    sourceReplacement, Console.ForegroundColor, Console.BackgroundColor);

If you're not fine with that, you can use the native console API (but it is Windows-only):

// http://pinvoke.net/default.aspx/kernel32/FillConsoleOutputCharacter.html
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FillConsoleOutputCharacter(
    IntPtr hConsoleOutput,
    char cCharacter,
    uint nLength,
    COORD dwWriteCoord,
    out uint lpNumberOfCharsWritten
    );
Community
  • 1
  • 1
Graeme Wicksted
  • 1,770
  • 1
  • 18
  • 21