Hallo zusammen,
so, die Fehlermeldung beim Programm beenden scheint erstmal weg zu sein. Allerdings sind die MemoryLeaks noch vorhanden. Ich habe jetzt den Tip von "Zacherl" befolgt und das Event "OnFreeNode" entsprechend eingebaut. Irgendwie glaube ich allerdings, dass das ganze nicht ganz sauber Programmiert ist. Ich möchte Euch gerne daher mal versuchen die jeweiligen Teilabschnitte aufzuführen und wäre Euch dankbar, wenn Ihr mir ein kurzes Feedback geben könntet.
So, ich versuch das mal Schrittweise darzustellen. Ich erzeuge ein VST mit ungefähr folgendem Aufbau:
Code:
+Hauptknoden (Zeigt den Datenbankpfad an)
+Kunde_1
+Objekt_1
+System_1
+Menü_1
+Menü_2
+Menü_3
+System_2
+Menü_1
+Menü_2
+Menü_3
+Objekt_2
+System_1
+Menü_1
+Menü_2
+Menü_3
+Kunde_2
+Objekt_1
+System_1
+Menü_1
+Menü_2
+Menü_3
+Objekt_2
+System_1
+Menü_1
+Menü_2
+Menü_3
Jeder Kunde kann mehrere Objekte haben. Jedes Objekt kann mehrere Systeme haben und Jedes System hat mehrere Menüpunkte.
Erzeugen tue ich das ganze dann in etwa so...
Ich habe je ein Objekt für die Kundendaten, Objektdaten und Systemdaten. Diese sind jeweils ähnlich und wie folgt aufgebaut...
Delphi-Quellcode:
unit Customers;
interface
uses
Buildings;
{ TObject für die Kundendaten }
type
TOCustomers =
class(TObject)
private
FID : integer;
//ID
FESID : integer;
//ESID
FName :
string;
//Name des Kunden
FOrt :
string;
//Ort des Kunden
FStraße :
string;
//Straße des Kunden
FAnsprechpartnerId : integer;
//Ansprechpartnernummer
FAnsprechpartner :
string;
//Ansprechpartner
FAnsPosition :
string;
//Position/Stellung
FEMail :
string;
//EMail des Ansprechpartners
FTel1 :
string;
//Telefonnummer 1 des Ansprechpartners
FTel2 :
string;
//Telefonnummer 2 des Ansprechpartners
FFax :
string;
//Faxnummer des Ansprechpartners
FBemerkung :
string;
//Kunden Zusatzinformation
public
property Kunden_Kundennummer : integer
read FID
write FID;
property Kunden_ESKundennummer : integer
read FESID
write FESID;
property Kunden_Kundenname :
string read FName
write FName;
property Kunden_Ort :
string read FOrt
write FOrt;
property Kunden_Straße :
string read FStraße
write FStraße;
property Kunden_Bemerkung :
string read FBemerkung
write FBemerkung;
property Ansprechpartner_Id : integer
read FAnsprechpartnerId
write FAnsprechpartnerId;
property Ansprechpartner_Name :
string read FAnsprechpartner
write FAnsprechpartner;
property Ansprechpartner_Position :
string read FAnsPosition
write FAnsPosition;
property Ansprechpartner_EMail :
string read FEMail
write FEMail;
property Ansprechpartner_Telefon1 :
string read FTel1
write FTel1;
property Ansprechpartner_Telefon2 :
string read FTel2
write FTel2;
property Ansprechpartner_Fax :
string read FFax
write FFax;
end;
implementation
end.
ähnlich sieht das Objekt für "Objekte" und "System" aus.
In meinem Hauptformular nutze ich die Objekte wie folgt:
Delphi-Quellcode:
...
interface
uses
...
type
PCustomersData = ^TCustomersData;
TCustomersData =
record
FCustomer_Object : TObject;
end;
type
PBuildingsData = ^TBuildingsData;
TBuildingsData =
record
FBuilding_Object : TObject;
end;
type
PSystemsData = ^TSystemsData;
TSystemsData =
record
FSystem_Object : TObject;
end;
...
private
{ Private-Deklarationen }
var
....
//Diese Globalen Variablen nutze ich für das LoadData
TMyKunden_Daten : TOCustomers;
TMyObjekt_Daten : TOBuilding;
TMySystem_Daten : TOSystems;
...
public
{ Public-Deklarationen }
procedure LoadData;
var
fMyForm: TfMyForm;
implementation
//Das hinzufügen der Daten mache ich dann über folgende Methode:
procedure TfMyForm.LoadData;
var
I,J,K : Integer;
CustomerNode, BuildingNode, SystemNode : PVirtualNode;
begin
try
vstKunden.BeginUpdate;
vstKunden.Clear;
CustomerNode := vstKunden.AddChild(
nil);
vstKunden.InvalidateNode (CustomerNode);
vstKunden.NodeDataSize:=SizeOf(TCustomersData);
{Hier glaube ich liegt das erste Problem. Ich setze NodeDataSize auf TCustomersData.
Was aber ist mit TBuildingData und TSystemData? Benötige ich die nicht,
weil es nur um den ersten Node geht?}
//Jetzt lade ich die Kundendaten aus der DB und lasse das ganze durch eine for-Schleife laufen
TMyKunden_Daten := TOCustomers.Create;
with TMyKunden_Daten
do
begin
//Daten zufügen
//Inerhalb der Schleife folgen dann die tieferen Datenpunkte
BuildingNode := AddVSTCustomer(vstKunden,CustomerNode,TMyKunden_Daten);
//Objektedaten laden aus Objektdatenbank
//Systemdaten
//Menüpunkte
end;
vstKunden.EndUpdate;
ExpandedRootNodes(vstKunden);
vstKunden.SortTree(0, sdAscending, True);
finally
//Queries schließen etc.
end;
Delphi-Quellcode:
//Hier die Funktion AddVSTCustomer, die weiteren Add-Funktionen sind ähnlich
function TfReportClient.AddVSTCustomer(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
AObject: TObject): PVirtualNode;
var
Data : PCustomersData;
begin
Result := AVST.AddChild(ANode);
AVST.ValidateNode(Result,False);
Data := AVST.GetNodeData(Result);
Data^.FCustomer_Object := AObject;
end;
Dann weiße ich über "OnGetText" die Bezeichnung zu und über "OnGetImageIndex" noch ein paar Icons
Das "OnFreeNode" sieht aktuell wie folgt aus...
Delphi-Quellcode:
procedure TfReportClient.vstKundenFreeNode(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
Kunden_Daten : PCustomersData;
Objekt_Daten : PBuildingsData;
System_Daten : PSystemsData;
begin
case vstKunden.GetNodeLevel(Node) of
0:
begin
Kunden_Daten := Sender.GetNodeData(Node);
Finalize (Kunden_Daten^);
end;
1:
begin
Objekt_Daten := Sender.GetNodeData(Node);
Finalize (Objekt_Daten^);
end;
2:
begin
System_Daten := Sender.GetNodeData(Node);
Finalize (System_Daten^);
end;
end;
end;
Die Globalen Var. gebe ich im FormDestroy wieder frei...
Delphi-Quellcode:
procedure TfReportClient.FormDestroy(Sender: TObject);
begin
TMyKunden_Daten.Free;
TMyObjekt_Daten.Free;
TMySystem_Daten.Free;
end;
Ich vermute, das einige von Euch jetzt schon die Hände über dem Kopf zusammengeschlagen haben
Aber vieleicht könnt Ihr mir ja mal ein paar Tips geben.
Danke schon mal und Gruß Jens