很抱歉各位看官,不太會排版丑陋了點,但是重點很清晰。
因本人的工作原因,大部分時間都在和控制台打交道,話說無論寫什么控制台處理程序都有進度顯示,方便直觀。假設如果僅使用文件方式記錄進度的話相當的麻煩,當然這個用作記錄日志的話另當別論了。本文為了方便查看處理進度而特意在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;
}
}
