• [原创]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;
            }
        }

     

  • 相关阅读:
    WINDOWPOS结构
    HTML 4.01 符号实体
    建立窗体时所响应的消息
    如何用正确的方法来写出质量好的软件的75条体会
    Onload加载多个方法函数
    UML中的一些概念
    aop应用范围
    如何成为“10倍效率”开发者
    网页引入taglibs
    XML编程—CRUD
  • 原文地址:https://www.cnblogs.com/xuyi/p/2738911.html
Copyright © 2020-2023  润新知