Как включить анимированный GIF-файл в DataGridView? - PullRequest
2 голосов
/ 31 декабря 2010

Я включил анимированный GIF в DataGridView, но изображение отображается статичным.Является ли это возможным?

Ответы [ 2 ]

3 голосов
/ 09 января 2013

Я реализовал класс DataGridViewImageAnimator, который заботится об анимации изображений gif для любого объекта DataGridView.Экземпляры DataGridViewImageAnimator отслеживают заданный DataGridView и анимируют любое изображение GIF, отображаемое в нем.Вы можете загрузить исходный код из https://docs.google.com/open?id=0B1r6und31C6BQXktM2VQN1Jza2c

. Вы можете создать аниматор в форме, включающей DataGridView, следующим образом:

public partial class YourForm : Form
{
    private DataGridViewImageAnimator dataGridImageAnimator;

    public YourForm()
    {
        InitializeComponent();
        dataGridImageAnimator = new DataGridViewImageAnimator(dataGridView1);
    }

    // ...
}

В качестве альтернативы, вы можете использовать производный от DataGridView класскоторый уже делает это в своем конструкторе, как показано ниже для класса AnimatedDataGridView ниже (код доступен в https://docs.google.com/open?id=0B1r6und31C6BQnZUaTBjVXA4SkE)

using System.Windows.Forms;

namespace JLR.Utils
{
    public class AnimatedDataGridView : DataGridView
    {
        private DataGridViewImageAnimator _imageAnimator;

        public AnimatedDataGridView()
            : base()
        {
            _imageAnimator = new DataGridViewImageAnimator(this);
        }
    }
}

Полный код для DataGridViewImageAnimator показан ниже:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace JLR.Utils
{
    public class DataGridViewImageAnimator
    {
        private class RowCol
        {
            public int Column { get; set; }
            public int Row { get; set; }

            public RowCol(int column, int row)
            {
                Column = column;
                Row = row;
            }

            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;

                RowCol other = obj as RowCol;
                if (other == null)
                    return false;

                return (other.Column == Column && other.Row == Row);
            }

            public bool Equals(RowCol other)
            {
                if (other == null)
                    return false;

                return (other.Column == Column && other.Row == Row);
            }

            public override int GetHashCode()
            {
                return Column.GetHashCode() ^ Row.GetHashCode();
            }

            public static bool operator ==(RowCol a, RowCol b)
            {
                // If both are null, or both are same instance, return true.
                if (object.ReferenceEquals(a, b))
                {
                    return true;
                }

                // If one is null, but not both, return false.
                if (((object)a == null) || ((object)b == null))
                {
                    return false;
                }

                // Return true if the fields match:
                return a.Column == b.Column && a.Row == b.Row;
            }

            public static bool operator !=(RowCol a, RowCol b)
            {
                return !(a == b);
            }
        }

        private class AnimatedImage
        {
            private DataGridView DataGridView { get; set; }
            private HashSet<RowCol> _cells = new HashSet<RowCol>();

            public Image Image { get; set; }

            public AnimatedImage(Image image, DataGridView dataGridView)
            {
                Image = image;
                DataGridView = dataGridView;
            }

            public bool IsUsed { get { return _cells.Count > 0; } }

            public void AddCell(RowCol rowCol)
            {
                Debug.Assert(!_cells.Contains(rowCol));

                if (!_cells.Contains(rowCol))
                {
                    _cells.Add(rowCol);

                    if (_cells.Count == 1)
                    {
                        // this is the first cell we are using this image, so start animation
                        ImageAnimator.Animate(Image, new EventHandler(OnFrameChanged));
                    }
                }
            }

            public void RemoveCell(RowCol rowCol)
            {
                Debug.Assert(_cells.Contains(rowCol));

                if (_cells.Contains(rowCol))
                {
                    _cells.Remove(rowCol);

                    if (_cells.Count == 0)
                    {
                        // this was the last cell we were using this image, so stop animation
                        ImageAnimator.StopAnimate(Image, new EventHandler(OnFrameChanged));
                    }
                }
            }

            private void OnFrameChanged(object o, EventArgs e)
            {
                // invalidate each cell in which it's being used
                RowCol[] rcs = new RowCol[_cells.Count];
                _cells.CopyTo(rcs);
                foreach (RowCol rc in rcs)
                {
                    DataGridView.InvalidateCell(rc.Column, rc.Row);
                }
            }
        }

        private Dictionary<RowCol, Image> _values = new Dictionary<RowCol, Image>();
        private Dictionary<Image, AnimatedImage> _animatedImages = new Dictionary<Image, AnimatedImage>();
        private DataGridView _dataGridView;

        public DataGridViewImageAnimator(DataGridView dataGridView)
        {
            _dataGridView = dataGridView;
            _dataGridView.CellPainting += new DataGridViewCellPaintingEventHandler(OnDatagridCellPainting);
        }

        void OnDatagridCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
            {
                object value = _dataGridView[e.ColumnIndex, e.RowIndex].Value;
                CheckValue(e.ColumnIndex, e.RowIndex, value);
                ImageAnimator.UpdateFrames();
            }
        }

        private void AddImage(RowCol rowCol, Image image)
        {
            _values[rowCol] = image;

            AnimatedImage animatedImage;
            if (!_animatedImages.TryGetValue(image, out animatedImage))
            {
                animatedImage = new AnimatedImage(image, _dataGridView);
                _animatedImages[image] = animatedImage;
            }

            animatedImage.AddCell(rowCol);
        }

        private void RemoveImage(RowCol rowCol, Image image)
        {
            Debug.Assert(_values.ContainsKey(rowCol));
            Debug.Assert(_animatedImages.ContainsKey(image));

            _values.Remove(rowCol);

            AnimatedImage animatedImage;
            if (_animatedImages.TryGetValue(image, out animatedImage))
            {
                animatedImage.RemoveCell(rowCol);
                if (!animatedImage.IsUsed)
                {
                    _animatedImages.Remove(image);
                }
            }
        }

        private void CheckValue(int columnIndex, int rowIndex, object value)
        {
            RowCol rowCol = new RowCol(columnIndex, rowIndex);

            // is the new value an Image, and can it be animated?
            Image newImage = value as Image;
            bool newValueIsImage = (newImage != null && ImageAnimator.CanAnimate(newImage));

            // is there a previous image value?
            Image oldImage;
            if (_values.TryGetValue(rowCol, out oldImage))
            {
                if (newImage == oldImage)
                {
                    // same old image --> nothing else to do
                    return;
                }

                RemoveImage(rowCol, oldImage);
            }

            if (newValueIsImage)
            {
                AddImage(rowCol, newImage);
            }
        }
    }
}

