Как вы показываете анимированные GIF-файлы в форме Windows (c #)

143

У меня есть форма, в которой отображаются сообщения о ходе выполнения довольно длительного процесса. Это вызов веб-службы, поэтому я не могу значимо показать процент выполнения на индикаторе выполнения. (Мне не особенно нравится свойство Marquee индикатора выполнения)

Я хотел бы показать анимированный GIF, чтобы придать процессу ощущение некоторой активности (например, файлы, летающие с одного компьютера на другой, как процесс копирования Windows).

Как ты делаешь это?

Стюарт Хельвиг
источник
для анимации изображения вы можете использовать этот контроллер. codeproject.com/Tips/1004624/Gif-viewer-Snipper-control
xwpedram

Ответы:

250

Это не так уж сложно.

  1. Поместите рамку с картинками в свою форму.
  2. Добавьте файл .gif как изображение в окно изображений
  3. Показывать окно с картинками при загрузке.

На что следует обратить внимание:

  • Отключение графического блока предотвратит анимацию гифки.

Анимированные гифки:

Если вы ищете анимированные гифки, вы можете их сгенерировать:

AjaxLoad - генератор гифок с загрузкой Ajax

Другой способ сделать это:

Другой способ, который я нашел, который работает довольно хорошо, - это элемент управления асинхронным диалогом, который я нашел в проекте кода.

FryHard
источник
5
Невероятно просто! МОЙ начальный поиск в Google этого не показал - возможно, это слишком очевидно. Спасибо.
Стюарт Хельвиг
1
Однако окно изображения не будет обновляться (перерисовываться) по мере выполнения процесса.
LarryBud
Дурр, я по ошибке поставил его в качестве фонового изображения. Фоновое изображение, естественно, не поддерживает анимацию; изображение переднего плана делает.
neminem
@neminem: То же самое! Вот почему я нахожусь здесь. Какое-то время я думал, что pictureBox не поддерживает гифки с лисами (впервые я его использую)
Джек
@LarryBud Чтобы заставить его обновляться (перерисовывать) во время выполнения процесса, вы можете вызвать Application.DoEvents();. Возможный подход: ваша бизнес-логика запускает событие, когда что-то частично выполнено, тогда любые свойства (например, индикатор выполнения или процент) могут быть обновлены, а анимация может быть обновлена ​​с помощью Application.DoEvents ()
Do-do-new
12

У меня такая же проблема. Вся форма (включая gif) перестает перерисовываться из-за долгой работы в фоновом режиме. Вот как я это решил.

  private void MyThreadRoutine()
  {
   this.Invoke(this.ShowProgressGifDelegate);
   //your long running process
   System.Threading.Thread.Sleep(5000);
   this.Invoke(this.HideProgressGifDelegate);
  }

  private void button1_Click(object sender, EventArgs e)
  {
   ThreadStart myThreadStart = new ThreadStart(MyThreadRoutine);
   Thread myThread = new Thread(myThreadStart);
   myThread.Start(); 
  }

Я просто создал другой поток, который будет отвечать за эту операцию. Благодаря этой начальной форме перерисовка продолжается без проблем (в том числе моя гифка работает). ShowProgressGifDelegate и HideProgressGifDelegate - это делегаты в форме, которые устанавливают для свойства visible свойства pictureBox с gif значение true / false.

Арух
источник
6

Обратите внимание, что в Windows вы обычно не используете анимированные Gif-файлы, а только небольшие анимации AVI: для их отображения есть собственный элемент управления Windows. Есть даже инструменты для преобразования анимированных GIF-файлов в AVI (и наоборот).

PhiLho
источник
Да - наверное, это то, что мне следовало спросить. Спасибо.
Стюарт Хельвиг
6
Ссылка на инструмент, s'il vous plaît? Или любая другая ссылка на документацию, причины почему и т. Д. Было бы замечательно. Благодарность!
Jeff B
1
Я не забочусь о написании традиционных программ для Windows. Если это поддерживается элементом System.Windows.Forms.PictureBoxуправления, я буду использовать только анимированные GIF-файлы.
Майк де Клерк,
3

Если вы поместите его в элемент управления PictureBox, он должен просто работать

Гранк
источник
2
Если только вы не отключите форму;)
Jeff B
1

Этого не происходит, когда вы начинаете долгую операцию, потому что все ОСТАНАВЛИВАЕТСЯ, поскольку вы находитесь в одном потоке.


источник
И режим потока MTA кажется худшим решением, насколько я читаю на StackOverflow.
Yogurtu
1
Public Class Form1

    Private animatedimage As New Bitmap("C:\MyData\Search.gif")
    Private currentlyanimating As Boolean = False

    Private Sub OnFrameChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)

        Me.Invalidate()

    End Sub

    Private Sub AnimateImage()

        If currentlyanimating = True Then
            ImageAnimator.Animate(animatedimage, AddressOf Me.OnFrameChanged)
            currentlyanimating = False
        End If

    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

        AnimateImage()
        ImageAnimator.UpdateFrames(animatedimage)
        e.Graphics.DrawImage(animatedimage, New Point((Me.Width / 4) + 40, (Me.Height / 4) + 40))

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        BtnStop.Enabled = False

    End Sub

    Private Sub BtnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStop.Click

        currentlyanimating = False
        ImageAnimator.StopAnimate(animatedimage, AddressOf Me.OnFrameChanged)
        BtnStart.Enabled = True
        BtnStop.Enabled = False

    End Sub

    Private Sub BtnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStart.Click

        currentlyanimating = True
        AnimateImage()
        BtnStart.Enabled = False
        BtnStop.Enabled = True

    End Sub

End Class
Гехан Фернандо
источник
0

У меня была такая же проблема, и я столкнулся с разными решениями, реализовав которые, я сталкивался с несколькими разными проблемами. Наконец, ниже я собрал несколько фрагментов из разных сообщений, которые сработали для меня, как и ожидалось.

private void btnCompare_Click(object sender, EventArgs e)
{
    ThreadStart threadStart = new ThreadStart(Execution);
    Thread thread = new Thread(threadStart);
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
}

Вот метод Execution, который также включает вызов элемента управления PictureBox:

private void Execution()
{
    btnCompare.Invoke((MethodInvoker)delegate { pictureBox1.Visible = true; });
    Application.DoEvents();

    // Your main code comes here . . .

    btnCompare.Invoke((MethodInvoker)delegate { pictureBox1.Visible = false; });
}

Имейте в виду, что PictureBox невидим из окна свойств или выполните следующие действия:

private void ComparerForm_Load(object sender, EventArgs e)
{
    pictureBox1.Visible = false;
}
М. Фавад Сурош
источник