在winforms按钮中切换动画图像和静态图像

时间:2011-07-19 19:42:05

标签: c# winforms image button animated

所以我在用C#4.0编写的Winforms应用程序中有一个自定义Button类。该按钮正常保存静态图像,但是当进行刷新操作时,它会切换到动画AJAX样式按钮。为了给图像添加动画效果,我设置了一个计时器,可以在每个刻度上推进图像动画并将其设置为按钮图像。这是我能让它发挥作用的唯一方法。我的解决方案效率不高;任何建议都会有所帮助。

所以有两个问题: 1.有没有更简单的方法 - 因为我忽略了我应该使用的一些功能? 2.有没有更好的手动动画图像的方法?

在下面找到我在每个tick上做的代码。第一个改进领域:可能将图像的每一帧复制到一个列表中?注意_image.Dispose();未能处理本地图像导致内存泄漏。

感谢您的任何建议。我将在线发布一些内容,并在我有一个有效的解决方案后链接它。

    private void TickImage()
    {
        if (!_stop)
        {
            _ticks++;

            this.SuspendLayout();

            Image = null;

            if(_image != null)
                _image.Dispose();

            //Get the animated image from resources and the info
            //required to grab a frame
            _image = Resources.Progress16;
            var dimension = new FrameDimension(_image.FrameDimensionsList[0]);
            int frameCount = _image.GetFrameCount(dimension);

            //Reset to zero if we're at the end of the image frames
            if (_activeFrame >= frameCount)
            {
                _activeFrame = 0;
            }

            //Select the frame of the animated image we want to show
            _image.SelectActiveFrame(dimension, _activeFrame);

            //Assign our frame to the Image property of the button
            Image = _image;

            this.ResumeLayout();

            _activeFrame++;

            _ticks--;
        }
    }

1 个答案:

答案 0 :(得分:2)

  1. 我觉得Winforms本身并没有达到动画功能。如果您想要更高级的动画,可以考虑使用某些第三方解决方案。
  2. 我认为你不应该每次打勾都从资源中加载图像。更好的方法是预加载图像帧并保持参考。然后用它来设置每个刻度线的适当帧。
  3. 正如我最近测试的那样,动画GIF动画效果很好,没有任何额外的编码,至少在标准按钮上。但是如果您仍然需要手动终止帧,您可以尝试这样的事情:

    // put this somewhere in initialization
    private void Init() 
    {
        Image image = Resources.Progress16;
        _dimension = new FrameDimension(image.FrameDimensionsList[0]);
        _frameCount = image.GetFrameCount(_dimension);
        image.SelectActiveFrame(_dimension, _activeFrame);
        Image = image;
    }
    
    private void TickImage()
    {
        if (_stop) return;
        // get next frame index
        if (++_activeFrame >= _frameCount)
        {
            _activeFrame = 0;
        }
        // switch image frame
        Image.SelectActiveFrame(_dimension, _activeFrame);
        // force refresh (NOTE: check if it's really needed)
        Invalidate();
    }
    

    另一种选择是将ImageList属性与预加载的静态帧一起使用,然后循环ImageIndex,就像使用上面的SelectActiveFrame一样。