[原創]ConsoleApplication ProgressBar


很抱歉各位看官,不太會排版丑陋了點,但是重點很清晰。

 

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

 

源碼:

  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;
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM