none
Form mit Animierten Bild von einer anderen Form aus aufrufen RRS feed

  • Frage

  • Hallo allerseits,

    ich möchte von einer MainForm aus bei einer Aktion (zb Speihern) eine andere Form aufrufen, um eine Animation während der Aktion anzuzeigen. Dazu habe rfe ch von der MeinForm die zu ladende Form wie folgt auf.

    frmL = new frmLoading();
    
    frmL.TopLevel = true;
    
    frmL.Show();

    Dann in der 2. Form versuche ich das ganze wie folgt anzuzeigen.

    private void frmLoading_Load(object sender, EventArgs e)
    
      {
    
       bmp = global::REC.Properties.Resources.lade;
    
       if (ImageAnimator.CanAnimate(bmp)) ImageAnimator.Animate(bmp, new EventHandler(nextFrame));
    
      }
    
      private void nextFrame(object sender, EventArgs e)
    
      { this.Invalidate(); }
    
    
    
      protected override void OnPaintBackground(PaintEventArgs e)
    
      {
    
       e.Graphics.DrawImage(bmp, 5, 5);
    
       ImageAnimator.UpdateFrames();
    
      }

    So, nun, die Anzeige funktioniert aber das Bild wird nicht animiert. Das heisst das es beim ersten Bild stehn bleibt.´
    Ich habe es auch mit einem Thread versucht bekomme ich auch das gleiche prolem.
    Wäre sehr dankbar wenn mir jemand sagen könnte was ich übersehen bzw. vergessen habe.

    Danke und Lg

    WaZZkeSS

    Montag, 9. August 2010 06:15

