Jak wyświetlić animowane pliki GIF w formularzu systemu Windows (C #)


142

Mam formularz pokazujący komunikaty o postępach, ponieważ trwa dość długo. Jest to połączenie z usługą internetową, więc nie mogę w znaczący sposób pokazać procentowej pełnej liczby na pasku postępu. (Nie podoba mi się właściwość Marquee paska postępu)

Chciałbym pokazać animowany GIF, aby nadać procesowi wrażenie jakiejś aktywności (np. Pliki przelatujące z jednego komputera na drugi, jak proces kopiowania w systemie Windows).

Jak Ty to robisz?


w przypadku animowanego obrazu możesz użyć tego kontrolera. codeproject.com/Tips/1004624/Gif-viewer-Snipper-control
xwpedram

Odpowiedzi:


249

To nie jest zbyt trudne.

  1. Upuść ramkę ze zdjęciami na formularz.
  2. Dodaj plik .gif jako obraz w ramce graficznej
  3. Pokaż ramkę graficzną podczas ładowania.

Kwestie, które należy wziąć pod uwagę:

  • Wyłączenie ramki graficznej uniemożliwi animację gifa.

Animowane gify:

Jeśli szukasz animowanych gifów, możesz je wygenerować:

AjaxLoad - Ajax ładuje generator gifów

Inny sposób na zrobienie tego:

Innym sposobem, który znalazłem, który działa całkiem dobrze, jest kontrolka okna dialogowego asynchronicznego, którą znalazłem w projekcie kodu


5
Żenująco proste! MOJE początkowe „Googling” tego nie pokazało - może jest to zbyt oczywiste. Dzięki.
Stuart Helwig

1
Pole obrazu nie zostanie jednak odświeżone (przerysowane) podczas wykonywania procesu.
LarryBud

Durr, przez pomyłkę ustawiłem go jako obraz tła. Obraz w tle nie obsługuje animacji; obraz pierwszego planu tak.
neminem

@neminem: To samo tutaj! Dlatego tu jestem. Przez chwilę myślałem, że pictureBox nie obsługuje gifów z lisami (pierwszy raz go używam)
Jack

@LarryBud Aby spowodować odświeżenie (odświeżenie) w trakcie wykonywania procesu, możesz wywołać Application.DoEvents();. Możliwe podejście: Twoja logika biznesowa wyzwala zdarzenie, gdy coś jest częściowo zrobione, następnie dowolne właściwości (na przykład pasek postępu lub wartość procentowa) mogą zostać zaktualizowane, a animacja może zostać zaktualizowana za pomocą Application.DoEvents ()
Do-do-new

12

Miałem ten sam problem. Cały formularz (łącznie z gifem) przestaje się przerysowywać z powodu długiego działania w tle. Oto jak to rozwiązałem.

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

Po prostu utworzyłem kolejny wątek, który będzie odpowiedzialny za tę operację. Dzięki takiemu początkowemu formularzowi przerysowuje się bez problemów (w tym mój gif działa). ShowProgressGifDelegate i HideProgressGifDelegate są delegatami w postaci, która ustawia właściwość visible obiektu pictureBox z gif na wartość true / false.


6

Zwróć uwagę, że w systemie Windows tradycyjnie nie używasz animowanych GIF-ów, ale małe animacje AVI: istnieje natywna kontrolka systemu Windows tylko do ich wyświetlania. Istnieją nawet narzędzia do konwersji animowanych Gifów do formatu AVI (i odwrotnie).


Tak - może o to powinienem zapytać. Dzięki.
Stuart Helwig

6
Link do narzędzia, s'il vous plaît? Lub jakiekolwiek inne odniesienie do dokumentacji, powodów, dla których itp. Byłoby świetne. Dzięki!
Jeff B

1
Nie obchodzi mnie pisanie tradycyjnego oprogramowania Windows. Jeśli jest obsługiwany przez System.Windows.Forms.PictureBoxkontrolkę, użyję tylko animowanych plików GIF.
Mike de Klerk

3

Jeśli umieścisz go w kontrolce PictureBox, powinno po prostu działać


2
Chyba że wyłączysz formularz;)
Jeff B

1

Nie dzieje się tak, gdy zaczynasz długą operację z tyłu, ponieważ wszystko ZATRZYMUJE się, odkąd jesteś w tym samym wątku.


A tryb wątku MTA wydaje się być najgorszym rozwiązaniem, o ile czytam na 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

Miałem ten sam problem i natknąłem się na różne rozwiązania, wdrażając, które napotykałem na kilka różnych problemów. Na koniec poniżej przedstawiam kilka fragmentów z różnych postów, które działały zgodnie z oczekiwaniami.

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

Oto metoda Execution, która przenosi również wywołanie kontrolki 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; });
}

Pamiętaj, że PictureBox jest niewidoczny w oknie Właściwości lub wykonaj poniższe czynności:

private void ComparerForm_Load(object sender, EventArgs e)
{
    pictureBox1.Visible = false;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.