65.9K
CodeProject 正在变化。 阅读更多。
Home

ProgressCircle -ProgressBar 的替代方案

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.38/5 (6投票s)

2008年4月25日

CPOL

4分钟阅读

viewsIcon

47175

downloadIcon

2283

这是一个自定义控件,是 Visual Studio ProgressBar 组件的替代方案。

ProgressCircleBinary

引言

在本文中,我将向您展示一个自定义进度控件,我将其作为常规 Visual Studio ProgressBar 组件的替代方案。因此,我们将讨论

  • 如何创建自定义组件
  • 如何创建自定义事件和属性,以便在属性窗口中显示它们
  • 如何使用 Paint 事件和图形进行绘图以及如何使用渐变画笔

背景

自定义控件继承自 UserControlUserControl 有一个名为 Paint 的事件,每次需要重绘控件时都会调用该事件。我们将使用此事件来绘制进度。创建此组件非常容易:我们只需要绘制一个椭圆(这将是剩余时间)和一个扇形(这将是经过的时间),如下面的代码所示

e.Graphics.FillEllipse(t_oBrushRemainingTime, t_oRectangle);
e.Graphics.FillPie(t_oBrushElapsedTime, t_oRectangle, -90f,
   (float)(360 * m_iElapsedTime / m_iTotalTime));

大多数可以使用 Graphics 绘制的东西都需要一个矩形,它是绘制的边界。此矩形定义为与组件相同的大小。

Rectangle t_oRectangle = new Rectangle(0, 0, this.Width, this.Height);

为了创建渐变视觉效果,在绘制椭圆和扇形之前,定义了两个不同的画笔变量,以创建剩余时间和经过时间的不同视觉效果,如下所示

Brush t_oBrushRemainingTime = new LinearGradientBrush(t_oRectangle,
    m_oColor1RemainingTime, m_oColor2RemainingTime, m_eLinearGradientMode);
Brush t_oBrushElapsedTime = new LinearGradientBrush(t_oRectangle,
    m_oColor1ElapsedTime, m_oColor2ElapsedTime, m_eLinearGradientMode);

我们将跟踪两个变量:m_iElapsedTime(它保存实际值 - 与 ProgressBar 中的 Value 属性相同)和 m_iTotalTime(它保存时间量 - 与 ProgressBar 中的 Maximum 属性相同)。这两个变量用于计算表示经过时间的扇形的角度。众所周知,一个完整的圆有 360° 角。为了获得实际角度,我们只需进行 m_iElapsedTime / m_iTotalTime * 360。

编写的唯一方法是 Increment() 方法。它有一个整数作为参数,该整数是要添加到 m_iElapsedTime 的数字。但在此之前,我们只需检查 m_iElapsedTime 是否大于 m_iTotalTime。如果是,这意味着任务已完成,该方法返回。如果不是更大,则检查要添加的值加上 m_iElapsedTime 是否大于或等于 m_iTotalTime。如果是,我们使 m_iElapsedTime 等于 m_iTotalTime,更新控件并引发两个事件,PCIncrementedPCComplete。如果不是更大,我们递增 m_iElapsedTime,更新组件并引发 PCIncremented 事件。请参阅下面的代码

if (m_iElapsedTime > m_iTotalTime)
    return;

if (m_iElapsedTime + a_iValue >= m_iTotalTime)
{
    m_iElapsedTime = m_iTotalTime;
    this.Refresh();
    if (m_EventIncremented != null)
        m_EventIncremented(this, null);
    if (m_EventCompleted != null)
        m_EventCompleted(this, null);
}
else
{
    m_iElapsedTime += a_iValue;
    this.Refresh();
    if (m_EventIncremented != null)
        m_EventIncremented(this, null);
}

为了创建这些自定义事件(PCIncrementedPCComplete),我们创建了一个名为 EventHandler 的委托。有了这个委托,现在我们声明了两个类型为 EventHandler 的变量,分别名为 m_EventIncrementedm_EventCompleted,带有修饰符 event,如下所示

public delegate void EventHandler(object sender, string message);
public event EventHandler m_EventIncremented;
public event EventHandler m_EventCompleted;

要引发事件,我们只需要检查变量是否已初始化,然后调用它。请参见下文

if (m_EventCompleted != null)
    m_EventCompleted(this, null);

为了使这些事件可在属性窗口中的事件列表中浏览,我们需要为它们创建属性,并在其前面用括号括起来几个属性。主要的属性是 Category(),它设置了在分类顺序中显示时的类别。另一个属性是 Description(),它在属性窗口的底部显示简短的描述。两个自定义事件的属性及其各自的属性如下所示

[Category("ProgressCircle"), Description(
    "Event raised everytime the component is incremented." +
    "Author: Sergio Augusto Bitencourt Petrovcic")]
public event EventHandler PCIncremented
{
    add { m_EventIncremented += new EventHandler(value); }
    remove { m_EventIncremented -= new EventHandler(value); }
}

[Category("ProgressCircle"), Description(
    "Event raised when the component get completed." +
    "Author: Sergio Augusto Bitencourt Petrovcic")]
public event EventHandler PCCompleted
{
    add { m_EventCompleted += new EventHandler(value); }
    remove { m_EventCompleted -= new EventHandler(value); }
}

Using the Code

源代码有两个项目。第一个项目实现组件并生成一个程序集。第二个项目是一个测试项目,将第一个项目作为参考。因此,如果我们打开测试项目的主窗体并查看工具箱,我们将在那里看到该组件。我们只需要将其拖放到窗体中即可。

如果您想在自己的项目中使用此组件,您只需要将该组件添加到项目的工具箱中。只需右键单击工具箱,然后单击“选择项目”。然后单击“浏览”并搜索 ProgressCircle.dll。单击“打开”和“确定”。之后,只需将其拖放到您的窗体即可。

要配置组件,您可以使用属性窗口更改剩余时间和经过时间的渐变颜色,更改线性渐变模式,更改组件的总时间和经过时间,并设置事件。随着您的任务流程,只需调用 Increment() 并将要递增的值作为参数传递。就是这样!就这么简单。

历史

* 2008 年 4 月 - 首次发布。

版权所有 © 2007 Sergio A. B. Petrovcic。保留所有权利。未经我的明确许可,请勿发布到其他网站。根据本网站的政策和程序链接到本文。

© . All rights reserved.