Alle Antworten

  • Hallo,

    bei mir fuktioniert es. Beispielcode:

      public partial class Form1 : Form
      {
        private Bitmap bmp = null;
        public Form1()
        {
          InitializeComponent();
          //namespace und ResourcenName natürlich anpassen
          Image imgIn = global::asdfasd.Properties.Resources.Bild1; //Funktioniert ebenfalls: Image.FromFile(@"Pfad\zu\Gif");
          this.bmp = (Bitmap)imgIn.Clone();
          imgIn.Dispose();
    
          if (ImageAnimator.CanAnimate(bmp)) 
            ImageAnimator.Animate(bmp, new EventHandler(nextFrame));
        }
    
        private void nextFrame(object sender, EventArgs e)
        {
          ImageAnimator.UpdateFrames();
          this.Invalidate(); 
        }
    
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
          if(bmp != null)
            e.Graphics.DrawImage(bmp, 0, 0);
        }
      }
    

    Das Bild muss aber "komplett" vorliegen. Eine Kopie via "this.bmp = new Bitmap(imgIn);" würde hier nicht funktionieren.

    Viele Grüße,

      Thorsten

    Montag, 9. August 2010 22:39
  • Hallo Thorsten,

    danke vorerst für deine Antwort. Jedoch muss ich sagen das es noch immer nicht klappt.
    Ich habe es bereits mit einer anderen gif Datei probiert habe das gleiche problem.
    Das eizige was mir jetzt aufgefallen ist, das bevor die Form mit der Ani geschlossen wird
    das nächste Bild sehe. Also beim Aufrufen sehe ich das erste Bild der Animation und wenn die
    Verarbeitung fertig ist sehe ich das nächste Bild kurz vorm schliessen. Keine Ahnung ob das
    vorher auch war oder nicht. Jedenfalls funktioniert es nicht.

    Danke trotzdem und Lg
    WaZZkeSS

    Dienstag, 10. August 2010 05:22
  • Hallo,

    klappt den die Animation an sich, sprich, ohne den "lange dauernden Prozess" (<- der ja im "Hintergrund", also in einem zweiten Thread laufen wird, denke ich)?

    Viele Grüße,

      Thorsten

    Dienstag, 10. August 2010 06:01
  • Ok, hier ein Testprogramm:

    '################## Form1.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace adfsga
    {
      public partial class Form1 : Form
      {
        private Form2 frm = null;
    
        public Form1()
        {
          InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          this.backgroundWorker1.RunWorkerAsync();
          frm = new Form2();
          frm.Show();
        }
    
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
          long a = 0;
          for (int i = 0; i < 100; i++)
          {
            a += i * i;
            System.Threading.Thread.Sleep(10);
          }
    
        }
    
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
          MessageBox.Show("fertig");
          if (frm != null)
          {
            if (frm.Visible)
              frm.Close();
          }
        }
      }
    }
    
    

    ##################### Form1.Designer.cs

    namespace adfsga
    {
      partial class Form1
      {
        /// <summary>
        /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
    
        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
          if (disposing && (components != null))
          {
            components.Dispose();
          }
          base.Dispose(disposing);
        }
    
        #region Vom Windows Form-Designer generierter Code
    
        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
          this.button1 = new System.Windows.Forms.Button();
          this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
          this.SuspendLayout();
          // 
          // button1
          // 
          this.button1.Location = new System.Drawing.Point(189, 39);
          this.button1.Name = "button1";
          this.button1.Size = new System.Drawing.Size(75, 23);
          this.button1.TabIndex = 0;
          this.button1.Text = "button1";
          this.button1.UseVisualStyleBackColor = true;
          this.button1.Click += new System.EventHandler(this.button1_Click);
          // 
          // backgroundWorker1
          // 
          this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
          this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
          // 
          // Form1
          // 
          this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
          this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
          this.ClientSize = new System.Drawing.Size(284, 262);
          this.Controls.Add(this.button1);
          this.Name = "Form1";
          this.Text = "Form1";
          this.ResumeLayout(false);
    
        }
    
        #endregion
    
        private System.Windows.Forms.Button button1;
        private System.ComponentModel.BackgroundWorker backgroundWorker1;
      }
    }
    
    
    

    #################### Form2.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace adfsga
    {
      public partial class Form2 : Form
      {
        private Bitmap bmp = null;
    
        public Form2()
        {
          InitializeComponent();
          Image imgIn = global::adfsga.Properties.Resources.Bild1; //Funktioniert ebenfalls: Image.FromFile(@"Pfad\zu\Gif");
          this.bmp = (Bitmap)imgIn.Clone();
          imgIn.Dispose();
    
          if (ImageAnimator.CanAnimate(bmp))
            ImageAnimator.Animate(bmp, new EventHandler(nextFrame));
    
        }
    
        private void nextFrame(object sender, EventArgs e)
        {
          ImageAnimator.UpdateFrames();
          this.Invalidate();
        }
    
        private void Form2_Paint(object sender, PaintEventArgs e)
        {
          if (bmp != null)
            e.Graphics.DrawImage(bmp, 0, 0);
        }
    
      }
    }
    
    

    ####################### Form2.Designer.cs

    namespace adfsga
    {
      partial class Form2
      {
        /// <summary>
        /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
    
        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
          if (disposing && (components != null))
          {
            components.Dispose();
          }
          base.Dispose(disposing);
        }
    
        #region Vom Windows Form-Designer generierter Code
    
        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
          this.SuspendLayout();
          // 
          // Form2
          // 
          this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
          this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
          this.ClientSize = new System.Drawing.Size(284, 262);
          this.Name = "Form2";
          this.Text = "Form2";
          this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form2_Paint);
          this.ResumeLayout(false);
    
        }
    
        #endregion
      }
    }
    

    Erstelle ein neues Projekt (Windows Forms), öffne die Form1 in der Code-Ansicht, lösche alles, was da steht und kopiere den Bereich Form1.cs dort hinein. Mache gleiches mit der Form1.Designer.cs. Füge dann eine zweite Form hinzu Name: "Form2". Kopiere auch hier wie bei Form1. Öffne dann die Datei "Programm.cs" und lösche auch dort alles und kopiere das Folgende hinein (wegen dem anderen Namespace):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace adfsga
    {
      static class Program
      {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          Application.Run(new Form1());
        }
      }
    }
    
    

    Schaue dann, ob der ResourcenName ("Bild1") stimmt, füge gegebenenfalls eine Gif-Resource hinzu und passe den Resourcennamen im Code an.

    Das sollte eigentlich so lauffähig sein.

      Viele Grüße

      Thorsten

    Dienstag, 10. August 2010 06:17
  • Hallo Thorsten,

    die Animation an sich  funktioniert schon. Dein Beispiel funktioniert auch, jedoch wenn ich das in meinem Projekt einau
    sehe ich nur einen StandBild wie schon vorher erklärt.

    Und das gesammte projekt jetzt wieder in einen funktionierende Animirte Form einzubinden ist (auf gut Wienerisch,  a Sissifuss hockn).
    Mal sehen vielleicht wenn ich am Abend Zeit haben sollte werde ich mal sehen wie ich das am besten implementieren kann.

    Danke trotzdem für dein Musterbeispiel und Lg
    WaZZkeSS

    Dienstag, 10. August 2010 08:39
  • Hallo WaZZkeSS,

    rufe den SplashScreen über einen BackgroundWorker auf. Dann ist Dein Problem gelöst.

    sG,

    Klaus


    No Brain - No Pain
    Montag, 16. August 2010 13:34
  • Hallo Klaus,

    ich mach's gerade andersherum. UI-Thread und Workers trennen. Stichwort: "invalid cross-thread access"

    Viele Grüße,

      Thorsten

    Montag, 16. August 2010 15:40
  • Hallo allerseits,

    ich muss gestehen dass ich leider noch immer nicht dazu gekommen bin das Projekt um zu modeln da ich auf Urlaub war.


    @ Klaus Mayer
    Verstehe nicht genau was du meinst, kannst einbisschen genauer sein bitte da ich mit Backgroundworker wenig zu tun hatte, Danke.

    @ Thorsten Gudera
    Habe ich auch probiert (delegate und Invoke) aber hat auch nicht geholfen.


    Danke und Lg
    WaZZkeSS

    Mittwoch, 18. August 2010 06:25
  • Hallo,

    in meinem Post vom Dienstag, 10. August 2010 06:17 in diesem Thread hatte ich doch ein Beispiel/Testprogramm mit einem extra Thread ("BackgoundWorker") geschrieben. Dort wird halt der Thread via Designer hinzugefügt, Du kannst das aber auch per Thread.Start() etc im code machen.

    Das Beispiel ruft in Button1_Click den thread für die "lange dauernde Berechnung" auf - sprich startet diesen und im Haupthread (UI-Thread) wird dann die Form2 mir dem gif-Bild aufgerufen:

     private void button1_Click(object sender, EventArgs e)
     {
     this.backgroundWorker1.RunWorkerAsync();
     frm = new Form2();
     frm.Show();
     }
    
    

    Per Invoke mit delegate bekommt man in etwa Dein geschildertes Verhalten, die Form wird geladen und gezeigt, dann wird hier unterbrochen, dannach wird die lange Berechnung ausgeführt und dann erst die Form wieder aktiviert (zumindest hier auf meiner Maschine läuft es dann in meistens so ab).

    Ich empfehle wirklich, einen zweiten Thread zu erstellen und dort die längeren Berechnungen auszuführen, mit dem BackgroundWorker bekommst Du ein bequem zu nutzendes "Steuerelement", wo auch Fortschrittsmeldungen etc kein Problem sind. Das Anzeigen der Form kann dann ebenfalls bequem über den Haupthread gemacht werden und beim Beenden des zweiten Threads (BackgroundWorker.RunWorkerCompleted per Designer, oder die Abfrage [ThreadInstanz].IsAlive für im code erstellte threads) wieder geschlossen werden.

    Viele Grüße,

      Thorsten

    Mittwoch, 18. August 2010 06:53
  • Hallo nochmals,

    ich habe hier:

    http://cid-d5e5bd21dbf5e4e9.office.live.com/self.aspx/ng^_demo/ng^_Fragen/BGW^_Example.zip

    ein kleines Beispiel für die Verwendung eines BackgroundWorker-Threads via Designer bereitgestellt.

    Bitte beachte dabei die Eigenschaft backgroundWorker1.WorkerReportsProgress, die hier im Designer auf true gestellt wurde.

    Viele Grüße,

      Thorsten

    Mittwoch, 18. August 2010 07:41