![]() |
Delphi-Version: 10.4 Sydney
TPngImage freigeben
Hallo,
ich bin gerade dabei, die MemLeaks aus meinem Programm zu entfernen. Ein Problem habe ich hierbei: Ich lade, je nach Bildschirmauflösung, verschieden große Grafiken über ein Funktion.
Delphi-Quellcode:
Beim Beenden wird mir ein TPngImage und TPngImageList Memory Leak ausgegeben. Wie kann ich das am Ende freigeben? Muss ich die Grafik dem TImage anders übergeben, damit ich das TPngImage in der Funktion freigeben kann?
ImageMain.Picture.Graphic := StartDlg.LoadImgFromResource('Main');
function TStartDlg.LoadImgFromResource(Bezeichner: String): TPngImage; var Png: TPngImage; begin Result := NIL; Png := TPngImage.Create; try // DPI 200% if Screen.PixelsPerInch >= 192 then Png.LoadFromResourceName(HInstance, Bezeichner + '_200') // DPI 150% else if Screen.PixelsPerInch >= 144 then Png.LoadFromResourceName(HInstance, Bezeichner + '_150') // DPI 100% else Png.LoadFromResourceName(HInstance, Bezeichner + '_100'); Result := Png; finally // Png.Free; // kann ich hier nicht freigeben end; end; Danke, für einen Hinweis. |
AW: TPngImage freigeben
Entweder übergibst du ein TPNGImage an die Funktion.
Dann brauchst du keines Freigeben. Oder die Methode erzeugt es und übergibt es. Dann ist der Aufrufer dafür zuständig. Was wird denn mit dem PNG gemacht? Evtl. an ein TImage gehängt? Dann solltest du das TImage als Parameter übergeben. Den beim Zuordnen an das TImage wird eine Kopie des TPNGImage erstellt. |
AW: TPngImage freigeben
Hallo,
pack das TPngImage doch als private Variable in dein TStartDlg. So wie du das hier erzeugst, sollte der Start-Dialog das dann selber freigeben. |
AW: TPngImage freigeben
Danke, ich habe mit für Bernhards Variante entschieden, da noch weitere Formulare auf die Funktion zugreifen.
Zitat:
Delphi-Quellcode:
StartDlg.LoadImgFromResource('Main', ImageMain);
procedure TStartDlg.LoadImgFromResource(Bezeichner: String; MyImage : TImage); var Png: TPngImage; begin Png := TPngImage.Create; try // DPI 200% if Screen.PixelsPerInch >= 192 then Png.LoadFromResourceName(HInstance, Bezeichner + '_200') // DPI 150% else if Screen.PixelsPerInch >= 144 then Png.LoadFromResourceName(HInstance, Bezeichner + '_150') // DPI 100% else Png.LoadFromResourceName(HInstance, Bezeichner + '_100'); MyImage.Picture.Graphic := Png; finally Png.Free; end; end; |
AW: TPngImage freigeben
Moin...8-)
![]() Prinzipiell kann man sowas machen...der constructor ist ja auch nix anderes. Aber der Name der function sollte beinhalten, daß ein object erzeugt wird! :warn:
Delphi-Quellcode:
...dann weiß man, daß man sich selbst um die Freigabe kümmern muß. Persönlich bekomme ich u.a. die Objekte aus der DB und packe sie in eine Liste. Die Liste übernimmt dann die Freigabe. :thumb:
function TStartDlg.LoadImgFromResource(Bezeichner: String): TPngImage;
... function TStartDlg.CreateImgFromResource(Bezeichner: string): TPngImage; |
AW: TPngImage freigeben
Besser den kleinsten gemeinsammen Nenner verwenden, also statt TImage das TPicture.
(Igentlich wäre das Kleineste TGraphic, aber für diesen Aufruf geht es nur bis TPicture)
Delphi-Quellcode:
So kann man die Funktion auch zum internen Laden benutzen, wo man keine große/sichtbare Komponente nutzen möchte.
StartDlg.LoadImgFromResource('Main', ImageMain.Picture);
procedure TStartDlg.LoadImgFromResource(Bezeichner: String; Image: TPicture); Auch wenn nicht mehr nötig, nochmal als Erklärung: Joar, da hier bei der Zuweisung nur den Inhalt des Objektes kopiert und nicht das Objekt übergeben/freigibt wird, mußt du das Result der Funktion am Ende freigeben. Und wie haentschman bereits sagte, sollte man den Namen der Funktion anfassen, um das Verhalten auch gleich mit zu dokumentieren. (Create statt Load oder CreateAndLoadImageFormResource)
Delphi-Quellcode:
Oder als Parameter: Objekt extern erstellen und dort freigeben.
Image := StartDlg.CreateImgFromResource('Main');
try ImageMain.Picture.Graphic := Image; // entspricht ja eigentlich einem ImageMain.Picture.Graphic.Assign(Image); finally Image.Free; end; function TStartDlg.CreateImgFromResource(Bezeichner: String): TPngImage; begin Result := TPngImage.Create; try if Screen.PixelsPerInch >= 192 then Result.LoadFromResourceName(HInstance, Bezeichner + '_200') // DPI 200% else if Screen.PixelsPerInch >= 144 then Result.LoadFromResourceName(HInstance, Bezeichner + '_150') // DPI 150% else Result.LoadFromResourceName(HInstance, Bezeichner + '_100'); // DPI 100% except Result.Free; // wenn es beim Laden knallte, muß es hier schon freigegeben werden, da Result nicht aus fer Funktion raus kommt raise; end; end;
Delphi-Quellcode:
Image := TPngImage.Create;
try LoadImgFromResource('Main', Image); ImageMain.Picture.Graphic := Image; finally Image.Free; end; procedure TStartDlg.LoadImgFromResource(Bezeichner: String; Image: TPngImage); begin if Screen.PixelsPerInch >= 192 then Image.LoadFromResourceName(HInstance, Bezeichner + '_200') // DPI 200% else if Screen.PixelsPerInch >= 144 then Image.LoadFromResourceName(HInstance, Bezeichner + '_150') // DPI 150% else Image.LoadFromResourceName(HInstance, Bezeichner + '_100'); // DPI 100% end; Entspricht deiner letzten Variante, außer * TPicture statt TImage übergeben * die Instanz wird nur erzeugt, wenn noch kein PNG vorhanden ist * die Behandlung des Namen vom dem Ladeaufruf entkoppelt
Delphi-Quellcode:
LoadImgFromResource('Main', ImageMain.Picture);
function TStartDlg.LoadImgFromResource(Bezeichner: String; Picture: TPicture); var Temp: TPngImage; begin if Screen.PixelsPerInch >= 192 then Bezeichner := Bezeichner + '_200' // DPI 200% else if Screen.PixelsPerInch >= 144 then Bezeichner := Bezeichner + '_150' // DPI 150% else Bezeichner := Bezeichner + '_100'; // DPI 100% if not (Picture.Graphic is TPngImage) then begin // wenn TPngImage schon drin ist, muß man es nicht nochmal neu erzeugen Temp := TPngImage.Create; try Picture.Graphic := Temp; // ja, die Behandlung von Graphic ist echt krank, aber das liegt nicht an dir finally Temp.Free; end; end; //Picture.Graphic.LoadFromResourceName(HInstance, Bezeichner); TPngImage(Picture.Graphic).LoadFromResourceName(HInstance, Bezeichner); // vermutlich geht es auch direkt und wird durchgereicht, aber ich war mir grad nicht ganz sicher end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:01 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