Entwickler-Ecke

Multimedia / Grafik - AddObject und in Schleife erzeugtes Bitmap


galagher - Di 15.12.09 19:34
Titel: AddObject und in Schleife erzeugtes Bitmap
Hallo!

Ich versuche, die Komponente TFileListBox zu modifizieren. Es sollen beim Einlesen der Dateinamen auch deren Symbole ausgelesen und per Items.AddObject den Items zugewiesen werden. Das klappt auch, aber nur so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
procedure TFileListBox.ReadFileNames;
var
  //...
  I: Integer;
  //...
  Glyph: TBitmap;
  aIcon: TIcon;
//...
begin
 aIcon := TIcon.Create;
//...
 if FindFirst(MaskPtr, AttrWord, FileInfo) = 0 then
 begin
  repeat
//...
  GetIconFromFile(FileInfo.Name, aIcon, True);  //Liest Dateisymbole in aIcon ein
  Glyph := TBitmap.Create;  // muss immer wieder erzeugt werden, da sonst alle Items das selbe Symbol zeigen
  IconToBitmap(aIcon, Glyph);
  Glyph.Height := 16;
  Glyph.Width := 16;
  I := Items.AddObject(FileInfo.Name, Glyph);
//...
finally
//...
 aIcon.Free;
end;

Meine Frage nun: Wie und wo wird das TBitmap Glyph wieder freigegeben? Es wird je immer wieder neu erzeugt, jedesmal, wenn man den Ordner wechselt, läuft die Prozedur ReadFileNames und es werden immer mehr von diesen Glyph-TBitmaps erzeugt.
Das funktioniert, aber ist das auch ok? Was ist mit dem Speicher?

Delphi-Hilfe:
Zitat:
Das TStringList-Objekt wird nicht zu Eigentümer der hinzugefügten Objekte. Diese Objekte exisitieren weiter, auch wenn die TStringList-Instanz freigegeben wird. Diese Objekte müssen explizit von der Anwendung freigegeben werden.

Wie müssen sie freigegeben werden?


Lannes - Di 15.12.09 21:03

Hallo,

eventuell ist das auch was für dich: http://www.delphi-forum.de/viewtopic.php?p=334000#334000


Freigeben bevor das Item gelöscht wird, mit einem TypeCast, etwa so:


Delphi-Quelltext
1:
2:
TBitmap(Items.Objects[x]).Free;
Items.Delete(x);


galagher - Di 15.12.09 21:20

user profile iconLannes hat folgendes geschrieben Zum zitierten Posting springen:
Freigeben bevor das Item gelöscht wird, mit einem TypeCast, etwa so:


Delphi-Quelltext
1:
2:
TBitmap(Items.Objects[x]).Free;
Items.Delete(x);


Ich weiss bloss nicht, wo das oder die Items gelöscht werden! Etwa direkt am Anfang der Prozedur ReadFileNames?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TFileListBox.ReadFileNames;
var
  //...
  I: Integer;
  //...
  Glyph: TBitmap;
  aIcon: TIcon;
//...
begin
 aIcon := TIcon.Create;
//...
 for i := Items.Count-1 downto 0 do
 begin
  TBitmap(Items.Objects[i]).Free;
  Items.Delete(i);
 end;
 
 if FindFirst(MaskPtr, AttrWord, FileInfo) = 0 then
 begin
  repeat
//...


Lannes - Mi 16.12.09 00:13

Hallo,


im Code der Unit FileCtrl in der Prozedur TFileListBox.ReadFileNames wird ziemlich am Anfang Clear aufgerufen, und zwar das von TCustomListBox, darin FItems.Clear. Das wiederum TListBoxStrings.Clear aufruft, darin wird ListBox.ResetContent aufgerufen.
In der Procedur erfolgte ein Message mit LB_RESETCONTENT das TWinControl auf den Plan ruft mit Gethandle >> HandleNeeded.
Dann gehts weiter mit Assembler in der StdWndProc, Call [ECX].Pointer verzweigt in TWinControl.MainWndProc und dann wird Window.Proc aufgerufen und jetzt habe ich keine Lust mehr weiter das zu verfolgen ...


galagher - Mi 16.12.09 21:51

So funktioniert es immerhin:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
 for i := Items.Count-1 downto 0 do
 begin
  if Assigned(TBitmap(Items.Objects[i])) then
   TBitmap(Items.Objects[i]).Free;  //Wird beim 1. Aufruf wie erwartet nicht, sondern erst bei Ordnerwechsel ausgeführt
  Items.Delete(i);
 end;

TBitmap(Items.Objects[i]).Free; wird 7x ausgeführt, wenn in einem Ordner 6 Dateien sind. Ok, 7x bei 6 Dateien ist mir jetzt nicht ganz klar, aber es funktioniert prinzipiell. Meine Frage konkret: Gibt das den Speicher der TBitmaps frei, der zuvor belegt wurde?


Lannes - Do 17.12.09 19:59

Hallo,

ja, sollte freigegeben sein.

Das würde mich auch wundern, 6 Dateien, aber 7 Freigaben. Items.Count kann nicht unter 7 liegen, sonst würde es eine Zugriffsverletzung geben. Wie hoch ist den die Anzahl der TBitmap.Create-Aufrufe in dem zuvor ausgeführten ReadFileNames?


galagher - Do 17.12.09 21:09

user profile iconLannes hat folgendes geschrieben Zum zitierten Posting springen:
Wie hoch ist den die Anzahl der TBitmap.Create-Aufrufe in dem zuvor ausgeführten ReadFileNames?

Es sind bei 6 Dateien genau 6 Read's und 6 Free's. Wie ich dann auf 7 kam? Ich habe mir einen Haltepunkt gesetzt und habe 1 zuviel gezählt. Mit Integers als Zähler klappte es jetzt!

Vielen Dank, also werde ich den Code so lassen!


galagher - Sa 19.12.09 10:35

Hallo!

Bin jetzt soweit fertig mit der filectrl.pas und es funktioniert alles. Ist diese Datei in einem Package, wie kann ich das nun kompilieren, sodass die neuen Eigenschaften auch schon zur Entwurfszeit angezeigt werden?

//Edit: Hat sich erledigt - habe es zu einer eigene Komponente umgebaut!