Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Record übergeben


Alpha_Wolf - Do 08.12.05 11:32
Titel: Record übergeben
Ich steh grad irgendwie etwas aufm Schlauch.. Ich habe Eine Liste und einen Record und diesen würd ich gerne mit einer Funktion an eine andere Unit übergeben.

Das hier ist mein Record und meine Liste.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
  TTreeListRecord = record
    ColValue0: string;
    ColValue1: string;
  end;

  ...
  private
    fTreeListRecord: ^TTreeListRecord;
    fTreeList: TList;

  ...
  SetData(fTreeList, fTreeListRecord); // Aufruf in der anderen Unit (siehe unten..)


Wenn ich jetzt in der anderen Unit das gleiche deklariere bringt er mir entweder eine AccessViolation oder es lässt sich gar nicht kompilieren. Die Liste überträgt er.. aber den Record mit den Pointern nicht..

Ich müsste die Liste und den Record übergeben.. Nachfolgend der Code der anderen Unit:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  function TChecklistePrintProcessMgr.SetData(aTreeList: TList;
    aTreeListRecord: TTreeListRecord): boolean;
  begin
    fTreeList := aTreeList;
    fTreeListRecord := aTreeListRecord;
  ...


Ich möchte deswegen die Liste und den Record übergeben weil in der anderen Unit damit weitergearbeitet wird...

Kann mir da jemand weiterhelfen?

Hoffe das war verständlich..^^

Danke.

Edit: Schreibfehler in Code angepasst.


opfer.der.genauigkeit - Do 08.12.05 11:41

Hi,

du versucht einen Record vom Typ TTreeListRecord an eine Funktion zu übergeben, die einen Record von Typ TRecord erwartet.


Alpha_Wolf - Do 08.12.05 11:45

Oh.. stimmt.. war allerdings n Schreibfehler.. sorry!


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
 function TChecklistePrintProcessMgr.SetData(aTreeList: TList;   
    aTreeListRecord: TTreeListRecord): boolean;   
  begin   
    fTreeList := aTreeList;   
    fTreeListRecord := aTreeListRecord;   
  ...


Selbst wenn ich beim Aufruf der Funktion

Delphi-Quelltext
1:
SetData(fTreeList, fTreeListRecord^);                    


mache sagt der Compiler mir:


Quelltext
1:
Inkompatible Typen: 'Unit1.TTreeListRecord' und 'Unit2.TTreeListRecord'                    


Hm.. sag ja ich steh aufm Schlauch -.-


Gausi - Do 08.12.05 11:49

Du hast TTreeListRecord aber nicht in beiden Units deklariert, oder?


Alpha_Wolf - Do 08.12.05 11:55

Sollte ich das nicht? Ich bin grad etwas durchn Wind.. aber woher sollte dann Unit2 wissen was in Unit1 ist? Nur Unit1 weiss was in Unit2 ist..

Ich weiss das doppelte Namensgebung nicht unbedingt gut ist..

Theoretisch könnte ich doch dann einfach Unit1 mit Unit2 bekannt machen und umgekehrt

und den Record und die Liste einmal ins public von Unit1 schreiben.. Ist aber denke ich nicht die Ideallösung..


petergensfeld - Do 08.12.05 11:59

Hallo Alpha_Wolf,

wenn ich das richtig interpretiere, definierst Du fTreeList in Unit1 als private Klassenvariable. Diese übergibst Du dann per Referenz an eine 2. Klasse (TChecklistePrintProcessMgr), in der Du wieder eine fTreeList als Klassenvariable definierst, richtig? Das halte ich schon mal für keine gute Idee, denn damit würdest Du die Referenz in TChecklistePrintProcessMgr zerschießen, sobald die Klasse in Unit1 zerstört wird. Entweder solltest Du die ganze Liste mit fTreeList.Assign(aTreeList) kopieren oder nur temporär mit der Referenz arbeiten.

Bzgl. der Fehlermeldung: Hast Du TTreeListRecord in Unit2 erneut definiert?

Gruß Dirk


Gausi - Do 08.12.05 11:59

