Можно приостановить, кешировать, сбросить ввод с клавиатуры в консоли c # .net? - PullRequest
3 голосов
/ 01 июля 2011

Мне было интересно, можно ли сделать паузу, а затем кэшировать и сбросить ввод с клавиатуры в консоли ac # .net.Например, представьте, что я создаю поток, который устанавливает позицию курсора консоли, пишет символы для рисования доски для индикатора выполнения (символы ANSI), и, когда процент выполнения фоновых задач изменяется, поток снова меняет положение курсора для добавлениядругая полоса внутри индикатора выполнения, и курсор возвращается в исходное положение.В то же время, как это происходит, я хочу, чтобы исходный поток обрабатывал Console.ReadLine ();Мне интересно, есть ли в любом случае, что я могу приостановить, затем кэшировать и сбросить ввод с клавиатуры, или есть ли способ поддержки двунаправленного ввода без побочных эффектов.Вот пример: вы заметите, что если вы удерживаете клавишу нажатой, она начинает работать.

public void DrawScreenBackground()
{
    List<ConsoleColor> ColourArray = new List<ConsoleColor>();
    //ColourArray.Add(ConsoleColor.Black);
    ColourArray.Add(ConsoleColor.DarkGray);
    ColourArray.Add(ConsoleColor.DarkGreen);
    ColourArray.Add(ConsoleColor.Green);
    ColourArray.Add(ConsoleColor.Green);
    ColourArray.Add(ConsoleColor.DarkGreen);
    ColourArray.Add(ConsoleColor.DarkGray);

    int minProgress = 0;
    int maxProgress = 20;
    int currentProgress = minProgress;
    bool reverse = false;
    while (1 == 1)
    {
        if (!reverse)
        {
            if (currentProgress == maxProgress)
                reverse = !reverse;
            else
                currentProgress += 1;
        }
        else
        {
            if (currentProgress == minProgress)
                reverse = !reverse;
            else
                currentProgress -= 1;
        }
        //draw/////
        int curLeft = Console.CursorLeft;
        int curTop = Console.CursorTop;
        ConsoleColor defaultColor = Console.ForegroundColor;
        ConsoleColor item = ColourArray[0];
        ColourArray.RemoveAt(0);
        ColourArray.Insert(ColourArray.Count-1, item);
        DrawDoubleBorder(9, 9, 21, 2);
        Console.ForegroundColor = item;
        Console.SetCursorPosition(10, 10);
        for (int i = 0; i < maxProgress - minProgress; i += 1)
            Console.Write(" ");
        Console.SetCursorPosition(10, 10);
        for (int i = 0; i < currentProgress - minProgress; i += 1)
            Console.Write("#");
        Console.ForegroundColor = defaultColor;
        Console.SetCursorPosition(curLeft, curTop);
        ///////////
        Thread.Sleep(125);
    }
}
private void DrawDoubleBorder(int x, int y, int width, int height)
{
    Console.SetCursorPosition(x, y);
    int currentX = x;
    int currentY = y;
    for (int h = 0; h <= height; h += 1)
    {
        for (int w = 0; w <= width; w += 1)
        {
            if (w == 0 && h == 0)
                Console.Write(ConsoleChars.DoubleBorderTopLeft);
            else if (w == width && h == height)
                Console.Write(ConsoleChars.DoubleBorderBottomRight);
            else if (w == width && h == 0)
                Console.Write(ConsoleChars.DoubleBorderTopRight);
            else if (w == 0 && h == height)
                Console.Write(ConsoleChars.DoubleBorderBottomLeft);
            else if (w == 0 || w == width)
                Console.Write(ConsoleChars.DoubleBorderVerticle);
            else if (h == 0 || h == height)
                Console.Write(ConsoleChars.DoubleBorderHorizontal);
            else
                Console.Write(" ");
        }
        currentY += 1;
        Console.SetCursorPosition(currentX, currentY);
    }
}
public struct ConsoleChars
{
    public static char DoubleBorderHorizontal = (char)205;
    public static char DoubleBorderVerticle = (char)186;
    public static char DoubleBorderBottomLeft = (char)200;
    public static char DoubleBorderTopRight = (char)187;
    public static char DoubleBorderBottomRight = (char)188;
    public static char DoubleBorderFourWaySplit = (char)206;
    public static char DoubleBorderTopLeft = (char)201;
    public static char DoubleBorderLeftThreeWaySplit = (char)204;
    public static char DoubleBorderRightThreeWaySplit = (char)185;
}

        Thread thread = new Thread(new ThreadStart(DrawScreenBackground));
        thread.Start();
        Console.ReadLine();

РЕДАКТ.using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { Console.OutputEncoding = System.Text.Encoding.GetEncoding(1252); Thread thread = new Thread(new ParameterizedThreadStart(DrawScreenBackground)); object locker = new object(); thread.Start(locker); string input = string.Empty; while(!input.Contains("\r\n")) { string temp = FlushKeyBoardInput(); if(temp!=string.Empty) { lock(locker) { Console.Write(temp); input+=temp; } } } } public static string FlushKeyBoardInput() { string output = string.Empty; while (Console.KeyAvailable) { ConsoleKeyInfo key = Console.ReadKey(true); output += key.KeyChar; } return output; } public static void DrawScreenBackground(object locker) { List<ConsoleColor> ColourArray = new List<ConsoleColor>(); //ColourArray.Add(ConsoleColor.Black); ColourArray.Add(ConsoleColor.DarkGray); ColourArray.Add(ConsoleColor.DarkGreen); ColourArray.Add(ConsoleColor.Green); ColourArray.Add(ConsoleColor.Green); ColourArray.Add(ConsoleColor.DarkGreen); ColourArray.Add(ConsoleColor.DarkGray); int minProgress = 0; int maxProgress = 20; int currentProgress = minProgress; bool reverse = false; while (1 == 1) { if (!reverse) { if (currentProgress == maxProgress) reverse = !reverse; else currentProgress += 1; } else { if (currentProgress == minProgress) reverse = !reverse; else currentProgress -= 1; } //draw///// lock (locker) { int curLeft = Console.CursorLeft; int curTop = Console.CursorTop; ConsoleColor defaultColor = Console.ForegroundColor; ConsoleColor item = ColourArray[0]; ColourArray.RemoveAt(0); ColourArray.Insert(ColourArray.Count - 1, item); DrawDoubleBorder(9, 9, 21, 2); Console.ForegroundColor = item; Console.SetCursorPosition(10, 10); for (int i = 0; i < maxProgress - minProgress; i += 1) Console.Write(" "); Console.SetCursorPosition(10, 10); for (int i = 0; i < currentProgress - minProgress; i += 1) Console.Write("#"); Console.ForegroundColor = defaultColor; Console.SetCursorPosition(curLeft, curTop); /////////// } Thread.Sleep(50); } } public static void DrawDoubleBorder(int x, int y, int width, int height) { Console.SetCursorPosition(x, y); int currentX = x; int currentY = y; for (int h = 0; h <= height; h += 1) { for (int w = 0; w <= width; w += 1) { if (w == 0 && h == 0) Console.Write(ConsoleChars.DoubleBorderTopLeft); else if (w == width && h == height) Console.Write(ConsoleChars.DoubleBorderBottomRight); else if (w == width && h == 0) Console.Write(ConsoleChars.DoubleBorderTopRight); else if (w == 0 && h == height) Console.Write(ConsoleChars.DoubleBorderBottomLeft); else if (w == 0 || w == width) Console.Write(ConsoleChars.DoubleBorderVerticle); else if (h == 0 || h == height) Console.Write(ConsoleChars.DoubleBorderHorizontal); else Console.Write(" "); } currentY += 1; Console.SetCursorPosition(currentX, currentY); } } public struct ConsoleChars { public static char DoubleBorderHorizontal = (char)205; public static char DoubleBorderVerticle = (char)186; public static char DoubleBorderBottomLeft = (char)200; public static char DoubleBorderTopRight = (char)187; public static char DoubleBorderBottomRight = (char)188; public static char DoubleBorderFourWaySplit = (char)206; public static char DoubleBorderTopLeft = (char)201; public static char DoubleBorderLeftThreeWaySplit = (char)204; public static char DoubleBorderRightThreeWaySplit = (char)185; } } } примечание: не поддерживает возврат и может быть лучше нарисовать курсор самостоятельно

1 Ответ

4 голосов
/ 01 июля 2011

Не используйте Console.ReadLine() или Console.Read(). Скорее посмотрите на Console.ReadKey() и Console.KeyAvailable()

Очистить очередь клавиатуры так же просто, как:

public void FlushKeyBoardInput()
{
  while ( Console.KeyAvailable )
  {
    ConsoleKeyInfo key = Console.ReadKey() ;
  }
}

Console.ReadKey() даже имеет перегрузку, которая позволяет вам контролировать, отображается ли клавиша на экране.

Что касается приостановки или кэширования ввода с клавиатуры, сама командная оболочка имеет определенное количество буфера клавиатуры, но вы хотите перетаскивать нажатия клавиш в очередь, не выводя их на экран в качестве кэша, и записывать свои методы ввода читать из кеша перед извлечением из реальной клавиатуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...