【问题标题】:Switching between animated image and static image in winforms button在winforms按钮中在动画图像和静态图像之间切换
【发布时间】:2011-10-08 20:22:10
【问题描述】:

所以我在一个用 C# 4.0 编写的 Winforms 应用程序中有一个自定义 Button 类。该按钮通常包含一个静态图像,但是当发生刷新操作时,它会切换到一个动画 AJAX 样式按钮。为了使图像动画化,我设置了一个计时器,它在每个刻度上推进图像动画并将其设置为按钮图像。这是我让它工作的唯一方法。我的解决方案不是那么有效;任何建议都会有所帮助。

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

在下面找到我在每个刻度上所做的代码。第一个改进领域:也许将图像的每一帧复制到一个列表中?注意 _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--;
        }
    }

【问题讨论】:

    标签: c# winforms image button animated


    【解决方案1】:
    1. 我猜想 Winforms 本身在动画功能方面并没有那么强大。如果您想要更高级的动画使用,可以考虑一些第三方解决方案。
    2. 我认为您不应该每次都从资源中加载图像。更好的方法是预加载图像帧一个并保留参考。然后使用它在每个刻度上设置适当的帧。

    正如我最近测试的那样,动画 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 一样。

    【讨论】:

    • 如何将图像帧加载到列表中?我认为这将解决我遇到的任何主要性能问题。谢谢你的回答。
    • 甜蜜。当然,现在它看起来非常非常明显。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多