Entwickler-Ecke

WinForms - Problem beim Abspeichern eines Bildes


Oliver M. - So 24.04.11 16:56
Titel: Problem beim Abspeichern eines Bildes
Hallo ihr Lieben,
ich habe begonnen ein Bildschirm-Schnappschuss-Programm zu schreiben. Hier mein Codeausschnitt der nicht Funktioniert:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
private void buttonSnapshot_Click(object sender, EventArgs e)
{
  Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
  Graphics g = Graphics.FromImage(bitmap);
  
  g.CopyFromScreen(0000, Screen.PrimaryScreen.Bounds.Size);
  bitmap.Save(GetFreeFile(textBoxLocation.Text)); //ExternalExeption "Allgemeiner Fehler in GDI+."
}

private string GetFreeFile(string dir)
{
  int i = 0;
  string tryPath;
  while (i < 1000)
  {
    tryPath = Path.GetFullPath(dir) + @"\ScreenSave" + i.ToString("0000") + ".bmp";
    if (!File.Exists(tryPath))
      return tryPath;
  }
  throw new Exception("No free File.");
}

(textBoxLocation.Text hat den Wert Path.GetTempPath() + "ScreenSave")

Vielleicht kann mir ja jemand helfen.

MfG Oliver


Trashkid2000 - So 24.04.11 21:31

Hallo,

also nach ein bisschen nachdenken bin ich zu der Erkenntnis gekommen, dass die Exception kommt, wenn der Pfad nicht existiert, also der Ordner "ScreenSave" nicht im Temp-Verzeichnis angelegt ist. Du musst also erstmal den Ordner anlegen, wenn er denn nicht existiert.

Aber zu Deiner Methode "GetFreeFile":
Also, erstens ist das eine schlechte Lösung (wenn überhaupt eine Lösung). Und zweitens ist es eine Endloschleife, denn "i" wird nie hochgezählt. Also wenn "ScreenSave0000.bmp" schon existiert, hängt das Programm.
Und wenn bereits 1000 Bilder gespeichert wurden? Dann kommt immer Deine geschmissene Exception. Und dann soll der Benutzer selber den Temp-Ordner bzw. den Ordner leeren?

Also, entweder fragst Du die Dateinamen in dem Ordner ab, fragst den "höchsten" Zähler ab und speicherst den Screrenshot dann unter dem Dateinamen +1. Aber besser noch ist der Einsatz einer Guid für den neuen Dateinamen. Da kannst Du Dir sehr sicher sein, dass der Dateiname kombiniert mit der Guid noch nicht existiert.
Aber die Frage dabei ist ja: brauchst Du die Dateien nur temporär, oder brauchst Du die Datei bzw. den Dateinamen noch für andere Zwecke?
LG


Oliver M. - Mo 25.04.11 15:40

Vielen Dank,
so funktioniert es besser. Danke wegen i++. Ich habe das schlichtweg übersehen. Die Exception("No free File.") wird außerhalb der Methode buttonSnapshot_Click abgefangen. Aber das mit dem Guid musst du mir noch mal erklären.
Die Datei wird so lange aufgehoben, bis der Benutzer sie löscht oder, wenn eingestellt ist dass die Dateien beim beenden gelöscht werden, bis das Programm beendet wird.
MfG Oliver


Trashkid2000 - Mo 25.04.11 16:19

user profile iconOliver M. hat folgendes geschrieben Zum zitierten Posting springen:
Aber das mit dem Guid musst du mir noch mal erklären.
Naja, ich meine das so, dass der Filename mit der Generierung einer Guid gebildet wird, also so:

C#-Quelltext
1:
string uniqueFilename = string.Format("{0}.bmp", Guid.NewGuid());                    

Aber eine Sortierung der Dateien nach dem Namem kannst Du so halt vergessen.
Achso, und Dispose() oder besser noch using-Blöcke bei dem Bitmap und der Graphics-Objekt nicht vergessen.
LG


Oliver M. - Mo 25.04.11 16:40

Ein Guid gibt mir so eine komische Zahlen- / Zeichenfolge. Aber woher weis der Guid ob die Zahlen- /Zeichenfolge nicht schon belegt ist??? Und was ist der Vorteil einer Guid im Gegensatz zu meiner string GetFreeFile(string)?

Zitat:
using-Blöcke bei dem Bitmap und der Graphics-Objekt nicht vergessen.

:gruebel: Wo soll ich da using-Blöcke einbauen? Die sind doch für using System.Drawing; usw. :gruebel:
Und g.Dispose() muss hinter

C#-Quelltext
1:
g.CopyFromScreen(0000, Screen.PrimaryScreen.Bounds.Size);                    

Stimmt, ich habe da so ne blasse Errinerung... Aber was bringt Dispose()?

MfG Oliver


jaenicke - Mo 25.04.11 16:55

user profile iconOliver M. hat folgendes geschrieben Zum zitierten Posting springen:
:gruebel: Wo soll ich da using-Blöcke einbauen? Die sind doch für using System.Drawing; usw. :gruebel:
Nicht nur, siehe Doku:
http://msdn.microsoft.com/de-de/library/sf0df423.aspx


Oliver M. - Mo 25.04.11 17:05

Cool! Wieder was dazugelernt. Ich wusste nicht dass das geht.
Aber wo soll ich die in den Code einbauen?
MfG Oliver


jaenicke - Mo 25.04.11 17:36


C#-Quelltext
1:
2:
3:
4:
  using(Graphics g = Graphics.FromImage(bitmap))
  {
    g.CopyFromScreen(0000, Screen.PrimaryScreen.Bounds.Size);
  }


Oliver M. - Mo 25.04.11 18:26

Ja, doch. Dieser Einsatz von using macht Sinn. :zustimm:
Danke.