Fragensteller
Form mit Animierten Bild von einer anderen Form aus aufrufen

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
- Bearbeitet Robert BreitenhoferModerator Dienstag, 10. August 2010 07:39 Formatierung
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
-
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 -
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
-
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 -
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 -
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
- Bearbeitet Thorsten Gudera Mittwoch, 18. August 2010 07:45
-
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