Autor Beitrag
Nitr0
Hält's aus hier
Beiträge: 11



BeitragVerfasst: So 13.04.08 15:40 
Hi,
habe ein Problem.
Ich will in Delphi ein Bild, das auf eine Leinwand (Canvas), die "in" einer Paintbox steckt, gemalt wurde, per SaveImageDialog (oder SaveDialog, spielt eigentlich keine Rolle) speichern. Das Problem ist nur, sobald das Fenster fürs Speichern geöffnet wird, wird die Canvas gelöscht, also wird immer nur ein leeres Bild gespeichert.
Habe schon probiert, vor dem Speichern ein Canvas.Lock durchzuführen und bei OnClose oder OnCanClose vom SaveDialog wieder zu Unlocken, aber dabei hängt sich meistens das Programm auf.
Wer kann mir helfen?
Danke schonmal. ;)
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: So 13.04.08 17:17 
Das Locken ist für Thread-sichere Anwendungen.

Du hättest aber unmittelbar danach eh ein Problem, da man Canvas nicht einfach so speichern kann. Lösung:
-TBitmap erzeugen
-Canvas rein kopieren
-Dialog aufrufen
-Bitmap speichern
-Freigeben nicht vergessen

Hth,
Martok

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Nitr0 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: So 13.04.08 21:15 
Ja, diese Möglichkeit habe ich danach ausprobiert.
Dazu habe ich folgendes gecodet:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.Button5Click(Sender: TObject);
   var
   Zwischenspeicher:TCanvas;
   _Rect:TRect;
begin
   _Rect := Rect(Paintbox1.Left,Paintbox1.Top,Paintbox1.Left+PaintBox1.Width,Paintbox1.Top+PaintBox1.Height);
   Zwischenspeicher:=Canvas.Create;
   Zwischenspeicher.CopyRect(_Rect,Paintbox1.Canvas,_Rect);
   if SavePictureDialog1.Execute then SaveCanvas(Zwischenspeicher,SavePictureDialog1.FileName);
end;


SaveCanvas ist definiert wie folgt:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure SaveCanvas(SaveCanvas: TCanvas; FileName: string);
var
  Bmp: TBitmap;
  MyRect: TRect;
begin
  Bmp := TBitmap.Create;
  try
    MyRect := SaveCanvas.ClipRect;
    Bmp.Width := MyRect.Right - MyRect.Left;
    Bmp.Height := MyRect.Bottom - MyRect.Top;
    Bmp.Canvas.CopyRect(MyRect, SaveCanvas, MyRect);
    Bmp.SaveToFile(FileName);
  finally
    FreeAndNil(Bmp);
  end;
end;


Doch damit klappt es auch nicht.
Wenn ich einfach nur SaveCanvas mache, klappt es. Nur, wenn der Dialog geöffnet wird geht es nicht.
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: Mo 14.04.08 08:15 
probiers mal so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.Button5Click(Sender: TObject);
  var
  Zwischenspeicher:TCanvas;
  _Rect:TRect;
  FName: String;
begin
  _Rect := Rect(Paintbox1.Left,Paintbox1.Top,Paintbox1.Left+PaintBox1.Width,Paintbox1.Top+PaintBox1.Height);
  Zwischenspeicher:=Canvas.Create;
  Zwischenspeicher.CopyRect(_Rect,Paintbox1.Canvas,_Rect);
  if SavePictureDialog1.Execute then begin
    FName := SavePictureDialog1.Filename;
    SaveCanvas(Zwischenspeicher,FName);
  end;
end;


lg elundril

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
Nitr0 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 14.04.08 20:22 
Danke erstmal auch für den Post.
Macht aber leider keinen Unterschied.
Es wird jetzt immer nur ein Bild vom Programmfenster gespeichert das dort wo der SaveDialog ist eine weiße Fläche und irgendeinen Speichern Icon hat. Aber das war auch schon davor so, ohne die FName Variable.
Ich häng das erzeugte Bild mal an... ;)
Einloggen, um Attachments anzusehen!
Nitr0 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Di 15.04.08 22:46 
Habe es selber gelöst, danke trotzdem. ;)

Andere Frage: Ich will es jetzt schaffen, ein Bild per OpenPictureDialog in die Canvas reinzuladen. Habe dazu Folgendes geschrieben:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm1.Button6Click(Sender: TObject);
var
   Bild : TBitmap;
begin
   if OpenPictureDialog1.Execute then begin
                                         Bild.LoadFromFile(OpenPictureDialog1.FileName);
                                         Paintbox1.Canvas.Draw(0,0,Bild);
                                      end;
end;


Doch er bringt mir immer die Fehlermeldung dass die Variable Bild wahrscheinlich nicht initialisiert wurde.
Wie kann ich das beheben?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19333
Erhaltene Danke: 1750

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 16.04.08 04:55 
Du musst von einer Klasse zuerst eine Instanz erzeugen und diese in die Variable tun, danach kannst du damit arbeiten:
ausblenden Delphi-Quelltext
1:
Bild := TBitmap.Create;					
Wichtig: Du musst den Speicher dieser Instanz auch wieder freigeben!
ausblenden Delphi-Quelltext
1:
Bild.Free;					


Dann noch etwas anderes:
Ich würde statt einer TPaintBox ein TImage benutzen, dann hast du auch nicht das Problem, dass deine Zeichenfläche gelöscht wird, wenn ein anderes Fenster davor geschoben wird.
Nitr0 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mi 16.04.08 13:16 
Danke schonmal, ich probier das gleich mal aus. :)
Das mit dem TImage hab ich mir auch schon gedacht, im Unterricht haben wir halt mit PaintBox angefangen. ;)