很抱歉各位看官,不太会排版丑陋了点,但是重点很清晰。
因本人的工作原因,大部分时间都在和控制台打交道,话说无论写什么控制台处理程序都有进度显示,方便直观。假设如果仅使用文件方式记录进度的话相当的麻烦,当然这个用作记录日志的话另当别论了。本文为了方便查看处理进度而特意在ConsoleApplication ProgressBar花了1个小时而开发的一个进度条控件类。
首先例举两个个常用的记录进度方式:
1、Console.Write
如图:
这种是最常见的,没什么好不好之说,但是不好的地方显而易见:屏幕一刷而过,当有其他的信息需要打印的时候还得翻滚动条。如果进度太长就无奈了。
2、Console.Title
如图:

这个用的相对比较少,如果开的比较多控制台的话,Title上原本的信息就没有了。
3、ConsoleApplication ProgressBar
如图:


综合前面两种方式,后者是最为方便的。好处我想不用我多说了。
下面奉上源码
调用示例:
class Program
{
static void Main( string[] args)
{
Random r = new Random();
while ( true)
{
ConsoleProgressBar bar = new ConsoleProgressBar( " 测试ConsoleApplication ProgressBar ");
int c = r.Next( 534);
for ( int i = 1; i <= c; i++)
{
bar.Update(i, c, string.Format( " 完成进度:{0}/{1} ", i, c));
System.Threading.Thread.Sleep( 10);
}
// 等待退出
Console.ReadKey( true);
}
}
}
{
static void Main( string[] args)
{
Random r = new Random();
while ( true)
{
ConsoleProgressBar bar = new ConsoleProgressBar( " 测试ConsoleApplication ProgressBar ");
int c = r.Next( 534);
for ( int i = 1; i <= c; i++)
{
bar.Update(i, c, string.Format( " 完成进度:{0}/{1} ", i, c));
System.Threading.Thread.Sleep( 10);
}
// 等待退出
Console.ReadKey( true);
}
}
}
源码:
public
class ConsoleProgressBar
{
int left = 0;
int backgroundLength = 50;
#region [ window api ]
ConsoleColor colorBack = Console.BackgroundColor;
ConsoleColor colorFore = Console.ForegroundColor;
private const int STD_OUTPUT_HANDLE = - 11;
private int mHConsoleHandle;
COORD barCoord;
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public COORD( short x, short y)
{
X = x;
Y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
struct SMALL_RECT
{
public short Left;
public short Top;
public short Right;
public short Bottom;
}
[StructLayout(LayoutKind.Sequential)]
struct CONSOLE_SCREEN_BUFFER_INFO
{
public COORD dwSize;
public COORD dwCursorPosition;
public int wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
}
[DllImport( " kernel32.dll ", EntryPoint = " GetStdHandle ", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int GetStdHandle( int nStdHandle);
[DllImport( " kernel32.dll ", EntryPoint = " GetConsoleScreenBufferInfo ", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int GetConsoleScreenBufferInfo( int hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
[DllImport( " kernel32.dll ", EntryPoint = " SetConsoleCursorPosition ", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetConsoleCursorPosition( int hConsoleOutput, COORD dwCursorPosition);
public void SetCursorPos( short x, short y)
{
SetConsoleCursorPosition(mHConsoleHandle, new COORD(x, y));
}
public COORD GetCursorPos()
{
CONSOLE_SCREEN_BUFFER_INFO res;
GetConsoleScreenBufferInfo(mHConsoleHandle, out res);
return res.dwCursorPosition;
}
#endregion
public ConsoleProgressBar( string title, int left = 10)
{
Console.WriteLine();
// 获取当前窗体句柄
mHConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// 获取当前窗体偏移量
barCoord = this.GetCursorPos();
this.left = left;
// 获取字符长度
int len = GetStringLength(title);
// 设置标题的相对居中位置
Console.SetCursorPosition(left + (backgroundLength / 2 - len), barCoord.Y);
Console.Write(title);
// 写入进度条背景
Console.BackgroundColor = ConsoleColor.DarkCyan;
Console.SetCursorPosition(left, barCoord.Y + 1);
for ( int i = 0; ++i <= backgroundLength; )
Console.Write( " ");
Console.WriteLine();
Console.BackgroundColor = colorBack;
}
/// <summary>
/// 更新进度条
/// </summary>
/// <param name="current"> 当前进度 </param>
/// <param name="total"> 总进度 </param>
/// <param name="message"> 说明文字 </param>
public void Update( int current, int total, string message)
{
// 计算百分比
int i = ( int)Math.Ceiling(current / ( double)total * 100);
Console.BackgroundColor = ConsoleColor.Yellow;
Console.SetCursorPosition(left, barCoord.Y + 1);
// 写入进度条
StringBuilder bar = new StringBuilder();
// 当前百分比*进度条总长度=要输出的进度最小单位数量
int count = ( int)Math.Ceiling(( double)i / 100 * backgroundLength);
for ( int n = 0; n < count; n++) bar.Append( " ");
Console.Write(bar);
// 设置和写入百分比
Console.BackgroundColor = colorBack;
Console.ForegroundColor = ConsoleColor.Green;
Console.SetCursorPosition(left + backgroundLength, barCoord.Y + 1);
Console.Write( " {0}% ", i);
Console.ForegroundColor = colorFore;
// 获取字符长度
int len = GetStringLength(message);
// 获取相对居中的message偏移量
Console.SetCursorPosition(left + (backgroundLength / 2 - len), barCoord.Y + 2);
Console.Write(message);
// 进度完成另起新行作为输出
if (i >= 100) Console.WriteLine();
}
/// <summary>
/// 获取字符长度
/// </summary>
/// <remarks> 中文和全角占长度1,英文和半角字符2个字母占长度1 </remarks>
/// <param name="message"></param>
/// <returns></returns>
private int GetStringLength( string message)
{
int len = Encoding.ASCII.GetBytes(message).Count(b => b == 63);
return (message.Length - len) / 2 + len;
}
}
{
int left = 0;
int backgroundLength = 50;
#region [ window api ]
ConsoleColor colorBack = Console.BackgroundColor;
ConsoleColor colorFore = Console.ForegroundColor;
private const int STD_OUTPUT_HANDLE = - 11;
private int mHConsoleHandle;
COORD barCoord;
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public COORD( short x, short y)
{
X = x;
Y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
struct SMALL_RECT
{
public short Left;
public short Top;
public short Right;
public short Bottom;
}
[StructLayout(LayoutKind.Sequential)]
struct CONSOLE_SCREEN_BUFFER_INFO
{
public COORD dwSize;
public COORD dwCursorPosition;
public int wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
}
[DllImport( " kernel32.dll ", EntryPoint = " GetStdHandle ", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int GetStdHandle( int nStdHandle);
[DllImport( " kernel32.dll ", EntryPoint = " GetConsoleScreenBufferInfo ", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int GetConsoleScreenBufferInfo( int hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
[DllImport( " kernel32.dll ", EntryPoint = " SetConsoleCursorPosition ", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetConsoleCursorPosition( int hConsoleOutput, COORD dwCursorPosition);
public void SetCursorPos( short x, short y)
{
SetConsoleCursorPosition(mHConsoleHandle, new COORD(x, y));
}
public COORD GetCursorPos()
{
CONSOLE_SCREEN_BUFFER_INFO res;
GetConsoleScreenBufferInfo(mHConsoleHandle, out res);
return res.dwCursorPosition;
}
#endregion
public ConsoleProgressBar( string title, int left = 10)
{
Console.WriteLine();
// 获取当前窗体句柄
mHConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// 获取当前窗体偏移量
barCoord = this.GetCursorPos();
this.left = left;
// 获取字符长度
int len = GetStringLength(title);
// 设置标题的相对居中位置
Console.SetCursorPosition(left + (backgroundLength / 2 - len), barCoord.Y);
Console.Write(title);
// 写入进度条背景
Console.BackgroundColor = ConsoleColor.DarkCyan;
Console.SetCursorPosition(left, barCoord.Y + 1);
for ( int i = 0; ++i <= backgroundLength; )
Console.Write( " ");
Console.WriteLine();
Console.BackgroundColor = colorBack;
}
/// <summary>
/// 更新进度条
/// </summary>
/// <param name="current"> 当前进度 </param>
/// <param name="total"> 总进度 </param>
/// <param name="message"> 说明文字 </param>
public void Update( int current, int total, string message)
{
// 计算百分比
int i = ( int)Math.Ceiling(current / ( double)total * 100);
Console.BackgroundColor = ConsoleColor.Yellow;
Console.SetCursorPosition(left, barCoord.Y + 1);
// 写入进度条
StringBuilder bar = new StringBuilder();
// 当前百分比*进度条总长度=要输出的进度最小单位数量
int count = ( int)Math.Ceiling(( double)i / 100 * backgroundLength);
for ( int n = 0; n < count; n++) bar.Append( " ");
Console.Write(bar);
// 设置和写入百分比
Console.BackgroundColor = colorBack;
Console.ForegroundColor = ConsoleColor.Green;
Console.SetCursorPosition(left + backgroundLength, barCoord.Y + 1);
Console.Write( " {0}% ", i);
Console.ForegroundColor = colorFore;
// 获取字符长度
int len = GetStringLength(message);
// 获取相对居中的message偏移量
Console.SetCursorPosition(left + (backgroundLength / 2 - len), barCoord.Y + 2);
Console.Write(message);
// 进度完成另起新行作为输出
if (i >= 100) Console.WriteLine();
}
/// <summary>
/// 获取字符长度
/// </summary>
/// <remarks> 中文和全角占长度1,英文和半角字符2个字母占长度1 </remarks>
/// <param name="message"></param>
/// <returns></returns>
private int GetStringLength( string message)
{
int len = Encoding.ASCII.GetBytes(message).Count(b => b == 63);
return (message.Length - len) / 2 + len;
}
}