คุณแสดง GIF แบบเคลื่อนไหวในแบบฟอร์ม Windows ได้อย่างไร (c #)


142

ฉันมีแบบฟอร์มแสดงข้อความความคืบหน้าในขณะที่กระบวนการทำงานค่อนข้างนาน เป็นการเรียกใช้บริการเว็บดังนั้นฉันจึงไม่สามารถแสดงตัวเลขที่สมบูรณ์แบบร้อยละบนแถบความคืบหน้าอย่างมีความหมาย (ฉันไม่ชอบคุณสมบัติ Marquee ของแถบความคืบหน้าเป็นพิเศษ)

ฉันต้องการแสดง GIF แบบเคลื่อนไหวเพื่อให้ความรู้สึกของกิจกรรมบางอย่าง (เช่นไฟล์ที่บินจากคอมพิวเตอร์เครื่องหนึ่งไปยังอีกเครื่องหนึ่งเช่นกระบวนการคัดลอก Windows)

คุณทำเช่นนี้ได้อย่างไร


สำหรับภาพเคลื่อนไหวคุณสามารถใช้คอนโทรลเลอร์นี้ codeproject.com/Tips/1004624/Gif-viewer-Snipper-control
xwpedram

คำตอบ:


249

มันไม่ยากเกินไป

  1. วาง picturebox ลงบนแบบฟอร์มของคุณ
  2. เพิ่มไฟล์. gif เป็นรูปภาพใน picturebox
  3. แสดงกล่องภาพเมื่อคุณกำลังโหลด

สิ่งที่ต้องคำนึงถึง:

  • การปิดใช้งาน picturebox จะทำให้ gif ไม่สามารถเคลื่อนไหวได้

gifs เคลื่อนไหว:

หากคุณกำลังมองหา gif ที่เคลื่อนไหวคุณสามารถสร้างมันได้:

AjaxLoad - Ajax กำลังโหลดตัวสร้าง gif

อีกวิธีในการทำ:

อีกวิธีหนึ่งที่ฉันพบว่าทำงานได้ค่อนข้างดีคือการควบคุมไดอะล็อก async ที่ฉันพบในโปรเจคโค้ด


5
ง่ายเขิน! "Googling" เริ่มต้นของฉันไม่ได้แสดงสิ่งนี้ - บางทีมันอาจจะชัดเจนเกินไป ขอบคุณ
Stuart Helwig

1
อย่างไรก็ตามกล่องภาพจะไม่รีเฟรช (วาดใหม่) เนื่องจากกระบวนการทำงาน
LarryBud

Durr ฉันตั้งเป็นภาพพื้นหลังโดยไม่ได้ตั้งใจ ภาพพื้นหลังอย่างสมเหตุสมผลไม่รองรับภาพเคลื่อนไหว ภาพพื้นหน้าไม่
neminem

@neminem: เหมือนกันที่นี่! นั่นเป็นเหตุผลที่ฉันมาที่นี่ ในขณะที่ฉันคิดว่า PictureBox ไม่สนับสนุน GIFs สุนัขจิ้งจอก (ครั้งแรกที่เคยฉันใช้มัน)
แจ็ค

@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 เป็นตัวแทนในรูปแบบที่ตั้งค่าคุณสมบัติที่มองเห็นได้ของ pictureBox ด้วย gif ให้เป็นจริง / เท็จ


6

โปรดทราบว่าใน Windows คุณจะไม่ใช้ Gif แบบเคลื่อนไหว แต่เป็นภาพเคลื่อนไหว AVI เล็กน้อย: มีการควบคุมเนทิฟ Windows เพียงแสดง มีแม้กระทั่งเครื่องมือในการแปลงภาพเคลื่อนไหว Gif เป็น AVI (และในทางกลับกัน)


ใช่ - นั่นอาจเป็นสิ่งที่ฉันควรถาม ขอบคุณ
Stuart Helwig

6
เชื่อมโยงไปยังเครื่องมือ s'il vous plaît? หรือการอ้างอิงอื่น ๆ ไปยังเอกสารเหตุผลทำไม ฯลฯ จะดีมาก ขอบคุณ!
Jeff B

1
ฉันไม่สนใจเกี่ยวกับการเขียนซอฟต์แวร์ Windows ดั้งเดิม หากได้รับการสนับสนุนโดยการSystem.Windows.Forms.PictureBoxควบคุมฉันจะใช้ GIF แบบเคลื่อนไหว
Mike de Klerk

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

นี่คือวิธีการดำเนินการที่มีการเรียกใช้ตัวควบคุม 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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.