user profile iconAlpha_Wolf hat folgendes geschrieben:
Sollte ich das nicht?
Nein, sollte man nicht. Wozu das führt, merkst du ja gerade ;-)

user profile iconAlpha_Wolf hat folgendes geschrieben:
Ich bin grad etwas durchn Wind.. aber woher sollte dann Unit2 wissen was in Unit1 ist? Nur Unit1 weiss was in Unit2 ist..
Trag Unit1 im Uses Teil der Unit2 hinzu. Ggf. im Implementationsteil, um eine Überkreuzreferenzierung zu vermeiden. (also nach implementation noch eine uses Zeile einfügen)

user profile iconAlpha_Wolf hat folgendes geschrieben:
Ich weiss das doppelte Namensgebung nicht unbedingt gut ist..
Das ist schön formuliert :lol:


Alpha_Wolf - Do 08.12.05 12:16

Danke für die Antworten :)

Hm.. also hab in Unit2 im uses Bereich die Unit1 reingeschrieben.
In Unit1 habe ich die Liste und den Record in public verschoben.

Wenn ich jetzt versuche irgendwo in Unit2 mit der Liste oder dem Record zu arbeiten (auch mit assign) bekomm ich ne AccessViolation. Wie umgeh ich das?


petergensfeld - Do 08.12.05 12:35

Um die Liste und den Record aus dem Public-Bereich der Klasse1 benutzen zu können, musst Du eine Instanz (=ein Objekt, per Create erzeugt) dieser Klasse zur Verfügung haben. Sonst bekommst Du eine Zugriffsverletzung.

Erkläre doch mal grob, was Du mit der Liste machen willst, vielleicht kann man Dir dann genauere Tipps geben. Vermutlich wird die Übergabe als Referenz die bessere Lösung sein, nur darfst Du diese nicht dauerhaft in Klasse2 speichern.

Gruß Dirk


opfer.der.genauigkeit - Do 08.12.05 12:42

Hi,

ein kleines Beispiel für den Umgang mit einem Record und einem Zeiger auf einen Record:

Unit1

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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    btnCopyRecord: TButton;
    procedure btnCopyRecordClick(Sender: TObject);
  private
    fMyRec: TMyRec;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnCopyRecordClick(Sender: TObject);
var
  lMyClass: TMyClass;
begin
  lMyClass := TMyClass.Create;
    fMyRec.Test := 'TEST';
  lMyClass.SetData( fMyRec );
  lMyClass.SetData( @fMyRec );
  FreeAndNil( lMyClass );
end;


end.


Unit2

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:
27:
28:
29:
30:
31:
32:
33:
34:
unit Unit2;

interface

type
  PMyRec = ^TMyRec;
  TMyRec = record
    Test: string;
  end;

  TMyClass = class
  public
    procedure SetData(aMyRec: TMyRec); overload;
    procedure SetData(aMyRec: PMyRec); overload;
  end;

implementation

uses
  Dialogs;

{ TMyClass }

procedure TMyClass.SetData(aMyRec: TMyRec);
begin
  MessageDlg( aMyRec.Test, mtInformation, [mbOK], 0 );
end;

procedure TMyClass.SetData(aMyRec: PMyRec);
begin
  MessageDlg( aMyRec.Test, mtInformation, [mbOK], 0 );
end;

end.


Der Rest sollte sich erschließen lassen könen.


Alpha_Wolf - Do 08.12.05 12:50

Kurze Erklärung:

Unit1 ist ein Modaler Dialog, Unit2 ist jediglich eine Klasse.

Ich habe eine Liste und einen Record in Unit1.
Diese fülle ich mit Daten aus einer TreeList.
Der Record besitzt 2 Felder mit Namen Value0 und Value1.
Ist das TreeListItem ein Parent kommt es in Value0,
ist es ein Child kommt es in Value1.

Die Liste und den Record schicke ich dann an eine extra Unit
die den Export zu Ecxel ermöglicht.
Mit der Liste bestimme ich die Anzahl der Zeilen für den Export.
In einer Schleife benutze ich nun 2 If-Anweisungen bei denen ich
jeweils prüfe ob Value0 leer ist (dann ist es ein Child) oder
ob Value1 leer ist (dann ist es ein Parent) je nachdem werden
die Inhalte die nicht leer sind in die erste Spalte(Parent)
oder in die zweite Spalte(Child) nach Excel exportiert.

