Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Pobleme mit FREE (bzw. Destroy) (https://www.delphipraxis.net/109537-pobleme-mit-free-bzw-destroy.html)

DoktorD 3. Mär 2008 10:55


Pobleme mit FREE (bzw. Destroy)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi. Habe ein kleines Tool in dem ich ein Panel dynamisch erzeuge. In diesem Panel erzeuge ich ein Image.

Zur Laufzeit hole ich mir mit "self.GetFormImage" dann das aktuelle Bild der Form.

Funktion:
Ich will, wenn ich ein Fenster aufmache den Hintergrund verschleiern.

Das Funktioniert soweit ganz gut, aber nach dem ca. 47 maligen aufrufen des Fensters kommt die Fehlermeldung:

Exception-Klasse EOutOfResources mit Meldung 'Für diesen Befehl ist nicht genügend Speicher verfügbar.

Ich hab keine Ahnung wie ich den Fehler lokalisieren soll, bzw. ich weiß garnicht warum hier ein Fehler auftritt.


Delphi-Quellcode:
procedure TFrmMain.Button1Click(Sender: TObject);
var
  ModalesFenster: TForm2;
begin
  Verschleiern(TRUE);
  ModalesFenster := TForm2.Create(Self);
  ModalesFenster.ShowModal;
  Verschleiern(FALSE);
end;




procedure TFrmMain.Verschleiern(Status: Boolean);
begin
  if Status = TRUE then
  begin
    PanelVerschleiern               := TPanel.Create(nil);
    PanelVerschleiern.Parent        := FrmMain;
    PanelVerschleiern.Align         := alclient;
    PanelVerschleiern.Visible       := FALSE;
    PanelVerschleiern.BevelOuter    := bvNone;

    ImageVerschleiern               := TImage.Create(PanelVerschleiern);
    ImageVerschleiern.Parent        := PanelVerschleiern;
    ImageVerschleiern.Align         := alclient;
    ImageVerschleiern.Picture.Bitmap := self.GetFormImage;

    AlphaBlendRect(ImageVerschleiern.Canvas,PanelVerschleiern.ClientRect,clblack,80);

    PanelVerschleiern.Show;
  end
  else
  begin
    PanelVerschleiern.Hide;
    ImageVerschleiern.Free;
    PanelVerschleiern.Free;
  end;
end;




procedure TFrmMain.AlphaBlendRect (const aCanvas: TCanvas;
                                 const aRect: TRect;
                                 const aColor: TColor;
                                 const aIntensity: Byte);
var
  w, h       : Integer;
  Bitmap     : TBitmap;
  BlendParams : TBlendFunction;
begin
  w := Succ(aRect.Right - aRect.Left);
  h := Succ(aRect.Bottom - aRect.Top);
  Bitmap := TBitmap.Create;
  try
    Bitmap.Width := w;
    Bitmap.Height := h;
    Bitmap.Canvas.Brush.Color := ColorToRGB(aColor);
    Bitmap.Canvas.FillRect (Rect(0, 0, w, h));
    BlendParams.BlendOp := AC_SRC_OVER;
    BlendParams.BlendFlags := 0;
    BlendParams.SourceConstantAlpha := aIntensity;
    BlendParams.AlphaFormat := 0;
    Windows.AlphaBlend(aCanvas.Handle, aRect.Left, aRect.Top, w, h,
                       Bitmap.Canvas.Handle, 0, 0, w, h,
                       BlendParams);
  finally
    Bitmap.Free;
  end;
end;


Im Anhang ist das Projekt

mkinzler 3. Mär 2008 11:04

Re: Pobleme mit FREE (bzw. Destroy)
 
Versuch mal
Delphi-Quellcode:
FreeAndNil( ImageVerschleiern);
satt de, .Free
Auerdem erzeugst du ja in denem Button immer ein neues Fenster, welches du nicht mehr freigibst.

DoktorD 3. Mär 2008 11:11

Re: Pobleme mit FREE (bzw. Destroy)
 
Hab ich auch schon probiert. Das geht auch nicht. Ich bin jetzt soweit, dass ich meine, dass es nicht an den dynamisch erzeugten Objekten liegt (Panel, Image), sondern irgendwie an "self.GetFormImage"

Aber wo belegt das denn speicher? Oder wie könnte ich den freigeben?

Aurelius 3. Mär 2008 11:20

Re: Pobleme mit FREE (bzw. Destroy)
 
Ich denke dass es, wie mkinzler schon geschrieben hat, daran liegt, dass du das "ModaleFenster" wahrscheinlich nicht wieder freigibst...

Bernhard Geyer 3. Mär 2008 11:23

Re: Pobleme mit FREE (bzw. Destroy)
 
Binde doch mal FastMM ein und schau was der über deinen Code so zu berichten hat.

DoktorD 3. Mär 2008 11:24

Re: Pobleme mit FREE (bzw. Destroy)
 
Danke für den Tipp.

Aber was ist denn FastMM? Wo bekomme ich das her und wie binde ich das ein?

Aurelius 3. Mär 2008 11:25

Re: Pobleme mit FREE (bzw. Destroy)
 
http://sourceforge.net/projects/fastmm/

Das überwacht dein Delphiprogramm und sagt dir ob irgendwo Speicherlecks auftreten, weil du z.b. ein dyn. erzeutes Formular nicht wieder freigibst und dieses somit immer noch Arbeitspeicher belegt.

DoktorD 3. Mär 2008 11:42

Re: Pobleme mit FREE (bzw. Destroy)
 
Wie genau wird das denn eingebunden oder gestartet? Hab jetzt die deutsche Unit FastMM4 und FastMM4Messages dem Projekt hinzugefügt.
Aber irgedwas muss ich doch noch machen, oder?

Muetze1 3. Mär 2008 12:05

Re: Pobleme mit FREE (bzw. Destroy)
 
Am besten noch kontrollieren, dass FastMM4 als aller erste Unit in der DPR in der Uses Liste steht. Dann Programm aufrufen, arbeiten und beenden. Dann erhälst du eine entsprechende Liste.

DoktorD 3. Mär 2008 12:46

Re: Pobleme mit FREE (bzw. Destroy)
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, habs nun hinbekommen. Nur verstehe ich die Meldung nicht. Was bedeutet das denn?

Bild ist im Anhang

mkinzler 3. Mär 2008 12:48

Re: Pobleme mit FREE (bzw. Destroy)
 
Wie sieht den TForm2 aus?

hoika 3. Mär 2008 12:55

Re: Pobleme mit FREE (bzw. Destroy)
 
Hallo,

in FastMM4Options.Inc die in der MessageBox gezeigten
Compiler-Schalter enabled ($define ..}

und noch mal:
Warum wir TForm2 erzeugt, aber nicht freigegeben ?
Das ist dein 1. mem leak .

Merke die Form-Variable global unbd guib sie wieder frei,
wenn du das nächste Fenster erzeugst.


Heiko

DeddyH 3. Mär 2008 12:56

Re: Pobleme mit FREE (bzw. Destroy)
 
Und GetFormImage erzeugt AFAIK auch bei jedem Aufruf eine neue Bitmap, die man wieder freigeben muss.

DoktorD 3. Mär 2008 13:05

Re: Pobleme mit FREE (bzw. Destroy)
 
Huch, gleich so viele antworten.

Zitat:

Zitat von mkinzler
Wie sieht den TForm2 aus?

Wenn ich Form2 mit Close schließe ist doch der Speicher frei gegeben, oder?

Delphi-Quellcode:
unit UntModalesFenster;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm2 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  Close;
end;

end.


Zitat:

Zitat von DeddyH
Und GetFormImage erzeugt AFAIK auch bei jedem Aufruf eine neue Bitmap, die man wieder freigeben muss.

Wie gebe ich den frei?

DeddyH 3. Mär 2008 13:07

Re: Pobleme mit FREE (bzw. Destroy)
 
Zitat:

Zitat von DoktorD
Wie gebe ich den frei?

Mit Free.
Delphi-Quellcode:
var bm: TBitmap;
begin
  bm := GetFormImage;
  try
    //irgendwas mit dem Bitmap machen
    ...
  finally
    bm.Free;
  end;
end;

mkinzler 3. Mär 2008 13:13

Re: Pobleme mit FREE (bzw. Destroy)
 
Zitat:

Wenn ich Form2 mit Close schließe ist doch der Speicher frei gegeben, oder?
Nein. das Formular wird nur geschlossen.

DoktorD 3. Mär 2008 13:23

Re: Pobleme mit FREE (bzw. Destroy)
 
Tatsächlich. Jetzt klappts. Super. Ich weiß aber immer noch nicht warum?

Hier erstmal der neue Code
Delphi-Quellcode:
procedure TFrmMain.Verschleiern(Status: Boolean);
var
  bm : TBitmap;
begin
  if Status = TRUE then
  begin
    PanelVerschleiern               := TPanel.Create(nil);
    PanelVerschleiern.Parent        := FrmMain;
    PanelVerschleiern.Align         := alclient;
    PanelVerschleiern.Visible       := FALSE;
    PanelVerschleiern.BevelOuter    := bvNone;

    ImageVerschleiern               := TImage.Create(PanelVerschleiern);
    ImageVerschleiern.Parent        := PanelVerschleiern;
    ImageVerschleiern.Align         := alclient;

    bm                              := self.GetFormImage;
    try
      ImageVerschleiern.Picture.Bitmap := bm;
    finally
      bm.Free;
    end;

    AlphaBlendRect(ImageVerschleiern.Canvas,PanelVerschleiern.ClientRect,clblack,80);

    PanelVerschleiern.Show;
  end
  else
  begin
    PanelVerschleiern.Hide;
    FreeAndNil( ImageVerschleiern);
    FreeAndNil( PanelVerschleiern);
  end;
end;
Was ist denn nun der unterschied? Ob ich das Bitmap gleich zuordne, ...
Delphi-Quellcode:
ImageVerschleiern.Picture.Bitmap := self.GetFormImage;

...oder erst über eine neue Variable?
Delphi-Quellcode:
    bm                              := self.GetFormImage;
    try
      ImageVerschleiern.Picture.Bitmap := bm;
    finally
      bm.Free;
    end;

DeddyH 3. Mär 2008 13:30

Re: Pobleme mit FREE (bzw. Destroy)
 
Das sollte nur ein Beispiel sein. Eigentlich müsste es auch so gehen (ungetestet):
Delphi-Quellcode:
FreeAndNil(ImageVerschleiern.Picture.Bitmap);
Das natürlich, bevor Du das Image selbst freigibst.

DoktorD 3. Mär 2008 13:42

Re: Pobleme mit FREE (bzw. Destroy)
 
Das hatte ich so gemacht. Und da ging es nicht. Komisch

Trotzdem vielen Dank an alle!!!


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:59 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