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

AnimatedIcon 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (20投票s)

2004年6月22日

3分钟阅读

viewsIcon

103587

downloadIcon

5133

AnimatedIcon 控件将动画作为存储在 ImageList 中的一系列图像播放。 本文演示了如何在 StatusBar 上显示动画图标。

AnimatedIcon Demo

引言

当我开始开发 Web 服务时,我研究了显示当前活动的可能性。 例如,当应用程序从 Internet 加载内容时,您可以显示沙漏或进度条。 进度条不够好,因为应用程序不知道它的真实状态:加载了多少以及还剩多少。 当然,您可以编写一个异步监视器来获取真实状态,但这会严重加载您的 Web 服务。 无论如何,我希望有一个简单的动画控件可以在 StatusBar 或任何地方显示动画图标。

您知道,.NET Framework 库中有一个 ImageAnimator 类,用于显示动画 GIF 文件。 它不适合我,因为

  • 我想在设计时从位图组成动画。
  • 我想为动画设置速度。

这就是我写了一个小而简单的控件的原因。

代码内部

AnimatedIcon 是一个 UserControl,具有几个属性和方法。 看看这个类(一些私有成员被隐藏)

AnimatedIcon Class

属性

五个属性定义了控件的外观和行为

  • ImageList

    ImageList 包含用于显示动画的图像。

  • 延迟

    帧之间的延迟(以毫秒为单位)。 默认值为 50 毫秒。

  • Pause

    每次循环后的暂停时间(以毫秒为单位)。 默认值为 0。

  • 循环次数

    要显示的循环次数。 默认值为 0。这意味着无限循环。

  • 第一帧

    动画的第一帧。

  • 最后一帧

    动画的最后一帧。

Pause 属性可用于在循环结束时设置延迟(感谢 Tim 的想法)。 FirstFrameLastFrame 默认分别设置为 0 和 ImageList.Images.Count-1。 但是,您可以为动画设置另一组帧。 例如,如果您将图像添加到 ImageList 以显示对象的某些特殊状态,甚至另一个动画。

方法

这些方法不言自明

  • StartAnimation

    从头开始启动动画。

  • StopAnimation

    停止动画。

  • ShowFrame

    停止动画并显示指定的帧。

代码

StartAnimation 创建一个 Thread,负责控件的逻辑。 StopAnimation 终止此线程。 threadFunc 计算帧数,并在帧更改时发送信号以重绘帧。

   // Starts animation from the beginning.
   public void StartAnimation()
   {
      StopAnimation();
      CheckRange();  // Check the first and the last frames
      thread = new Thread( new ThreadStart( threadFunc ) );
      thread.IsBackground = true;
      thread.Start();
   }

   // Stops animation not changing current frame number.
   public void StopAnimation()
   {
      if( thread != null )
      {
         thread.Abort();
         thread = null;
      }
      currentLoop = 0;
   }

   // Displays the specified frame.
   public void ShowFrame(int frame)
   {
      StopAnimation();

      if( frame >= 0 && imageList != null 
              && frame < imageList.Images.Count )
         currentFrame = frame;
      else
         currentFrame = 0;

      Refresh();
   }

   // Occurs when the control is redrawn.
   protected override void OnPaint(PaintEventArgs e)
   {
      // Draw a crossed rectangle if there is no frame to display

      if( imageList == null ||
         currentFrame < 0 || 
         currentFrame >= imageList.Images.Count )
      {
         if( this.Size.Width == 0 || this.Size.Height == 0 )
            return;

         Pen pen = new Pen( SystemColors.ControlText );
         e.Graphics.DrawRectangle( pen, 0, 0, 
               this.Size.Width-1, this.Size.Height-1 );
         e.Graphics.DrawLine( pen, 0, 0, 
                   this.Size.Width, this.Size.Height );
         e.Graphics.DrawLine( pen, 0, 
            this.Size.Height-1, this.Size.Width-1, 0 );
         pen.Dispose();
      }
      else
      {
         // Draw the current frame

         e.Graphics.DrawImage( imageList.Images[currentFrame], 
                               0, 0, this.Size.Width, this.Size.Height );
      }
   }

   // The method to be invoked when the thread begins executing.
   private void threadFunc()
   {
      bool wasPause = false;
      currentFrame = firstFrame;

      while( thread != null && thread.IsAlive )
      {
         Refresh();                     // Redraw the current frame
         wasPause = false;

         if( imageList != null )
         {
            currentFrame++;
            if( currentFrame > lastFrame ||
                currentFrame >= imageList.Images.Count )
            {
               if( pause > 0 )          // Sleep after every loop
               {
                  Thread.Sleep( pause );
                  wasPause = true;
               }

               currentFrame = firstFrame;
               if( loopCount != 0 )     // 0 is infinitive loop
               {
                  currentLoop++;
               }
            }
            if( loopCount != 0 && currentLoop >= loopCount )
            {
               StopAnimation();         // The loop is completed
            }
         }
         if( !wasPause ) // That prevents summation (pause + delayInterval)
            Thread.Sleep( delayInterval );
      }
   }

使用 AnimatedIcon

首先,您应该将 AnimatedIcon 控件添加到 Visual Studio .NET IDE 的工具箱中。 为此,您应该

  • 右键单击工具箱中的“Windows 窗体”选项卡。
  • 选择“添加/删除项目...” 。
  • 在“.NET Framework 组件”上,按“浏览...”按钮,找到 AnimatedIcon.dll。

新的 AnimatedIcon 控件将被添加到工具箱中

Toolbox

现在,您可以将此控件从工具箱拖到您的 Form 上。 这将在您的项目中创建一个新的 AnimatedIcon 对象。 默认情况下,它的 ImageList 为空,并且控件显示为交叉方块。 选择此对象并修改其属性:设置包含一系列帧的 ImageList,设置延迟和循环计数器。

Properties

别忘了在某个地方调用 StartAnimation() 方法。 编译您的项目并享受!

StatusBar 上的 AnimatedIcon

如果您运行我的演示,您将在 StatusBar 上看到一个小动画图标。 我将告诉您如何做到这一点。 它不能在设计器中完成,但手动操作非常容易。 首先,在您的 Form 类中创建一个私有成员

   private AnimatedIcon.AnimatedIcon animatedIcon2;

然后将几行代码添加到 Form 的构造函数中

   public Form1()
   {
      InitializeComponent();

      // This code adds the AnimatedIcon to the StatusBar

      this.animatedIcon2 = new AnimatedIcon.AnimatedIcon();
      this.animatedIcon2.Delay = 200;
      this.animatedIcon2.ImageList = this.imageList2;
      this.animatedIcon2.Name = "animatedIcon2";
      this.animatedIcon2.TabStop = false;
      this.animatedIcon2.Location = new Point(190, 
          (statusBar1.Height - animatedIcon2.Size.Height)/2);

      statusBar1.Controls.Add(this.animatedIcon2);
      this.animatedIcon2.StartAnimation();
   }

此代码将 AnimatedIcon 对象添加到 StatusBar 中包含的控件集合中。 请注意,我的 StatusBarPanel 文本为“Another...”,宽度为 180 个单位。 这就是为什么 this.animatedIcon2 的左上角是 190 个单位

   this.animatedIcon2.Location = new Point(190, 
        (statusBar1.Height - animatedIcon2.Size.Height)/2);

我希望这并不难。 祝您动画愉快!

历史

  • 2004 年 6 月 18 日 - 首次发布。
  • 2004 年 6 月 28 日 - 版本 1.1。
© . All rights reserved.