© 2012 Conmajia, 2011 Graham Wilson
SN: 125.2
本文为 CodeProject 2011 年 4 月号最佳 C# 文章获奖作品。本中文版翻译已获原作者 Graham Wilson 首肯。
简介
本文介绍一款有趣的进度条控件(ProgressBar)。如下演示,这款名为“超赞进度条”的控件可以直接平替传统的 WinForm 原生进度条控件。
本文提供了 2.0.0 版本的类库,包含控件库本体和一个便捷的编辑器。读者可以下载后通过该编辑器获取所需效果并生成最终代码。
可下载内容:
- 超赞进度条演示程序及编辑器
- 超赞进度条类库文件
- 超赞进度条源代码
超赞进度条使用 .NET Framework 3.5,4.6.2 和 6.0 编译完成。所有的公共和私有类、方法及属性都使用标准 C# XML 文档注释进行了完整的文档记录。项目文件中附带了 .chm 和 .mshc 格式的帮助文件(英文)。有关使用该类的更多详细信息,请参阅帮助文件中的概述部分。
演示程序及编辑器文件(AmazingProgressBar2_200_Demo.zip)中包含以下文件。
GAW.AmazingProgressBar2.Net462.dll
以 .NET 4.6.2 编译的库文件GAW.AmazingProgressBar2.ExplorerApp.Net462.exe
超赞进度条编辑器GAW.AmazingProgressBar2.ExamplesApp.Net462.exe
超赞进度条演示程序GAW.SimpleWidgets2.Net462.dll
以 .NET 4.6.2 编译的 SimpleWidgets2 库
背景
某日,我苦等一个漫长的计算任务,百无聊赖地看着进度条在屏幕上缓缓蠕动。我突然意识到这个标准的进度条是多么无趣(参见图 1——译者注)。在思考这个问题一段时间后,我想到了一个穿越迷宫的进度条想法。于是,超赞进度条就此诞生。
如何使用
使用超赞进度条非常简单,只需将在界面窗体上添加 AmazingProgressBar2
类的实例即可。
AmazingProgressBar2 amaze = new AmazingProgressBar2();
amaze.Location = new System.Drawing.Point(0, 0);
amaze.Size = new System.Drawing.Size(200, 50);
form.Controls.Add(amaze);
你可以直接用 AmazingProgressBar2
平替任何已有的 ProgressBar
(传统进度条)。进度条填充方向和样式由 MazeStyle
属性决定,各效果如下。
SingleRight
SingleLeft
SingleUp
SingleDown
SplitConvergeHorizontal
SplitConvergeVertical
SplitDivergeHorizontal
SplitDivergeVertical
每个迷宫都应该有一条可以穿越的路线,但如果设定的 RowCount
大于 3,生成的迷宫可能会出现少量岔路。迷宫的总方向由 MazeStyle
指定,实际填充进度的时候会有转弯和回头。
迷宫的大小和复杂程度通常取决于 RowCount
参数,设置这个参数以固定迷宫中的行数。RowCount = 1
的结果是一个单行迷宫,看起来就像传统的进度条。RowCount = 2
将生成一个明显无趣的迷宫。强烈推荐使用 3 或更高的值。
迷宫中的列数是考虑到控件的大小、当前的 RowCount
、WallSize
和 BorderSize
的值,以及迷宫中所有单元格必须是正方形的规则下的最大值。
ProgressBar.Style
属性仍然可以设置。Marquee
样式按预期工作,但如果迷宫长度过长,可能不会像预期的那样快。Blocks
样式通常在视觉上不如 Continuous
那样吸引人,尽管将 Blocks
与零宽度的 WallSize
结合使用会产生有趣的效果。
以下代码段展示了如何设置 Style
、MazeStyle
以及行数。
// 假设超赞进度条实例 amaze 已经初始化
amaze.Style = ProgressBarStyle.Continous;
amaze.MazeStyle = AmazingProgressBarMazeStyle.SingleLeft;
amaze.RowCount = 4;
如果控件无法生成迷宫,则控件会被填充为粉红色与黑色的波纹图案(图 2)。这通常是由于 RowCount
设置得太高或太低所导致的。
迷宫内填充的单元格可以是固定的同一颜色,也可以遵循颜色渐变。这由 ColorStyle
属性决定:
ForeColor
:所有填充的单元格都是ForeColor
。GradientRows
:迷宫中的每一行都是不同的颜色,沿着渐变展开,第一行是GradientColors
中的第一种颜色,最后一行是GradientColors
中的最后一种颜色。GradientColumns
:迷宫中的每一列都是不同的颜色,沿着渐变展开,第一列是GradientColors
中的第一种颜色,最后一列是GradientColors
中的最后一种颜色。GradientFlow
:迷宫中的每个单元格都是不同的颜色,沿着渐变展开,第一个单元格是GradientColors
中的第一种颜色,最后一个单元格是GradientColors
中的最后一种颜色。
所有未填充的单元格始终是 BackColor
。
如果 WallSize
大于零,则迷宫墙壁可见。墙壁只能是 WallColor
属性指示的一个固定颜色。
迷宫边框可以是一个固定颜色,或者是从那个固定颜色到默认控件颜色的渐变。迷宫边框也可以有圆角。
以下代码段展示了如何设置各种颜色属性。
// 假设超赞进度条实例 amaze 已经初始化
amaze.Gradient = GradientType.Rows;
amaze.ForeColor = Color.LightBlue;
amaze.BorderSize = 2;
amaze.BorderColor = Color.LightGreen;
amaze.BorderGradient = false;
amaze.BorderRoundCorners = true;
amaze.BackColor = Color.White;
如何生成迷宫
有许多方法可以生成迷宫。这个控件需要一种算法,能够快速且内存开销有限地生成在特定方向上流动、分支最少的迷宫。
SimpleMap
类就是为这个目的而设。它是一个静态类,用于生成仅在指定方向上有一条路线的迷宫。大多数情况下它工作得很好,但对于 RowCount
大于 3 的值,它偶尔会错过一些单元格,导致迷宫中出现分支。
以下是生成单路径迷宫的指令。所使用的方向——向前、向后和侧向——取决于方向参数。例如,如果方向是 Dir.E
,那么向前就是东,向后就是西,侧向就是北或南。
从最后方的角落单元格之一开始。反复遵循以下规则(按顺序)来确定下一个单元格。当所有方向都被阻挡时停止。
- 如果只有一个方向可能,就往那个方向走。
- 如果可以向后走,就走那个方向。
- 如果在侧向方向只有一个空单元格,就往那个方向走。
- 如果在两个侧向方向都有不止一个空单元格,随机选择其中一个方向。
- 从可用的方向中随机选择一个方向;但你只能向前走,如果:
- 在侧边边缘,
- 距最前端超过两步,
- 最后方填充的列不超过三步向后。
规则 2 和 5 的目的是确保迷宫在回绕前不会走得太远。
一旦到达所有方向都被阻挡的单元格,上述规则就不再适用。此时,对于每个未使用的单元格:随机选择一个方向并使该方向可通行。这将导致迷宫中出现分支,但它确保没有跳过或未使用的单元格。
许可
本文及其附带文件、代码以 CPOL 许可 发布。
© 2012 Conmajia, 2011 Graham Wilson