С уважением,

0 голосов
/ 26 июня 2018

После ответа "Только для ссылки" @AseemGautam, который ссылается на тот же вопрос, опубликованный на другом форуме, с ответом только на одну ссылку, который ссылается на rar файл , содержащий сложный проект, сводится к простому ответу.

Включение изображения непосредственно из ресурса не будет воспроизводить его анимацию.Таким образом, мы включаем изображение в изображение 1x1 пикселей в той же форме, что и сетка (это изображение 1x1 не может скрываться за другими компонентами, в противном случае анимация не будет работать, надеюсь, что 1 пиксель будет прозрачным в gif-файле).Затем с помощью таймера аннулируйте ячейку каждые 60 мс (или наименьшая продолжительность кадра в анимации gif).Скорее всего, это вызовет мерцание на изображениях, поэтому добавление события RowPostPaint, которое рисует линию в 1 пиксель, синхронизирует рисование ячейки.

    void frmMain_Load(object sender, EventArgs e) {
        DataGridView1.Rows.Clear();
        DataGridView1.Rows.Add(PictureBox1.Image);
    }

    void Timer1_Tick(object sender, EventArgs e) {
        if (DataGridView1.Rows.Count > 0) {
            DataGridView1.Rows[0].Cells[0].Value = PictureBox1.Image;
            DataGridView1.InvalidateCell(0, 0);
        }
    }

    void DataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) {
        e.Graphics.DrawLine(new Pen(SystemColors.ActiveBorder), 0, 0, 1, 1);
    }
...