How to prevent the console to write a character in the last line?
Asked Answered
A

3

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?

Admiration answered 8/1, 2014 at 15:5 Comment(10)
This extra character is known as the 'cursor'.Stromboli
Don't draw right bottom edge and it should be fine.Warlord
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?Admiration
You could put some info in that last line, to example "Version 1.0".Warlord
That would be a solution but feels not very professional to avoid this problem.Admiration
This might be a silly question, but are there any newlines in your character matrix?Influx
Nope. That's the reason why I used an array of chars instead of a string array.Admiration
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. 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.Influx
Is it really necessary to "goof around" with the char array to avoid this behavior? Is the console output really that annoying? ^^Admiration
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.Influx
H
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);
        }
    }
}
Homoeroticism answered 8/1, 2014 at 15:23 Comment(8)
So moving the cursor to 0,0 after writing the last character "╝" prevents the console to draw the last line?Admiration
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.Homoeroticism
Is the cursor postion 0,0 the first writable position?Admiration
0,0 is the top-left corner. Yes. That is the first.Homoeroticism
Are there any "invisible" borders in a console window? Like columns you can't write to?Admiration
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 hereAdmiration
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.Homoeroticism
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. :)Admiration
S
4

Use CursorVisible property of Console

Console.CursorVisible = false;
Siena answered 8/1, 2014 at 15:8 Comment(4)
I think the problem here is not the blinking cursor, but the thing that a line's last written character moves the cart to the next line.Homoeroticism
Thank you for specifying my question @AttilaBujáki. :) Of course I mean the new line...Admiration
Did you try this? It may be the case that it only wraps because it needs to display the cursor and you have run out of screen buffer.Influx
Disabling the cursor visibility? Yes, I tried it. Unfortunately it didn't help.Admiration
O
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
    );
Oligopoly answered 26/5, 2016 at 2:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.