Ответ 1
Вы можете перемещать курсор везде, где хотите: Console.SetCursorPosition или использовать Console.CursorTop.
Console.SetCursorPosition(0, Console.CursorTop -1);
Console.WriteLine("Over previous line!!!");
Я хотел бы добиться чего-то вроде этого:
Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OK
Я отобразил 3 строки текста, каждая из которых связана с потоком, который может закончиться рано или поздно. Но если вторая завершится позже третьей, я получу что-то вроде этого:
Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OKOK
Это, конечно, неприемлемо. Я знаю, как вернуться в текущей строке, но есть ли способ подняться? Я бы поклялся, что видел его где-то, хотя это может быть консоль Linux:)
Забудьте об этом. Смотрите Far File Manager! Он работает в консоли Windows, он работает даже в PowerShell! Как сделать что-то подобное? И самая крутая часть - это восстановление состояния консоли после выхода. Поэтому, возможно, я должен спросить - как напрямую обращаться к буферу консоли? Я предполагаю, что мне понадобится собственный код, чтобы сделать трюк, но, может быть, есть другой способ? Я думал о очистке консоли при каждом обновлении, но это похоже на излишний. Или, может быть, нет? Будет ли это мигать?
Вы можете перемещать курсор везде, где хотите: Console.SetCursorPosition или использовать Console.CursorTop.
Console.SetCursorPosition(0, Console.CursorTop -1);
Console.WriteLine("Over previous line!!!");
Используйте возврат каретки. Этот образец печатает одну строку, перезаписывая то, что было до этого.
Console.WriteLine();
for (int i = 0; i <= 100; i++)
{
System.Threading.Thread.Sleep(10);
Console.Write("\x000DProgress: " + i);
}
Это работает до тех пор, пока все ваши строки меньше 80 столбцов (или независимо от того, что ваш буфер терминала установлен).
Примечание: следующий ответ был первоначально отредактирован в вопросе OP.
Здесь полное решение с демо:
using System;
using System.Collections.Generic;
using System.Threading;
namespace PowerConsole {
internal class Containers {
internal struct Container {
public int Id;
public int X;
public int Y;
public string Content;
}
public static List<Container> Items = new List<Container>();
private static int Identity = 0;
public static int Add(string text) {
var c = new Container();
c.Id = Identity++;
c.X = Console.CursorLeft;
c.Y = Console.CursorTop;
c.Content = text;
Console.Write(text);
Items.Add(c);
return c.Id;
}
public static void Remove(int id) {
Items.RemoveAt(id);
}
public static void Replace(int id, string text) {
int x = Console.CursorLeft, y = Console.CursorTop;
Container c = Items[id];
Console.MoveBufferArea(
c.X + c.Content.Length, c.Y,
Console.BufferWidth - c.X - text.Length, 1,
c.X + text.Length, c.Y
);
Console.CursorLeft = c.X;
Console.CursorTop = c.Y;
Console.Write(text);
c.Content = text;
Console.CursorLeft = x;
Console.CursorTop = y;
}
public static void Clear() {
Items.Clear();
Identity = 0;
}
}
internal class Program {
private static List<Thread> Threads = new List<Thread>();
private static void Main(string[] args) {
Console.WriteLine("So we have some threads:\r\n");
int i, id;
Random r = new Random();
for (i = 0; i < 10; i++) {
Console.Write("Starting thread " + i + "...[");
id = Containers.Add("?");
Console.WriteLine("]");
Thread t = new Thread((object data) => {
Thread.Sleep(r.Next(5000) + 100);
Console.ForegroundColor = ConsoleColor.Green;
Containers.Replace((int)data, "DONE");
Console.ResetColor();
});
Threads.Add(t);
}
Console.WriteLine("\n\"But will it blend?\"...");
Console.ReadKey(true);
i = 0;
Threads.ForEach(t => t.Start(i++));
Threads.ForEach(t => t.Join());
Console.WriteLine("\r\nVoila.");
Console.ReadKey(true);
}
}
}