Як показувати анімовані GIF у формі Windows (c #)


142

У мене є форма, в якій відображаються повідомлення про прогрес у процесі досить тривалого процесу. Це дзвінок до веб-сервісу, тому я не можу реально відобразити відсоткову кількість повного показника на панелі прогресу. (Мені особливо не подобається властивість Marquee на панелі прогресу)

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

Як це зробити?


для анімаційного зображення ви можете використовувати цей контролер. codeproject.com/Tips/1004624/Gif-viewer-Snipper-control
xwpedram

Відповіді:


249

Це не надто важко.

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

Що слід врахувати:

  • Якщо вимкнути графічну скриньку, перешкоджатиме анімації gif.

Gif анімації:

Якщо ви шукаєте анімовані gif-файли, можете згенерувати їх:

AjaxLoad - Генератор gif-файлів для завантаження Ajax

Ще один спосіб зробити це:

Ще один спосіб, який я виявив, що працює досить добре, - це контроль діалогу асинхронізації, який я знайшов у проекті коду


5
Збентежено легко! Мій початковий "Гуглінг" цього не показав - можливо, це занадто очевидно. Дякую.
Стюарт Гельвіг

1
Однак графічне поле не оновиться (перемальовується) у процесі виконання.
LarryBud

Durr, я поставив це як фонове зображення помилково. Фонове зображення, розумно, не підтримує анімацію; зображення переднього плану дійсно.
neminem

@neminem: Те саме тут! Тому я тут. Якийсь час я думав, що pictureBox не підтримує фокс-gif (вперше я його використовую)
Джек

@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(); 
  }

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


6

Зауважте, що в Windows, ви традиційно не використовуєте анімовані Gif-файли, а мало AVI-анімацій: для їх відображення є власне управління Windows. Існують навіть інструменти для перетворення анімованих Gifs в AVI (і навпаки).


Так - можливо, це я повинен був запитати. Дякую.
Стюарт Гельвіг

6
Посилання на інструмент, s'il vous plaît? Або будь-яке інше посилання на документацію, причини, і т.д., було б чудово. Дякую!
Джефф Б

1
Мені не цікаво писати традиційне програмне забезпечення для Windows. Якщо це підтримується елементом System.Windows.Forms.PictureBoxуправління, я просто використовуватиму анімовані GIF-файли.
Майк де Клерк

3

Якщо ви помістите його в елемент управління PictureBox, він повинен просто працювати


2
Якщо ви не відключите форму;)
Jeff B

1

Це не відбувається, коли ви починаєте довгу операцію позаду, тому що все ЗАСТАВЛЯЄТЬСЯ з того часу, коли ви знаходитесь в одній нитці.


І режим потоку MTA здається найгіршим рішенням, наскільки я читаю в StackOverflow.
Йогурту

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.