![]() |
VirtualStringTree und OnLoadNode
Hallo,
jetzt kämpf ich schon eine ganze Weile mit dem VirtualStringTree. Ich möchte den Tree mit den dazu zur Verfügung gestellten Methoden "SaveToFile" und "LoadFromFile" speichern. Jede Node enthält jedoch auch noch einen Record mit Daten, welche in den Ereignissen "OnSaveNode" und "OnLoadNode" in einen übergebenen Stream geschrieben bzw. von diesem gelesen werden müssen. Wie es aussieht, klappt das Schreiben der Nodes. Ich verwende folgenden Record, der mir die Daten hält welche ich im Node speichern möchte.
Delphi-Quellcode:
TEntry ist die Basisklasse, verschiedener TEntryClassen, so gibt es CategoryEntry Klassen wie auch NoticeEntry Klassen.
PTreeData = ^TTreeData;
TTreeData = record FileName: string; EntryType: TEntryType; Entry: TEntry; end; Über EntryType kann unterschieden werden ob es sich um eine CategoryEntry Klasse oder eine NoticeEntry Klasse handelt. Die TEntry Klasse:
Delphi-Quellcode:
Das Feld Caption ist das Feld, welches zur Beschriftung der Node hergenommen wird.
TEntryType = (etCATEGORY, etNOTICE);
TEntry = class(TObject) private FCaption: string; FEntryType: TEntryType; FEntryFolder: string; FEntryFilename: string; function getEntryFullFileName: string; function getDataSize: integer; public procedure SaveMeToFile(aSourceComponent: TComponent); virtual; procedure LoadMeFromFile(aTargetComponent: TComponent; const aFilename: string); virtual; property EntryType: TEntryType read FEntryType write FEntryType; property Caption: string read FCaption write FCaption; property EntryFolder: string read FEntryFolder write FEntryFolder; property EntryFilename: string read FEntryFilename write FEntryFilename; property EntryFullFileName: string read getEntryFullFileName; property DataSize: integer read getDataSize; end; Die Eventroutine beim Speichern der Node schaut so aus:
Delphi-Quellcode:
Die Eventroutine zum Laden der Nodes schaut so aus:
procedure TfDataBox.vstSaveNode(Sender: TBaseVirtualTree;
Node: PVirtualNode; Stream: TStream); var lTreeData: PTreeData; lIntegerData: integer; begin lTreeData := PTreeData(Sender.GetNodeData(Node)^); lIntegerData := Ord(lTreeData.EntryType); Stream.WriteBuffer(lIntegerData, sizeOf(lIntegerData)); lIntegerData := length(lTreeData.FileName); Stream.WriteBuffer(lIntegerData, sizeOf(lIntegerData)); Stream.WriteBuffer(PChar(lTreeData.FileName)^, lIntegerData); end;
Delphi-Quellcode:
procedure TfDataBox.vstLoadNode(Sender: TBaseVirtualTree;
Node: PVirtualNode; Stream: TStream); var lTreeData: PTreeData; lEntryType: TEntryType; lIntegerData: integer; lFileName: string; begin lTreeData := PTreeData(Sender.GetNodeData(Node)^); Stream.Read(lTreeData^.EntryType, sizeOf(integer)); Stream.Read(lIntegerData, sizeOf(lIntegerData)); setLength(lTreeData^.FileName, lIntegerData); Stream.Read(lTreeData^.FileName, lIntegerData); case lEntryType of etCATEGORY: begin lTreeData^.Entry := TCategoryEntry.Create; lTreeData^.Entry.LoadMeFromFile(nil, lFileName); end; etNOTICE: begin lTreeData^.Entry := TNoticeEntry.Create; lTreeData^.Entry.LoadMeFromFile(FNoticeEditor, lFileName); end; end; end; Jedoch bekomme ich beim Laden des Trees nur Access Violations, welche daher kommen, dass die Daten welche an den Nodes angehängt sein sollten, anscheinend nicht angehängt sind. Ich denke aber, dass ich genau das ja mit dieser Routine erreichen sollte. Die NodeDataSize ist vorher schon auf die Größe von PTreeData festgelegt. Weiß vielleicht jemand was ich falsch mache? Wieso mein Code nicht so funktioniert, wie ich mir das vorstelle? |
Re: VirtualStringTree und OnLoadNode
Hallo,
Zitat:
Zu vstSaveNode():
Delphi-Quellcode:
Zu vstLoadNode():
begin
... lTreeData := Sender.GetNodeData(Node); ... Stream.WriteBuffer(lTreeData.FileName[1], lIntegerData); end;
Delphi-Quellcode:
lTreeData: PTreeData;
lEntryType: TEntryType; lIntegerData: integer; lFileName: string; begin lTreeData := Sender.GetNodeData(Node); ... Stream.Read(lTreeData.FileName[1], lIntegerData); case lTreeData.EntryType of ... Zitat:
Freundliche Grüße vom marabu |
Re: VirtualStringTree und OnLoadNode
Liste der Anhänge anzeigen (Anzahl: 2)
Hm, habe Deine Korrekturen eingebaut, nur ich bekomme nun immer noch Access violations.
Da scheint es immer noch einen/mehrere Fehler zu geben. Vielleicht hilft es ein wenig, wenn ich die Unit die den VST verwendet anhänge |
Re: VirtualStringTree und OnLoadNode
Hallo Günter,
wo bekommst du denn deine AV? Ich habe mir deine Unit zwar runter geladen, aber sie ist in meiner Umgebung leider nicht ladbar. Dein Code enthält an vielen Stellen:
Delphi-Quellcode:
Mein Vorschlag war:
with PTreeData(Sender.GetNodeData(Node)^) do .. ;
Delphi-Quellcode:
Du kannst aber auch so vorgehen:
var
ptd: PTreeData; begin ptd := Sender.GetNodeData(Node); with ptd do ... ;
Delphi-Quellcode:
Da ist schon ein Unterschied...
with PTreeData(Sender.GetNodeData(Node))^ do .. ;
marabu |
Re: VirtualStringTree und OnLoadNode
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab das mal versucht umzusetzen wie du das geschrieben hast, geht dann teilweise, habe dann aber andere Probleme, wie dass bei Neuen Nodes dann kein Text angezeigt wird, bis ich diesen Editiere.
Ich hab jetzt mal ein kleines Projekt gemacht, ich häng das da mal an, da wird jetzt dann nur 'Node' hingeschrieben, anstatt 'Neuer Eintrag'. Ich hoff das kann man jetzt aufmachen. |
Re: VirtualStringTree und OnLoadNode
Hallo Günter,
wenn du dem VST einen Knoten hinzufügst, dann darfst du deinen TreeData-Record nicht selbst auf dem Heap anlegen - das macht der VST für dich. Um einen Zeiger auf deine Struktur zu erhalten, rufst du nach dem InsertNode() oder AddChild() mit dem von diesen Methoden zurückgegebenen node pointer die Methode GetNodeData() auf. Mit dieser Vorgehensweise solltest du in der Lage sein den von dir geschilderten Fehler zu beheben. marabu |
Re: VirtualStringTree und OnLoadNode
Danke für den Hinweis, das werde ich heute abend ausprobieren.
Ich frage mich jetzt dann allerdings wofür der letzte Parameter der Methoden AddChild() bzw. InsertNode() dann dienen soll, wenn nicht zur Übergabe des PTreeData Records. |
Re: VirtualStringTree und OnLoadNode
Wenn deine Struktur TTreeData einen Pointer als erstes Feld definieren würde, dann könntest du durch die Übergabe von UserData (der zweite Parameter von AddChild) diesen Pointer für interne Steuerungszwecke initialisieren. Einfach weglassen, solange du das nicht brauchst.
marabu |
Re: VirtualStringTree und OnLoadNode
Soll ich das jetzt so verstehen, dass der Pointer den man bei AddChild() bzw. InsertNode() übergeben kann, nichts mit dem zu tun hat, den man sich über vst.GetNodeData(Node) holen kann?
Dann frage ich mich, allerdings wieso manche Teile funktioniert haben. |
Re: VirtualStringTree und OnLoadNode
Du hast mich richtig verstanden. Der "trotzdem funktionierende" Code war nicht in deinem Demo-Projekt, also kann ich dazu nichts sagen. Ist aber auch nicht so wichtig, hoffe ich.
marabu |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:58 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