Danke für die Hilfe!


petergensfeld - Do 08.12.05 12:55

@ opfer.der.genauigkeit

Fehlt da nicht ein "^"?


Delphi-Quelltext
1:
2:
3:
4:
procedure TMyClass.SetData(aMyRec: PMyRec);
begin
  MessageDlg( aMyRec^.Test, mtInformation, [mbOK], 0 );
end;


opfer.der.genauigkeit - Do 08.12.05 13:06

Hallo petergensfeld,

die Dereferenzierung mit ^ ist nicht nötig.
Wenn ich mich recht entsinne entfällt dies seit der Version 4 von Delphi und dient nur der Abwärtskompatibilität.

Ich hab das in diesem Fall außer Acht gelassen, sollte der Korrektheit aber benutzt werden.


petergensfeld - Do 08.12.05 13:20

Hallo Alpha_Wolf,

zunächst zu Deinem Record, folgenden Aufbau fände ich irgendwie konsequenter:


Delphi-Quelltext
1:
2:
3:
4:
5:
type
  TTreeListRecord = record
    Value: String;
    IsChild: Boolean;
  end;


Du bräuchtest nur IsChild abzufragen und müsstest nicht immer ein leeres Feld mit Dir rumschleppen.

Warum führst Du in der Dialog-Klasse überhaupt eine zweite Liste mit den Einträgen (die hast Du ja dort schon in Deinem TreeView)? Oder brauchst Du die noch anderweitig? Wenn nicht, dann würde ich der SetData-Routine der Klasse TChecklistePrintProcessMgr eine Referenz auf das TreeView mitgeben und die Liste dort füllen und verwalten.

So in der Art könnte ich mir das vorstellen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
  procedure TChecklistePrintProcessMgr.SetData(tv: TTreeView);
  var
    i: Integer;
    ptlr: ^TTreeListRecord;
  begin
    for i:=0 to tv.Items.Count-1 do
    begin
      new(ptlr);
      ptlr^.Value:=tv.Items[i].Text;
      ptlr^.IsChild:=tv.Items[i].Parent<>nil;
      fTreeList.Items.Add(ptlr);  
        // fTreeList muss in TChecklistePrintProcessMgr.Create
        // erzeugt worden sein 
    end;
    // [...] 
  end;


@ opfer.der.genauigkeit

Da hab ich auch wieder was dazugelernt, muss ich in meinem D5 mal ausprobieren. Gut finde ich das aber nicht, sehr unsauber.

Gruß Dirk


opfer.der.genauigkeit - Do 08.12.05 13:28

user profile iconpetergensfeld hat folgendes geschrieben:

@ opfer.der.genauigkeit

Da hab ich auch wieder was dazugelernt, muss ich in meinem D5 mal ausprobieren. Gut finde ich das aber nicht, sehr unsauber.


Wenn dich sowas beunruhigt, dann solltest du auch solche Sprachen wie C# meiden. ;)
In den meisten fällen sieht man eh nicht, was alles referenziert bzw. dereferenziert wird, oder wo sich ein Zeiger versteckt und wo nicht.
Ich denke dabei an Dinge wie implizite Zeiger und Instanzen.

Ein Beispiel unter C++ ist z.B.:
rec->test;
Es handelt sich dabei auch um einen verstecken Typecast.

Und da wir grade bei sauberer Programmierung sind.
Variablenbezeichnungen alá 'i: integer' sind auch nicht immer vorteilhaft. ;)

@Alpha_Wolf:
Wenn du eh jedem Knoten einen Record zuweist und dann jeweils prüfen möchtest ob es sich um ein Child oder Parent handelt, warum hängst du dann nicht entsprechend dem Knoten den Record als Data (Zeiger auf den Record) an, das geht bei den meisten Trees.

Wenn nicht, merk dir im Record den Knoten (Zeiger auf den Knoten) und benutze die Treefunktionen um festzustellen ob es ein Kind oder Parent ist.

Dadurch wärst du flexibler für Erweiterungen.


Stefan.Buchholtz - Do 08.12.05 13:47

user profile iconopfer.der.genauigkeit hat folgendes geschrieben:

Wenn dich sowas beunruhigt, dann solltest du auch solche Sprachen wie C# meiden. ;)
In den meisten fällen sieht man eh nicht, was alles referenziert bzw. dereferenziert wird, oder wo sich ein Zeiger versteckt und wo nicht.
Ich denke dabei an Dinge wie implizite Zeiger und Instanzen.

Ein Beispiel unter C++ ist z.B.:
rec->test;
Es handelt sich dabei auch um einen verstecken Typecast.


Wo ist denn da der Cast? Wenn rec ein struct oder ein Objekt ist, ist, heisst es rec.test, wenn rec ein Zeiger auf ein struct oder Objekt ist, heisst es rec->test - da läuft nix implizit ab.

user profile iconopfer.der.genauigkeit hat folgendes geschrieben:
Und da wir grade bei sauberer Programmierung sind.
Variablenbezeichnungen alá 'i: integer' sind auch nicht immer vorteilhaft. ;)


Na ja, man kann es auch übertreiben. i als Laufvariable in einer Schleife ist meiner Meinung nach völlig ok - man sollte es nur nicht für was anderes verwenden, dann wird es unübersichtlich.

Stefan


opfer.der.genauigkeit - Do 08.12.05 14:10

user profile iconStefan.Buchholtz hat folgendes geschrieben:
user profile iconopfer.der.genauigkeit hat folgendes geschrieben:

Ein Beispiel unter C++ ist z.B.:
rec->test;
Es handelt sich dabei auch um einen verstecken Typecast.


Wo ist denn da der Cast? Wenn rec ein struct oder ein Objekt ist, ist, heisst es rec.test, wenn rec ein Zeiger auf ein struct oder Objekt ist, heisst es rec->test - da läuft nix implizit ab.



Ich hab nix von Implizit im Bezug auf diesen Operator gesagt.
Das gilt z.B.: für dyn. Arrays.

Der Cast liegt aber hier versteck:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
#include <iostream>

struct foo
{
    char foo;
};

int main()
{
    foo *p;
    foo f;
    p = (foo *)malloc( sizeof(foo) );
    p->foo = 'a';
  std::cout << p->foo << std::endl;
  f = *p;
  std::cout << f.foo << std::endl;
  std::cout << ((foo)*p).foo << std::endl;
  std::cout << (*p).foo << std::endl;
  return 0;
}


-> ersetzt also die Dereferenzierung.
Das sind solche Dinge, die man schon garnicht mehr sieht.

user profile iconStefan.Buchholtz hat folgendes geschrieben:

user profile iconopfer.der.genauigkeit hat folgendes geschrieben:
Und da wir grade bei sauberer Programmierung sind.
Variablenbezeichnungen alá 'i: integer' sind auch nicht immer vorteilhaft. ;)


Na ja, man kann es auch übertreiben. i als Laufvariable in einer Schleife ist meiner Meinung nach völlig ok - man sollte es nur nicht für was anderes verwenden, dann wird es unübersichtlich.
Stefan


Nein, übertreiben sicherlich nicht. Aber man sollte es sich nicht für wichtige Variablen angewöhnen, sonst kommt man leicht durcheinander.


petergensfeld - Do 08.12.05 14:51

Hmm, da sehe ich genau wie Stefan aber dennoch einen Unterschied. f.foo und p->foo kann man durchaus noch unterscheiden. Bei dem Delphi-Beispiel benutzt Du aber exakt die gleiche Syntax, kannst also überhaupt nicht mehr erkennen, ob es sich um einen Pointer oder eine Strukturvariable handelt. Ich werde mir diese Syntax gar nicht erst angewöhnen (schon gar nicht, wenn man hier die korrekte Übergabe eines Records an eine Funktion aufzeigen will). Aber sie funktioniert in D5 tatsächlich, habe das eben mal ausprobiert.

Wichtige Variablen heißen bei mir auch nie i, für Laufvariablen nehme ich aber immer wieder gerne i,j,k... Ich glaube kaum, dass jemand Probleme haben wird, meine Quellcodes zu interpretieren (jedenfalls nicht deshalb ;)).

Gruß, Dirk


opfer.der.genauigkeit - Do 08.12.05 15:16

Natürlich besteht da ein Unterschied.
Ich will auch nur darauf hinweisen, daß man nicht alles sieht was passiert.
Unter C# und sonstigen bequemen Sprachen sieht man eben noch weniger.
Für einen sauberen Stil sollte man das ^ sicherlich auch verwenden.
Im Zeitalter der Augen und Quelltexthinweise etc. laßen sich aber solche Dinge mit nur einem kurzen Blick klären.

Nebenbei erwähnt tut es mir aufrichtig leid, daß ich das in dem Beispiel nicht berücksichtigt habe. :mrgreen:


petergensfeld - Do 08.12.05 15:30

Zitat:
Unter C# und sonstigen bequemen Sprachen sieht man eben noch weniger.

Ich weiß, in VB braucht man nicht mal Variablen zu definieren (ohne die Krücke mit "option explicit"). Grund genug für mich, Sprachen wie VB zu meiden, wo immer es geht. Ich hoffe nur, dass die Delphi-Language nicht auch in diese Richtung abgleitet.


Alpha_Wolf - Do 08.12.05 15:51

Ersteinmal danke an alle =) hab von jedem ein bisschen was übernommen.. stand wohl wirklich aufm Schlauch.. danke für den Code Philipp!

Die Liste brauche ich deswegen da ich zuerst komplett den Tree zwischenspeichern möchte bevor ich ich weiterarbeite..


Alpha_Wolf - Do 08.12.05 17:11

Hmm..mir ist grad wieder was aufgefallen was nicht funktioniert(wieder Problem mit der Übergabe eines Records..)

Ich habe den Code von opfer.der.genauigkeit genommen.
Das ganze baut darauf auf das ich vorher eine Liste fülle und sie dann an einen Rekord übergebe damit ich Value und IsChild auslesen kann:

Unit1

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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
...

private
    fTreeListRecord: TTreeListRecord;

...

//******************************************************************************
function TForm1.InitChecklistPrintDlg(aTreeList: TdxTreeList): boolean;
var
  lNodeCount: integer;
  lItemCount: integer;
  lCounter: integer;
  lCounter2: integer;
  lValue: string;
  lNode: TdxTreeListNode;
begin
  result := false;
  lChecklistePrintProcessMgr := nil;
  try
    lChecklistePrintProcessMgr := TChecklistePrintProcessMgr.Create;
    // ParentCount der TreeList
    lNodeCount := aTreeList.Count;

    // Record wird gefüllt
    for lCounter := 0 to lNodeCount-1 do begin
      // Parents
      lNode := aTreeList.Items[lCounter];
      lValue := lNode.Values[0] + ' ' + lNode.Values[2];

      //New(fTreeListRecord);
      with fTreeListRecord do begin
        Value := lValue;
        IsChild := false;
      end;
      lChecklistePrintProcessMgr.AddToList(fTreeListRecord);

      // ItemCount der TreeList
      lItemCount := lNode.Count;

      // Childs
      for lCounter2 := 0 to lItemCount-1 do begin
        lValue := lNode.Items[lCounter2].Values[2];

        //New(fTreeListRecord);
        with fTreeListRecord do begin
          Value := lValue;
          IsChild := true;
        end;

        lChecklistePrintProcessMgr.AddToList(fTreeListRecord);
      end;
    end;

    result := true;
  except
    // Hier später Fehlerbehandlung
  end;
end;





Unit2

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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
PTreeListRecord = ^TTreeListRecord;
  TTreeListRecord = record
    Value: string;
    IsChild: boolean;
  end;

  ...

  private
    TreeListRecord: ^TTreeListRecord;

  ...

