Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Combobox mit AddObject - Speicher automatisch freigeben (https://www.delphipraxis.net/86828-combobox-mit-addobject-speicher-automatisch-freigeben.html)

backdraft 20. Feb 2007 10:10


Combobox mit AddObject - Speicher automatisch freigeben
 
Hallo zusammen,

wie wandele ich mir eine ComboxBox so ab, dass Sie automatisch beim Zerstören die Objekte freigibt, die ich mit AddObject angefügt habe?

Wenn ich den Destructor überschreiben und auf die Items zugreifen will bekomme ich die Meldung, dass die Combobox kein übergeordnetest Objekt hat.

Weiss jemand rat?

IngoD7 20. Feb 2007 10:20

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Zitat:

Zitat von backdraft
Wenn ich den Destructor überschreiben und auf die Items zugreifen will bekomme ich die Meldung, dass die Combobox kein übergeordnetest Objekt hat.

Weiss jemand rat?

Wenn du den Code postest, mit dem du es versucht hast, dann vielleicht. ;-)

backdraft 20. Feb 2007 10:24

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Delphi-Quellcode:
destructor TCustomImageComboBox.Destroy;
var i : Integer;
begin
 FOR i := 0 TO FFItems.Count - 1 DO BEGIN
  IF FItems.Objects[i] <> nil THEN FItems.Objects[i].Free;
 END;
 inherited;
end;

IngoD7 20. Feb 2007 11:07

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Zitat:

Zitat von backdraft
Delphi-Quellcode:
destructor TCustomImageComboBox.Destroy;
var i : Integer;
begin
 FOR i := 0 TO FFItems.Count - 1 DO BEGIN // <=== doppeltes F ??
  IF FItems.Objects[i] <> nil THEN FItems.Objects[i].Free;
 END;
 inherited;
end;

Das doppelte F ist keine Absicht, oder?

Wie sieht deine Klasse TCustomImageBox denn aus? Wovon leitest du ab?


Bei meinem Test habe ich mal direkt von TComboBox abgeleitet:

Delphi-Quellcode:
type
  ...

  TCombo = class(TComboBox)
  public
    destructor destroy; override;
  end;

var
  Combo: TCombo;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
...
   Combo := TCombo.Create(Form1);
   Combo.Name:='Combo';
   Combo.Parent:=self;
   Combo.Left := 448;
   Combo.Top := 64;
   Combo.Width := 145;
   Combo.Height := 21;
   Combo.ItemHeight := 13;
   Combo.Clear;
   Combo.Items.AddObject('Label',self.Label1); //Testobject ist Label1 auf Form1
end;

destructor TCombo.destroy;
var i : integer;
begin
  for i := 0 to Combo.Items.Count-1 do
  begin
    Combo.Items.Objects[0].free;
  end;
  inherited;
end;
Wenn ich irgendwo im Programm ein Combo.Free habe, so funktioniert das einwandfrei. In meinem Beispiel verschwindet das Label1 von der Form. :-)

backdraft 20. Feb 2007 11:29

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Ok, hab alles aus den Klassen mal in ein Beispielprog geschrieben

Form enthält nur 2 Buttons, die Combo wird angelegt
Nach Klick auf den Hinzufügen button wird beim Prog Ende kein Speicher freigegeben.

Delphi-Quellcode:
unit Unit1;

interface

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


type

  TNeueComboBox = class;

  TNeuesComboBoxItem = class
  protected
    FOwner: TNeueComboBox;
    FItemIndex: Integer;
    FListID : Integer;
    FIndex: Integer;
    FIndentLevel: Integer;
    FImageIndex: Integer;
    FOverlayIndex: Integer;
    FCaption: string;
    FTag: Integer;
    FData: Pointer;
    procedure SetIndentLevel( Value: Integer );
    procedure SetImageIndex( Value: Integer );
    procedure SetCaption( const Value: string );
    procedure SetOverlayIndex( Value: Integer );
  public
    constructor Create( AOwner: TNeueComboBox );
    destructor Destroy; override;
    property Index: Integer       read FIndex;
    property IndentLevel: Integer read FIndentLevel write SetIndentLevel;
    property ImageIndex: Integer  read FImageIndex  write SetImageIndex;
    property OverlayIndex: Integer read FOverlayIndex write SetOverlayIndex;
    property Caption: string      read FCaption     write SetCaption;
    property Data: Pointer        read FData        write FData;
    property Tag: Integer         read FTag         write FTag;
    property ListID: Integer      read FListID      write FListID;
  end;

   TNeueComboBox = class(TCustomComboBox)
   public
    destructor Destroy; override;
    function AddItem(Caption: string; ImageIndex: Integer; IndentLevel: Integer; ListID: Integer ): TNeuesComboBoxItem;
   end;

type
  TForm1 = class(TForm)
    btn_Hinzu: TButton;
    btn_Delete: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btn_HinzuClick(Sender: TObject);
    procedure btn_DeleteClick(Sender: TObject);
  private
   FComboBox : TNeueComboBox;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TNeuesComboBoxItem.Create( AOwner: TNeueComboBox );
begin
  inherited Create;
  FOwner := aOwner;
  FOverlayIndex := -1;
end;

destructor TNeuesComboBoxItem.Destroy;
begin
  inherited;
end;

procedure TNeuesComboBoxItem.SetIndentLevel( Value: Integer );
begin
  FIndentLevel := Value;
  FOwner.Invalidate;
end;

procedure TNeuesComboBoxItem.SetImageIndex( Value: Integer );
begin
  FImageIndex := Value;
  FOwner.Invalidate;
end;

procedure TNeuesComboBoxItem.SetCaption( const Value: string );
begin
  FCaption := Value;
  FOwner.Invalidate;
end;

procedure TNeuesComboBoxItem.SetOverlayIndex( Value: Integer );
begin
  FOverlayIndex := Value;
  FOwner.Invalidate;
end;

function TNeueComboBox.AddItem( Caption: string; ImageIndex: Integer; IndentLevel: Integer; ListID: Integer ): TNeuesComboBoxItem;
const NOSTRING: string = '';
begin
  Result := TNeuesComboBoxItem.Create(Self);
  Result.FCaption := Caption;
  Result.FImageIndex := ImageIndex;
  Result.FIndentLevel := IndentLevel;
  Result.ListID      := ListID;
  Result.FIndex := inherited Items.AddObject( Caption, Result )
end;

destructor TNeueComboBox.Destroy;
begin
 WHILE Items.Count > 0 DO Items.Delete(0);
 inherited;
end;

procedure TForm1.btn_DeleteClick(Sender: TObject);
begin
 FComboBox.Items.Clear;
end;

procedure TForm1.btn_HinzuClick(Sender: TObject);
begin
 FComboBox.AddItem('Name', 0, 0, 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 FComboBox := TNeueComboBox.Create(self);
 FComboBox.Parent := self;
end;

end.

IngoD7 20. Feb 2007 14:19

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Die Kiste verschluckt sich einfach. Ich habe keine Ahnung, warum. :(

Es passt aber der schöne Spruch dazu, dass alles, was man im Constructor created, man im Destructor wieder destroyen soll.

Baue mal das folgende dazu, dann sollte es mit der Fehlermeldung vorbei sein:

Delphi-Quellcode:
procedure TForm1.FormDestroy(Sender: TObject);
begin
   FComboBox.Free;
end;

Dann noch was:

Zitat:

Delphi-Quellcode:
destructor TNeueComboBox.Destroy;
begin
  WHILE Items.Count > 0 DO Items.Delete(0);
  inherited;
end;

Mit Delete gibst du keine Objekte frei, du löscht nur die Referenz aus der Liste.
Benutze Items.Objects[].Free, so wie du es schon in deinem zweiten Posting hier angedeutet hattest.

backdraft 20. Feb 2007 14:36

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Ich hab mittlerweile festgestellt, dass wenn ich die Items auf TComponent basieren lasse (TNeuesComboBoxItem = class(TComponent), macht er er es.

IngoD7 20. Feb 2007 15:00

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Zitat:

Zitat von backdraft
Ich hab mittlerweile festgestellt, dass wenn ich die Items auf TComponent basieren lasse (TNeuesComboBoxItem = class(TComponent), macht er er es.

:gruebel:
Das ist aber irgendwie von hinten durch die Brust ins Auge.
Damit erzwingst/ermöglichst du möglicherweise - auf was für Kosten auch immer - dass deine Combobox ihre Einträge bzw. die Objekte in den Einträgen automatisch freigibt. Also so, wie eine Form für die Freigabe der visuellen Komponenten auf ihr verantwortlich ist. War das die ganze Zeit dein Ziel?

Da finde ich aber die manuelle Freigabe sowohl der Listen-Objekte in TComboBox.Destroy als auch deiner ComboBox mittels ComboBox.Free in TForm.Destroy viel sauberer.

backdraft 20. Feb 2007 15:21

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
ne das war nicht mein ziel,
das prob ist aber, dass ich das free event nicht auslösen kann, weil die kombo ja von der ide erzeugt wird und nicht wie in meinem beispiel zur runtime.
also kann ich den destroy nicht aufrufen, für jede kombo die ich auf die maske lege, oder?

IngoD7 20. Feb 2007 21:28

Re: Combobox mit AddObject - Speicher automatisch freigeben
 
Zitat:

Zitat von backdraft
ne das war nicht mein ziel,
das prob ist aber, dass ich das free event nicht auslösen kann, weil die kombo ja von der ide erzeugt wird und nicht wie in meinem beispiel zur runtime.

Das könnte aber vielleicht noch hier und da einen Unterschied ausmachen. Aber das weiß ich wirklich nicht genau.

Offen gestanden ergeben sich für mich von einem Posting von dir zum nächsten zuviele Abweichungen. Das mit der Ide (also Entwurfszeit) ist ja nun völlig neu.

Zitat:

Zitat von backdraft
also kann ich den destroy nicht aufrufen, für jede kombo die ich auf die maske lege, oder?

Destroy solltest du nicht aufrufen, aber Free oder FreeAndNil wäre möglich. Warum denn nicht?

Allerdings möchte ich mich jetzt auch langsam ausklinken, weil ich heute sehr lange an dieser Sache herumgetestet habe und nun hören muss, dass alles nicht der wirklichen Umsetzung entsprach. Sorry.

Nur soviel noch: Ich würde - wenn es tatsächlich eine Komponente zum Auf-die-Form-ziehen werden soll - tatsächlich auch gucken, dass sie automatisch freigegeben wird. Die Komponente! Die in der Liste enthaltenen Objekte könntest du dabei aber trotzdem manuell freigeben. Sie werden ja auch manuell zur Laufzeit created. Bei einer normalen ComboBox muss man das auch so tun.

Letztlich hält die Liste ja nur Referenzen auf Objekte und oftmals wäre es im wahrsten Sinne des Wortes zerstörerisch, wenn bei der Löschung einer Auflistung von Gegenständen, die Gegenstände gleich selbst mit zerlegt würden. ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:08 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz