控制台进度条

  今天在整理资料的时候,翻出多年前在网上看到的一篇帖子,一个控制台的进度条,非常酷炫,原文出处-传送门

     记得在刚开始接触编程的时候,用控制台写些小工具玩,也喜欢将信息打印到屏幕上,看着不断闪动的屏幕觉得很酷,后来一次偶然的机会看到了这个进度条让控制台的输出又上了一个层次,感谢作者。

 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.WriteLine("Contiue?(y/n)");
                string s=Console.ReadLine();
                if (s.Equals("n",StringComparison.InvariantCultureIgnoreCase))
                    break;
            }
        }
 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;
        }
    }

      

原文地址:https://www.cnblogs.com/jingsha/p/6103228.html