//******************************************************************************
// Aufruf um den aktuellen Inhalt des Records in eine Liste zu speichern
function TChecklistePrintProcessMgr.AddToList(
  aTreeListRecord: TTreeListRecord): boolean;
begin
  result := false;
  try
    fTreeList.Add(@aTreeListRecord);
    result := true;
  except
    // Hier später Fehlerbehandlung 
  end;
end;

//******************************************************************************
// Hier wird versucht den Inhalt der Liste auszulesen und ihn wieder auf den
// Record aufzuteilen damit Value und IsChild getrennt ausgelesen werden können
function TChecklistePrintProcessMgr.PrepareData: boolean;
var
  lTreeListCount: integer;
begin
  Result := false;
  lTreeListCount := fTreeList.Count;

  for lCounter := 0 to lTreeListCount-1 do begin

    TreeListRecord := fTreeList.Items[lCounter];
    ShowMessage(TreeListRecord^.Value);
  end;


Der markierte Code ist nur ein Test.. allerdings funktioniert es nicht.. ich bekomme jedes mal wenn er die markierte Zeile erreicht folgende Fehlermeldung:


Quelltext
1:
Im Projekt Project1.exe ist eine Exception der Klasse EExternalException aufgetreten. Meldung: 'Externe Exception 80000001'. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.                    


Danach gehts nicht mehr weiter. Ich weiss bei dieser Fehlermeldung leider nicht mehr weiter.. Bitte um Hilfe!

Dankeschön.


opfer.der.genauigkeit - Do 08.12.05 17:26

Hi,

setzt mal bitte ein var hier ein oder übergib direkt den Zeiger:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
//******************************************************************************
// Aufruf um den aktuellen Inhalt des Records in eine Liste zu speichern
function TChecklistePrintProcessMgr.AddToList( [b]var[/b] aTreeListRecord: TTreeListRecord): boolean;
begin
  result := false;
  try
    fTreeList.Add(@aTreeListRecord);
    result := true;
  except
    // Hier später Fehlerbehandlung 
  end;
end;


Probier das mal oder mach es etwas schöner und übergib direkt den Zeiger:

Delphi-Quelltext
1:
aTreeListRecord: PTreeListRecord                    


//Edit: Zudem sei erwähnt, daß du in deinem Code immer den gleichen Record an deine Liste übergibst. (fTreeListRecord: TTreeListRecord == konstante adresse)

//Edit:
Beispiel:

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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
unit Unit1;

interface

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

type
  PTreeRec = ^TTreeRec;
  TTreeRec = record
    Idx: string;
  end;

  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    fList: TList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  lIdx: integer;
  lRec: PTreeRec;
begin
  fList := TList.Create;

  for lIdx := 0 to 100 do
  begin
    New( lRec );
    lRec^.Idx := IntToStr( lIdx );
    fList.Add( lRec )
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  lIdx: integer;
begin

  if Assigned( fList ) then
  begin
    for lIdx := 0 to (fList.Count - 1do
    begin
      Dispose( fList.Items[lIdx] );
    end;
    FreeAndNil( fList );
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
var
  lIdx: integer;
begin
  for lIdx := 0 to (fList.Count -1do
  begin
    Memo1.Lines.Add( PTreeRec(fList.Items[lIdx])^.Idx );
  end;
end;

end.


petergensfeld - Do 08.12.05 17:55

Hier noch mein Vorschlag, ändere die Methode AddToList mal wie folgt ab:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
    
function TChecklistePrintProcessMgr.AddToList(
  aTreeListRecord: TTreeListRecord): Boolean;
var
  pNewRec: ^TTreeListRecord;
begin
  new(pNewRec);
  pNewRec^:=aTreeListRecord;
  try
    fTreeList.Add(pNewRec);
    Result:=true;
  except
    Result:=false;
  end;
end;

Dein Fehler: Du speicherst immer wieder die gleiche Referenz in der Liste ab.

Gruß Dirk


Alpha_Wolf - Fr 09.12.05 10:04

So, jetzt funktioniert alles.. :idea: vielen Dank euch allen :)

Das mit New() hatte ich ausversehen auskommentiert und dann gelöscht :oops: