4

I'm trying to have my console application automatically scroll but keep the text at the top. The text history must be accessible so Console.Clear isn't viable.

Is there any method to detect when console scrolls or any method to adjust the current Y pos, as I know console will scroll when your text is about to be off-screen. I'd like this same effect, but to keep the newest line at the top of the window. Any help is appreciated, thank you!

Joshua
  • 41
  • 3
  • I don't really understand what you describe in english, but maybe you can use `Console.SetCursorPosition()`. –  Feb 11 '20 at 11:50
  • @OlivierRogier `SetCursorPosition` only sets the position of the _cursor_ but it doesn't scroll the contents. The OP (as I understand) wants the same effect as manually scrolling to only show the top line. – 41686d6564 stands w. Palestine Feb 11 '20 at 11:52
  • @AhmedAbdelhameed So the OP needs to get the console windows handle and use scrollbars' WinAPIs ? https://stackoverflow.com/questions/1277563/how-do-i-get-the-handle-of-a-console-applications-window & https://learn.microsoft.com/en-us/windows/console/scrolling-the-screen-buffer & https://learn.microsoft.com/en-us/windows/console/scrolling-a-screen-buffer-s-window –  Feb 11 '20 at 11:57
  • @OlivierRogier Not really. `Console.SetWindowPosition()` does that for you. Note that a "window" here doesn't mean the actual Console window itself. See my answer below for more info. – 41686d6564 stands w. Palestine Feb 11 '20 at 12:07
  • 1
    @AhmedAbdelhameed Ok, your result animation seems to be good and now I understand the OP question. –  Feb 11 '20 at 12:08

1 Answers1

6

You may use the Console.SetWindowPosition() method. *

Parameters
left Int32
The column position of the upper left corner of the console window.

top Int32
The row position of the upper left corner of the console window.

Here's an example to demonstrate:

static void Main(string[] args)
{
    int i = 0;
    while (true)
    {
        Console.ReadKey(false);
        Console.WriteLine($"You are currently at line #{++i}");
        Console.SetWindowPosition(0, i - 1);
    }
}

Result:

Scroll Console to Top

Note that if you're getting close to the value of Console.BufferHeight, you could get an ArgumentOutOfRangeException, that is, when the new position (top) is greater than Console.BufferHeight - Console.WindowHeight, so you might want to take that into account. I would add a simple condition to handle this case. Example:

int newTop = i - 1;
if (newTop + Console.WindowHeight <= Console.BufferHeight)
{
    Console.SetWindowPosition(0, newTop);
}

..but you might want to handle this differently (e.g., increase the buffer as you go, change the window size, etc.)


* Don't be mislead by the name of the method. A "window" here doesn't mean the actual desktop/console window in OS terms (borders, etc.). Instead, it refers to the currently displayed window of the character buffer. To move the actual console window, you'd have to use the SetWindowPos Windows API function. Example.

  • 1
    I think the OP is asking for setting the position of the text, not the window position of the console. – Eriawan Kusumawardhono Feb 11 '20 at 11:40
  • @EriawanKusumawardhono This code does exactly what you just described. – 41686d6564 stands w. Palestine Feb 11 '20 at 11:43
  • @AhmedAbdelhameed I know, that's why I upvoted the answer and was trying to clear things up. But I think the confusion is mostly because `SetWindowPosition` is a confusing name for this method as it does not actually affect the desktop window. You might want to add this from its documentation to the answer – Biesi Feb 11 '20 at 11:59
  • I upvoted cause I like it, the only one bad thing is the old text flashing when you add a new line – Marco Salerno Feb 11 '20 at 11:59
  • @BiesiGrr I know that the name can be a little confusing but "window" here doesn't mean the actual console window. I added an update to the answer to make that clear. – 41686d6564 stands w. Palestine Feb 11 '20 at 12:06
  • the downside of using `SetWindowPosition` is its limitation to the Windows platform. this is not working in .NetCore on Linux system yet (tested with Core3.1.1) – AliReza Sabouri Feb 11 '20 at 13:49
  • @AliReza Yes, that is documented. If the OS isn't Windows, you get a PlatformNotSupportedException. This question is tagged [.net], not [.net-core] though. – 41686d6564 stands w. Palestine Feb 11 '20 at 13:58