2012-05-29 18 views
18

me gustaría lograr algo como esto:¿Cómo modificar la línea anterior del texto de la consola?

Time consuming operation...OK 
Another time consuming operation... 
And another one, but it completed, so...OK 

me muestra 3 línea de texto, cada uno relacionado con un hilo que puede terminar más pronto o más tarde. Pero si el segundo complete a más tardar el tercero, voy a conseguir algo como esto:

Time consuming operation...OK 
Another time consuming operation... 
And another one, but it completed, so...OKOK 

que por supuesto es inaceptable. Sé cómo volver en la línea actual, pero ¿hay alguna manera de subir? Juraría que lo he visto en alguna parte, aunque podría ser una consola Linux :)

Olvídalo. ¡Vea el administrador de archivos lejanos! Funciona en la consola de Windows, ¡funciona incluso en PowerShell! ¿Cómo hacer algo como esto? Y la mejor parte es que restablece el estado de la consola después de salir. Entonces, tal vez debería preguntar: ¿cómo acceder al buffer de la consola directamente? Supongo que necesitaré algún código nativo para hacer el truco, pero ¿tal vez hay otra manera? Pensé en borrar la consola con cada actualización, pero esto parece excesivo. O tal vez no es? ¿Parpadeará?

+0

hubiera sido agradable si se hubiera incluido la manera de "volver atrás en la línea actual", y no sólo decir que usted lo sepa. Así es como lo hice: 'Console.SetCursorPosition (0, Console.CursorTop);' Sé que no es directamente parte de la pregunta, pero está relacionado, y esta es la pregunta que encontré cuando la busqué. –

Respuesta

48

Puede mover el cursor donde quiera: Console.SetCursorPosition o use Console.CursorTop.

Console.SetCursorPosition(0, Console.CursorTop -1); 
Console.WriteLine("Over previous line!!!"); 
+1

Sí. Eso es todo. Ahora estoy haciendo una clase para agregar contenedores como DIVs en HTML al texto de la consola. Recordará la posición de cada contenedor para poder cambiarlo más tarde. Ahora puedo finalmente terminar mi servidor :) Bueno, todavía es un inserto para hacer, pero allí Console.MoveBufferArea será útil. Gracias. – Harry

4

Utilice un retorno de carro. Esta muestra imprime una sola línea, sobrescribiendo lo que estaba allí antes.

Console.WriteLine(); 
    for (int i = 0; i <= 100; i++) 
    { 
    System.Threading.Thread.Sleep(10); 
    Console.Write("\x000DProgress: " + i); 
    } 

Esto funciona siempre y cuando todas las cadenas son menos de 80 columnas (o lo que su buffer del terminal está en).

+1

Supongo que esto solo funciona en Windows, pero no lo he probado en mono. –

+1

Funciona bien, pero no se puede usar para modificar líneas hacia arriba. Sin embargo, es una forma simple de hacer una única barra de progreso o porcentaje de actualización. – Harry

+1

'\ r' también funciona en lugar de' \ x000D'. – jnm2

1

Nota: la respuesta siguiente fue editada originalmente en la pregunta por el OP.


Aquí es solución completa con demostración:

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); 
     } 
    } 
} 
+1

Works lekker, solo tiene que agregar una línea más al final en el método 'Replace'' Items [id] = c; '. Esto resolverá el problema de reemplazo continuo donde los personajes comienzan a rodar con valores incorrectos. – Pierre

+1

@Pierre ¡Gracias por tu comentario! No he verificado el código para la corrección, por lo que es posible que haya algunos problemas con él. – Stijn

Cuestiones relacionadas