【发布时间】:2011-06-30 21:26:15
【问题描述】:
我想知道是否可以暂停,然后在 c# .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;
}
}
}
注意:不支持退格,自己画光标可能会更好
【问题讨论】:
-
Console.OutputEncoding = System.Text.Encoding.GetEncoding(1252);
标签: c# .net multithreading interop console