![]() |
TImages verwalten
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe ein Programm zum Scannen. Dieses legt die Bilder zunächst nacheinander in einer
Delphi-Quellcode:
ab und speichert die dann als png-Dateien.
TImageList
Jetzt möchte ich das Programm gern erweitern. Dazu sollen die Bilder statt in einer TImageList jeweils erst als
Delphi-Quellcode:
nebst 3
TImage
Delphi-Quellcode:
in einer
TRadioButtons
Delphi-Quellcode:
untereinander angezeigt werden. Hintergrund ist der, dass die Bilder standardmäßig in schwarzweiß eingescannt werden. Allerdings soll/muss es hin und wieder auch mal Fotos geben. Auch diesen Fall löst mein Programm im Ansatz. Allerdings gibt es immer wieder Nutzer, die einfachen Text mit 16 Mio. Farben einscannen und damit sinnloser Weise riesige Dateien erzeugen. Die Bilder sollen daher selbst beim Einscannen in Farbe nachträglich umgewandelt werden können - dafür die TRadioButtons.
TScrollBox
Ein Screenshot, wie ich es gern hätte, ist angehängt. Wie man TImage und TRadioButton zur Laufzeit erzeugt, ist klar. Klar ist mehr oder weniger auch die Umwandlung. Es geht also wirklich nur um das Vorhalten/Anzeigen für den Benutzer zur Laufzeit. Meine Überlegung geht jetzt dahin, Image und Buttons in ein Object zu packen und dann das ganze in einer Liste abgeleitet von
Delphi-Quellcode:
zu organisieren. In dieser kann man mit
TStringList
Delphi-Quellcode:
derartiges erledigen.
AddObject();
Wäre das völlig abwegig? Falls ja, wie macht man es richtig[tm]? Ich lese gern selbst. Im Moment fehlen mir aber die passenden Suchworte für mein Problem. Daher bitte nicht gleich meckern, falls das Problem schon einmal ausführlich behandelt wurde, sondern lieber eine Links setzen. Danke. Gruß, Alex |
AW: TImages verwalten
Zunächst würde ich die Bilder nicht komplett im Speicher behalten sondern jeden Scan direkt auf die Platte schreiben und merken (in einer Liste).
Für eine Komponenten-Komposition (TImage, TRadioButtons) eignen sich Frames sehr schön. Einfach ein Frame bauen und dann für jeden Scan eine Instanz erzeugen und in die Scrollbox packen. Die Bilder werden für die Ansicht ja nicht in der vollen Auflösung benötigt, somit wäre es auch ratsam die Bilder selber nur in einer reduzierten Auflösung für die Anzeige bereitzustellen. Mit einer PaintBox könnte man auch auf gecachte Bilder zurückgreifen, die im Hintergrund geladen werden. Auch das Umrechnen der Bilder sollte in einem Thread erfolgen, somit musst du eh mit Threads hantieren ;) |
AW: TImages verwalten
Liste der Anhänge anzeigen (Anzahl: 1)
Danke für die Antwort.
Zitat:
Zitat:
Zitat:
Zum zweiten - das kommt noch :-D Und nun zu meiner Lösung: Ich hatte bei der Suche nach Frames im Netz die Möglichkeit entdeckt, Formulare anzudocken. Das klappt prima in einer
Delphi-Quellcode:
. Und der Vorteil (mit Frames kenne ich mich nicht aus) ist der, dass ich die Formulare schon zu Entwurfszeit basteln kann. Ich habe jetzt bloß noch ein Problem:
TPageControl
Wie schaffe ich es in der TPageControl auf das Schließen eines Fensters zu reagieren, so dass ich den TabSheet ebenfalls schließen kann? Ich habe meinen Code mal angehängt. Wenn dazu jemand eine Lösung hätte, wäre mein Problem - wenn auch anders als in der Überschrift evtl. gedacht - gelöst. Gruß und danke für den Push in diese Richtung! Alex |
AW: TImages verwalten
Die Anwendung wird nicht aufgehalten, wenn die Aktionen in einem Thread erfolgen (speichern, laden, umrechnen) ;)
Zum Schließen des Tabs musst du eigentlich rein gar nichts machen ... ok bis auf eins:
Delphi-Quellcode:
Wenn du jetzt das Formular schließt, dann wird es durch das Setzen von
type
TDockForm = clas( TForm ) protected // Ich könnte auch den Event OnClose nehmen, da ich aber von dieser Form // weitere ableiten möchte, ist dieser Weg etwas robuster :o) procedure DoClose( var Action: TCloseAction ); override; end; TDockFormClass = class of TDockForm; procedure TDockForm.DoClose( var Action: TCloseAction ); begin Action := caFree; inherited; // <- dort wird der Event OnClose gefeuert end;
Delphi-Quellcode:
auch automatisch zerstört, was wiederum automatisch den Tab aus dem PageControl entfernt :)
Action := caFree
Vorausgesetzt, die Form wird auch so dort eingedockt:
Delphi-Quellcode:
Wenn du diese
procedure TMyForm.DockNewForm( APageControl : TPageControl; ADockFormClass : TDockFormClass );
var LForm : TDockForm; begin LForm := TDockFormClass.Create( APageControl ); try LForm.ManualDock( APgeControl, nil, alClient ); LForm.Visible := True; LForm := nil; finally LForm.Free; end; end;
Delphi-Quellcode:
als Basis für deine weiteren DockFOrms nimmst, dann kannst du nach Belieben dort die unterschiedlichsten DockForms an dein PageControl hängen und diese werden dann beim Schließen automatisch aufgeräumt und der Tab geschlossen :)
TDockForm
|
AW: TImages verwalten
Zitat:
Ich kann aber nirgends ein Ereignis wie
Delphi-Quellcode:
finden. Und dann habe ich noch das Problem wo bzw. wie ist
onDockNewForm
Delphi-Quellcode:
definiert?
TDockFormClass
[edit] Und noch ein Problem fällt mir ein: Wie greife ich auf die einzelnen Komponenten (TImage etc.) nach dem Erstellen des angedockten Forms zu? Der Benutzer soll die Bilder erst scannen. Dann mit dem Button Bilder, die er nicht haben will, löschen können und schließlich über einen zentralen Save-Button alle Bilder nacheinander abspeichern. Letzteres soll dann über einen Thread vom Hauptformular erfolgen. Ich muss also irgendwie rankommen... [/edit] Gruß, Alex |
AW: TImages verwalten
Zitat:
Delphi-Quellcode:
procedure TMyForm.DockNewForm( APageControl : TPageControl; ADockFormClass : TDockFormClass ) : TDockForm;
var LForm : TDockForm; begin LForm := TDockFormClass.Create( APageControl ); try LForm.ManualDock( APgeControl, nil, alClient ); LForm.Visible := True; Result := LForm; LForm := nil; finally LForm.Free; end; end; Zitat:
Delphi-Quellcode:
type
TDockForm = class( TForm ) protected // Ich könnte auch den Event OnClose nehmen, da ich aber von dieser Form // weitere ableiten möchte, ist dieser Weg etwas robuster :o) procedure DoClose( var Action: TCloseAction ); override; end; TDockFormClass = class of TDockForm; // <--- DA Zitat:
Delphi-Quellcode:
drin ist? Das wird für die Anzeige benötigt ... aus und Ende.
TImage
Erstelle dir ein Daten-Objekt, was alle Informationen beinhaltet und merke dir dort alle Informationen zu jedem gescannten Bild und organisiere diese in einer Liste. Zu jedem Daten-Objekt gibt es dann eine Form (der du das zugehörige Daten-Objekt an die Hand gibts), die die Inhalte aus dem Daten-Objekt anzeigen und auch die Eingaben des Benutzers dort ablegen kann. Wenn der Benutzer fertig ist, dann gehts du einfach durch deine Liste und arbeitest die einzelnen Bilder ab. Die einzelnen Forms interessieren nicht mehr ;) |
AW: TImages verwalten
Danke für die Erläuterungen.
Zitat:
Aber müsste es nicht richtiger Weise dann
Delphi-Quellcode:
statt
function
Delphi-Quellcode:
heißen?
procedure
Und wo genau wird die Instanz übergeben (Result:=... oder Var in der Definition der Procedure)? Zitat:
Zitat:
|
AW: TImages verwalten
Zitat:
Zitat:
|
AW: TImages verwalten
Zitat:
Delphi-Quellcode:
die Instanz freigegeben.
finally
Das ist eigentlich eine sehr übliche und sinnvolle Vorgehensweise wenn man nicht auf Speicherlecks steht.
Delphi-Quellcode:
Auch wenn es sich im Beispiel um eine Komponente mit Owner handelt, was für eine korrekte Freigabe durch den Owner sorgt. Eine ungenutzte Instanz im Speicher ist zuviel und solche Fehler (Speicher läuft im Betrieb voll) sind nachher nur schwer zu finden, denn beim Beenden gibt es kein Speicherleck, dafür ist irgendwann der Speicher voll und die Anwendung verabschiedet sich.
function FooFactory : TFoo;
var LFoo : TFoo; begin LFoo := TFoo.Create; try ... Result := Lfoo; LFoo := nil; // auf nil setzen finally // bei einer Exception wird die Instanz freigegeben, // sonst nicht, denn dann zeigt LFoo ja auf nil ;o) LFoo.Free; end; end; |
AW: TImages verwalten
Danke. Es wird langsam klarer und zeigt sich, dass es für Gelegenheitprogrammierer wie mich schwer werden dürfte. Ich habe jetzt folgendes zusammengebastelt. Allerdings weiß ich nicht, wie ich herausbekomme, ob der Benutzer ein Form selbst mit Close "zerstört" hat:
Delphi-Quellcode:
[edit]
Type
TMainForm = Class(TForm) BtnAdd : TButton; BtnInfo : TButton; PCPics : TPageControl; Procedure FormCreate(Sender: TObject); Procedure BtnAddClick(Sender: TObject); Procedure BtnInfoClick(Sender: TObject); Procedure FormDestroy(Sender: TObject); Protected fCount : Integer; fPicList : TList; End; Var MainForm : TMainForm; Implementation {$R *.dfm} Procedure TMainForm.FormCreate(Sender: TObject); Begin fCount:=0; fPicList:=TList.Create; End; Procedure TMainForm.BtnAddClick(Sender: TObject); Var aPNG : TPngImage; lForm : TDockForm; Begin aPNG:=TPngImage.Create; Try aPNG.LoadFromFile('.TestBilder\_0001.png'); aPNG.RemoveTransparency; lForm:=TDockFormClass.Create(PCPics); Try lForm.ManualDock(PCPics, nil, alClient); lForm.Visible:=True; LForm.IMGScan.Picture.Bitmap.Assign(aPNG); Inc(fCount); lForm.Caption:='Bild ' + FormatFloat('0,', fCount); fPicList.Add(lForm); // <- in Liste merken lForm:=nil; // 1:1 übernommen Finally lForm.Free; // 1:1 übernommen PCPics.ActivePageIndex:=Pred(PCPics.PageCount); End; Finally aPNG.Free; End; End; Procedure TMainForm.BtnInfoClick(Sender: TObject); Var I : Integer; lDockForm : TDockForm; Begin If (fPicList.Count = 0) Then Exit; I:=PCPics.ActivePageIndex; lDockForm:=fPicList.Items[I];// <- so greife ich jetzt zu. With lDockForm Do Try ShowMessage('Original' + #09 + BoolToStr(RBorgjpg.Checked, True)); Finally End; End; Procedure TMainForm.FormDestroy(Sender: TObject); Begin Try While (fPicList.Count > 0) Do fPicList.Delete(0); Finally fPicList.Free; End; End; End. Also der Zugriff klappt. Bleibt die Frage, wie ich herausbekomme, ob der Benutzer eine Form gelöscht hat... [/edit] |
AW: TImages verwalten
Zitat:
Delphi-Quellcode:
Result := TFoo.Create;
try ... except Result.Free; raise; end; |
AW: TImages verwalten
Ich habe das doch so geschrieben, wie das was er machen soll. Und
Delphi-Quellcode:
ist ein Ressourcen-Schutzblock - wenn ich mich da richtig erinnere - und genau den will ich haben und darum schreibe ich ihn so.
try finally
|
AW: TImages verwalten
Zitat:
OK, es funktioniert Beides, aber IMHO ist es mit'm Finally etwas schneller missverständlicher.
Delphi-Quellcode:
LFoo := TFoo.Create;
try ... LFoo := nil; // Womöglich auch noch tief in irgendwelchen IFs versteckt auf nil setzen. ... finally LFoo.Free; // IMMER freigeben, außer irgendwo anders wurde vorher die Variable heimlich auf nil gesetzt. end;
Delphi-Quellcode:
Ich weiß, im Falle von Free muß nicht geprüft werden, da es das selber macht, aber irgenwie sollte man hier schon, beim Free, einen Hinweis geben ... sei es in Form eines Codes oder als Kommentar, daß sich oben irgendwo noch ein :=nil versteckt.
Result := TFoo.Create;
try ... except Result.Free; // NUR freigeben, wenn es geknallt hat. raise; end;
Delphi-Quellcode:
LFoo := TFoo.Create;
try ... LFoo := nil; ... finally if Assigned(LFoo) then LFoo.Free; end; |
AW: TImages verwalten
Das werde ich definitiv nicht machen, denn ich schreibe keine Kommentare, die sich auf Basis-Funktionalitäten (
Delphi-Quellcode:
prüft selber auf assigned) beziehen, noch füge ich unnützen Code hinzu
TObject.Free
Delphi-Quellcode:
). Ich schreibe keine Tutorials sondern Anwendungen und wer das verstehen möchte, der soll die Sprache beherrschen.
if (Assigned( LFoo ) then LFoo.Free;
Wie man Instanzen aufräumt sollte eigentlich bekannt sein und gehört zum Basiswissen:
Delphi-Quellcode:
procedure Example;
var LFoo : TFoo; LBar : TBar; begin LFoo := nil; LBar := nil; try LFoo := TFoo.Create; while LFoo.NeedsMore do begin LBar := TBar.Create; LFoo.InteractWith( LBar ); FreeAndNil( LBar ); end; finally LFoo.Free; LBar.Free; end; |
AW: TImages verwalten
Dein
Delphi-Quellcode:
wird immer ausgeführt, macht aber meistens (hoffentlich immer) nichts, was schon einen Kommentar wert wäre. :stupid:
finally LFoo.Free; end;
|
AW: TImages verwalten
Danke für Eure erhellenden Antworten. Natürlich lerne ich gern dazu. Einen "Krieg" anzuzetteln, war das Letzte, was ich mit meiner Fragestellung wollte.
Zitat:
Delphi-Quellcode:
Ich habe jetzt aber konkret das Problem, dass meine (Object)Liste und die tatsächlich in den TabSheets vorhandenen Forms auseinanderfallen können. Denn mir fehlt immer noch das Wissen und auch eine Idee, wie die angedockte Form den Umstand des Schließens und damit das Löschen aus dem Tabsheet an das Hauptprgramm/-form weiterleitet.
Procedure Example;
Var SL : TIrgendwas; Begin SL:=TIrgendwas.Create; Try SL.TuEtwas; Finally SL.Free; End; End; Die Änderung des TabSheets wird mir über
Delphi-Quellcode:
mitgeteilt. Aber wie filtere ich jetzt das verschwundene Fenster aus meiner Liste? Eine Idee wäre natürlich einen Zugriff zu machen, damit dann künstlich eine Exception zu erzeugen und das betreffende Fenster zu löschen; so klappt es jedenfalls. Ich kann mir aber kaum vorstellen, dass das so legitim ist:
TPageControl.OnChange
Delphi-Quellcode:
Daher eben nochmal meine Frage, wie man das macht richtig?
Procedure TMainForm.PCPicsChange(Sender: TObject);
Var I : Integer; lDockForm : TDockForm; Begin I:=0; While (fPicList.Count > I) Do Begin lDockForm:=fPicList.Items[I]; Try lDockForm.RBorgjpg.Checked; Inc(I); // <- hat geklappt, ist also noch vorhanden Except fPicList.Delete(I); End; End; End; Gruß, Alex |
AW: TImages verwalten
Die ganzen DockFormen werden ja im Hauptformular/Programm kreiert.
Da könntest du denen doch eine Callback-Funktion mitgeben, die im OnClose des DockFormulars ausgelöst wird. ![]() |
AW: TImages verwalten
Richtiger wäre es den ganzen Kram zu trennen.
Es gibt eine Liste mit Datenobjekten
Delphi-Quellcode:
Für das DatenObjekt gibt es eine Form, die dieses DatenObjekt anzeigen kann
// ein Datenobjekt
TImageData = class property Filename : string; end;
Delphi-Quellcode:
Die MainForm kann nun aus der Liste mit den DatenObjekten die passenden Forms erzeugen und natürlich auch wieder entfernen.
TImageView = class( TDockForm )
property ImageData : TImageData; end;
Delphi-Quellcode:
Nach jeder Änderung an der
TMainForm = class( TForm )
FDataList : TObjectList; FViewList : TObjectList; procedure PresentDataList; end; procedure TMainForm.PresentDataList; var LView : TImageView; begin for LIdx := 0 to FDataList.Count - 1 do begin if LIdx < FViewList.Count then LView := FViewList[LIdx] as TImageView else begin LView := TImageView.Create( PageControl1 ); FViewList.Add( LView ); LView.ManualDock( PageControl1, nil, alClient ); end; LView.Visible := false; LView.ImageData := FDataList[LIdx] as TImageData; LView.Visible := true; end; // überflüssige Views entfernen for LIdx := FViewList.Count - 1 downto FDataList.Count do begin LView := FViewList[LIdx] as TImageView; FViewList.Delete( LIdx ); LView.Close; end; end;
Delphi-Quellcode:
(Sortieren, Hinzufügen, Entfernen) ruft man einfach
FDataList
Delphi-Quellcode:
auf und der Keks ist gegessen.
PresentDataList
Auf der MainForm ist nun ein Button um das aktuell angezeigte Bild zu entfernen, dann muss man folgendes ausführen
Delphi-Quellcode:
Richter wäre es aber auch hier eine sprechendere Programmierung zu wählen
procedure TMainForm.Button1Click( Sender : TObject );
begin FDataList.Delete( PageControl1.TabIndex ); PresentDataList; end;
Delphi-Quellcode:
Wenn man nämlich aus der ImageView heraus dieses Entfernen auslösen möchte, dann gibt man jeder ImageView einfach dieses als Event mit
procedure TMainForm.Button1Click( Sender : TObject );
begin RemoveCurrentItem; end; procedure TMainForm.RemoveCurrentItem; begin RemoveItem( FDataList[PageControl1.TabIndex] ); end; procedure TMainForm.RemoveItem( AItem : TObject ); begin FDataList.Remove( AItem ); PresentDataList; end;
Delphi-Quellcode:
und in der ImageView wird das dann einfach aufgerufen und alles passiert von selber
procedure TMainForm.PresentDataList;
... LView.OnRemoveItem := RemoveItem; ...
Delphi-Quellcode:
Das möchte ich jetzt aber nicht weiter ausführen, sonst sprengt es den Rahmen.
procedure TImageView.RemoveButtonClick( Sender : TObject );
begin OnRemoveItem( ImageData ); end; Die
Delphi-Quellcode:
Form muss jetzt natürlich im
TImageView
Delphi-Quellcode:
Event die Daten aus dem
OnShow
Delphi-Quellcode:
lesen und entsprechend anzeigen. Hier kann man in dem Setter von ImageData auch noch ein Flag setzen, ob sich ImageData überhaupt geändert hat und kann sich das erneute Einlesen sparen.
ImageData
(da das mit dem Resourcenschutzblock nur zu Verwirrung führt, habe ich mal alles weggelassen, was nicht unbedingt notwendig ist) |
AW: TImages verwalten
Mir ist nicht klar für was du überhaupt ein angedocktes Fenster benötigst.
Ich vermute du vermischt die Anzeige und das Halten der Daten. Wenn zum Bild zusätzliche Einstellungen gehören, dann erweitere einfach die Klasse.
Delphi-Quellcode:
Für die Anzeige genügt eine Paintbox, im OnPaint wird das aktuell ausgewählte Bild mit seinen Einstellungen gezeichnet.
TMyColorStyle = (mycsDefault, mycsGray, mycsBlackAndWhite);
TMyPicture = class(TPicture) private FColorStyle: TMyColorStyle; protected procedure Draw(ACanvas: TCanvas; const Rect: TRect); override; procedure DrawBlackAndWhite((ACanvas: TCanvas; const Rect: TRect); procedure DrawGray(ACanvas: TCanvas; const Rect: TRect); published property ColorStyle: TMyColorStyle read FColorStyle write FColorStyle; end; TMyPictureList = TObjectList<TMyPicture>; procedure TMyPicture.Draw(ACanvas: TCanvas; const Rect: TRect); begin case FColorStyle of mycsGray: DrawGray(ACanvas, Rect); mycsBlackAndWhite: DrawBlackAndWhite(ACanvas, Rect); else inherited Draw(ACanvas, Rect); end; end; Den Steuerelementen werden die zum Bild gehörenden Einstellungen zugewiesen. Vereinfacht:
Delphi-Quellcode:
TMyForm = class(TForm)
procedure DoOnTabChanged(Sender: TObject); procedure DoOnRadioClick(Sender: TObject); procedure DoOnPaintBoxPaint(Sender: TObject); private FPictureList: TMyPictureList; function GetCurrentPicture: TMyPicture; end; procedure TMyForm.DoOnTabChanged(Sender: TObject); var Picture: TMyPicture; ColorStyle: TMyColorStyle; begin Picture := GetCurrentPicture; if Assigned(Picture) then ColorStyle := Picture.ColorStyle else ColorStyle := mycsDefault; RBtnDefault.Checked := ( ColorStyle = mycsDefault ); RBtnGray.Checked := ( ColorStyle = mycsGray ); RBtnBW.Checked := ( ColorStyle = mycsBlackAndWhite ); {neu zeichnen} PaintBox.Invalidate; end; procedure TMyForm.DoOnRadioClick(Sender: TObject); var Picture: TMyPicture; ColorStyle: TMyColorStyle; begin ColorStyle := mycsDefault; Picture := GetCurrentPicture; if Assigned(Picture) then begin if RBtnBW.Checked then ColorStyle := mycsBlackAndWhite else if RBtnGray.Checked then ColorStyle := mycsGray; end; Picture.ColorStyle := ColorStyle; {neu zeichnen} PaintBox.Invalidate; end; procedure TMyForm.DoOnPaintBoxPaint(Sender: TObject); begin PaintBox.Canvas.StretchDraw(PaintBox.ClientRect, GetCurrentPicture); end; function TMyForm.GetCurrentPicture: TMyPicture; var idx: Integer; begin idx := TabControl.TabIndex; if (idx >= 0) and (idx < FPictureList.Count) then Result := FPictureList[idx] else Result := nil; end; |
AW: TImages verwalten
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Ich finde aber die Forms nicht schlecht. Denn ich kann den Code für diese separat verwalten, was den Code später sogar besser warten lässt. Und ich möchte auch keine Querverweise haben. Das heißt, die Fenster wissen nichts voneinander und kümmern sich - bei Bedarf - um das Umwandeln selbst. Es verkompliziert es daher, eine Liste mit den Bilder im Hauptprogramm (=Code des MainForm) vorzuhalten und zu warten - mit Ausnahme der Liste für die Instanzen der Fenster. Ich hatte bereits in meinem ersten Post eingestellt, wie ich es gern hätte. Genau so sieht es jetzt auch aus. Der Zugriff auf die Bild-Daten klappt. Die Bilder sollen auch nicht in Grau angezeigt, sondern nur in Grau gespeichert werden. Ich habe dennoch noch einmal einen Screenshot angehängt. |
AW: TImages verwalten
Ich bin jetzt (urlaubsbedingt) schon etwas weiter:
Mein DockForm bietet ein Ereignis an, welches vor dem Löschen ausgelöst wird und die Adresse des DockForms übergibt. Damit bekommt das Hauptfenster mit, das und was gelöscht wurde. Danke insoweit für Eure wertvollen Tipps! Jetzt wollte ich das gern auf Speicherlecks untersuchen, bevor ich weitermache. Dazu habe ich mir FastMM4991 runtergeladen. Ich hatte FastMM schon vor Jahren benutzt. Meiner Erinnerung nach muss man es einfach als erste Unit in die dpr-Datei einbinden. Anderes Infos habe ich trotz Suche im Forum nicht gefunden. Kann es sein, dass FastMM unter Delphi XE5 nicht mehr funktioniert? Es kommt keine Meldung. Auch dann nicht, wenn ich in FormCreate einfach folgenden Code einfüge:
Delphi-Quellcode:
FastMM scheint schon lange nicht mehr gepflegt und explizit zu XE5 und FastMM konnte ich nichts finden.
With tStringList.Create Do
Begin Append('Datenmüll'); End; Was mache ich falsch? Falls FastMM nicht mehr funktioniert, womit erforscht man denn heutzutage Speicherlecks? Gruß, Alex |
AW: TImages verwalten
Delphi-Quellcode:
ist seit ??? in Delphi integriert, wird also schon direkt mitgeliefert.
FastMM
Wenn du den Bericht über Speicherlecks am Ende haben möchtest, dann musst du das lediglich einschalten mit
Delphi-Quellcode:
(am besten gleich am Anfang in der Projekt-Datei)
ReportMemoryLeaksOnShutdown := true;
|
AW: TImages verwalten
Zitat:
Das externe FastMM braucht man eigentlich nur, wenn man z.B. die erweiterten Debuggingfunktionen nutzen möchte. (Prüfen auf Pufferüberläufe, Schreiben nach Free, wer hat was wann erstellt usw.) FastMM funktioniert noch und ja, es muß als Erstes in die DPR (außer man benutzt Packages, denn da muß es als Erstes in die DPK des ersten Packages) |
AW: TImages verwalten
Danke!
Und da ich Delphi jetzt einfach mal so glaube, freue ich mich, dass mein Code bis hierhin keine Speicherlecks produziert hat. Eine letzte Frage habe ich dann aber trotzdem noch: Ich hatte ![]()
Delphi-Quellcode:
Wieso geht es so nicht?
// Aus diesem hier ...
Procedure TMainForm.FormKeyDown(Sender: TObject; Var Key: Word; Shift: TShiftState); Var lDockForm : TDockForm; Begin If (PCPics.PageCount = 0) Then Exit; If (Key = VK_DELETE) Then Begin lDockForm:=fPicList.Items[PCPics.ActivePageIndex]; lDockForm.BtnDelete.Click; End; End; // ... soll auch an mehreren anderen Stellen so etwas hier werden: Procedure TMainForm.FormKeyDown(Sender: TObject; Var Key: Word; Shift: TShiftState); Begin If (PCPics.PageCount = 0) Then Exit; If (Key = VK_DELETE) Then With (fPicList.Items[PCPics.ActivePageIndex] As TDockForm) Do BtnDelete.Click; // geht auch nicht :-) (fPicList.Items[PCPics.ActivePageIndex] As TDockForm).BtnDelete.Click; End; Kann man es irgendwie (anders) machen? [edit] Ich wäre nicht auf die Idee gekommen, dass es mind. 3 Varianten gibt, wie man casten kann. So klappt es:
Delphi-Quellcode:
Aus 8 Zeilen 3 gemacht. Sehr schön.
Procedure TMainForm.FormKeyDown(Sender: TObject; Var Key: Word;
Shift: TShiftState); Begin If (PCPics.PageCount = 0) Then Exit; If (Key = VK_DELETE) Then TDockForm(fPicList.Items[PCPics.ActivePageIndex]).BtnDelete.Click; End; [/edit] Gruß, Alex |
AW: TImages verwalten
Kürzer heißt ja nicht unbedingt übersichtlicher/lesbarer, sprich ich finde den 8-Zeiler verständlicher, aber das ist ja bekanntlich Geschmacksache. Aber getreu dem Motto Wenn-Schon-Denn-Schon würde ich dann aber auch einen Zweizeiler draus machen:
Delphi-Quellcode:
So fällt auch das unschöne (ich weiß: auch weider Geschmacksache) vorzeitige exit weg.
If (Key = VK_DELETE) And (PCPics.PageCount > 0) Then
TDockForm(fPicList.Items[PCPics.ActivePageIndex]).BtnDelete.Click; |
AW: TImages verwalten
ReportLeaksOnShutdown zeigt natürlich nur Speicherlecks, die beim Beenden der Anwendung noch bestehen. Ist also z.B. nicht geeignet um 24/7 Anwendungen Lecks zu finden, wenn Objekte mit dem Hauptform als Owner erstellt werden. (Soll es ja geben)
|
AW: TImages verwalten
Zitat:
Einen Zweizeiler kann ich nicht drauß machen, weil später andere Tastenabfragen hinzukommen werden. Ich fange gerade erst an. Ich mag ein solches Exit auch nicht wirklich aber es spart einen Tab-Einzug und macht den weiteren Code damit lesbarer. Zitat:
Gibt es einen Schalter, mit dem man auch die bösen, unsichtbaren Lecks des Hauptforms herausfindet? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz