Como você mostra GIFs animados em um formulário do Windows (c #)

142

Eu tenho um formulário mostrando mensagens de progresso à medida que um processo bastante longo é executado. É uma chamada para um serviço da Web, por isso não posso realmente mostrar um valor percentual completo em uma barra de progresso significativamente. (Não gosto particularmente da propriedade Marquee da barra de progresso)

Gostaria de mostrar um GIF animado para dar ao processo a sensação de alguma atividade (por exemplo, arquivos que voam de um computador para outro, como o processo de cópia do Windows).

Como você faz isso?

Stuart Helwig
fonte
para animar uma imagem, você pode usar este controlador. codeproject.com/Tips/1004624/Gif-viewer-Snipper-control
xwpedram

Respostas:

249

Não é muito difícil.

  1. Solte uma caixa de imagem em seu formulário.
  2. Adicione o arquivo .gif como a imagem na caixa de imagem
  3. Mostre a caixa de imagem quando estiver carregando.

O que levar em consideração:

  • Desativar a caixa de imagem impedirá que o gif seja animado.

Gifs animados:

Se você estiver procurando por gifs animados, pode gerá-los:

AjaxLoad - Ajax Loading gif generator

Outra maneira de fazer isso:

Outra maneira que eu descobri que funciona muito bem é o controle de diálogo assíncrono que encontrei no projeto de código

FryHard
fonte
5
Embaraçosamente fácil! Meu "Google" inicial não mostrou isso - talvez seja óbvio demais. Obrigado.
Stuart Helwig
1
A caixa de imagem não será atualizada (redesenhada) enquanto o processo está sendo executado.
precisa saber é o seguinte
Durr, eu a defini como imagem de fundo por engano. A imagem de plano de fundo, razoavelmente, não suporta animação; imagem de primeiro plano faz.
Neminem
@neminem: O mesmo aqui! É por isso que estou aqui. Por um tempo eu pensei pictureBox não apoiar gifs Fox (primeira vez que eu estou usando-o)
Jack
@LarryBud Para fazer com que seja atualizada (redesenhada) enquanto o processo está em execução, você pode ligar Application.DoEvents();. Abordagem possível: sua lógica de negócios dispara um evento quando algo é parcialmente concluído; quaisquer propriedades (por exemplo, barra de progresso ou porcentagem) podem ser atualizadas e a animação pode ser atualizada com Application.DoEvents ()
Do-do-new
12

Eu tive o mesmo problema. Forma inteira (incluindo gif) parando para se redesenhar por causa de uma operação longa trabalhando em segundo plano. Aqui está como eu resolvi isso.

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

Eu simplesmente criei outro thread para ser responsável por esta operação. Graças a este formulário inicial, continua o redesenho sem problemas (incluindo o meu gif funcionando). ShowProgressGifDelegate e HideProgressGifDelegate são delegados no formulário que definem a propriedade visível de pictureBox with gif como true / false.

Aruch
fonte
6

Observe que, no Windows, você tradicionalmente não usa Gifs animados, mas poucas animações AVI: existe um controle nativo do Windows apenas para exibi-los. Existem ainda ferramentas para converter gifs animados em AVI (e vice-versa).

PhiLho
fonte
Sim - talvez seja o que eu deveria ter perguntado. Obrigado.
Stuart Helwig
6
Link para a ferramenta, s'il vous plaît? Ou qualquer outra referência à documentação, motivos, etc., seria ótima. Obrigado!
Jeff B
1
Não me importo em escrever software tradicional do Windows. Se for suportado pelo System.Windows.Forms.PictureBoxcontrole, usarei apenas GIFs animados.
Mike de Klerk
3

Se você colocá-lo em um controle PictureBox, ele deve funcionar

Grank
fonte
2
A menos que você desative o formulário;)
Jeff B
1

Não acontece quando você inicia uma longa operação para trás, porque tudo para desde que você está no mesmo segmento.


fonte
E o modo de thread MTA parece ser a pior solução, tanto quanto eu estou lendo no 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
Gehan Fernando
fonte
0

Eu tive o mesmo problema e me deparei com diferentes soluções implementando as quais eu costumava enfrentar vários problemas diferentes. Finalmente, abaixo está o que eu coloquei algumas peças de diferentes posts, que funcionaram para mim como esperado.

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

Aqui está o método Execution que também carrega a chamada do controle 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; });
}

Lembre-se de que o PictureBox é invisível na janela Propriedades ou abaixo:

private void ComparerForm_Load(object sender, EventArgs e)
{
    pictureBox1.Visible = false;
}
M. Fawad Surosh
fonte