![]() |
TVirtualStringTree AddChild access violation
Ich habe ein Problem damit zu verstehen, warum ich eine access violation bekomme.
ich bekomme in der Zeile "Item := Tree.AddChild(Item);" ein access violation beim zweiten Schleifendurchlauf. Ich habe darüber LData := Tree.GetnodeData(Item); geschrieben, um zu gucken, ob das Item ein bereits definierter Node ist und Daten sind da. Meines Verständnisses nach müsste das Access Violation in der Zeile bedeutet, dass das Item sich weigert ein neues Child anzunehmen. Das ergibt in meinem Kopf keinen Sinn.
Delphi-Quellcode:
procedure TFrameTreeView.GetDirectories(Tree: TVirtualStringTree; Directory: string; Item: PVirtualNode; IncludeFiles: Boolean);
var SearchRec: TSearchRec; ItemTemp: PVirtualNode; LNode : PVirtualNode; LData : PTreeData; Lteststring : string; I: Integer; begin Tree.BeginUpdate; if Directory[Length(Directory)] <> '\' then Directory := Directory + '\'; if FindFirst(Directory + '*.*', faDirectory, SearchRec) = 0 then begin repeat //loop if (SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name[1] <> '.') then begin if (SearchRec.Attr and faDirectory > 0) then begin try if not Assigned(Item) then break; LData := Tree.GetnodeData(Item); Item := Tree.AddChild(Item); //<------ access violation LData := Tree.GetnodeData(Item); LData^.FPath := Directory+SearchRec.Name; LData^.FFolderName := SearchRec.Name; LData^.FFirstFolder := false; Tree.NodeDataSize := SizeOf(TTreeData); Tree.ValidateNode(Item, False); except break; end; end; ItemTemp := Item.Parent; LData := Tree.GetnodeData(ItemTemp); GetDirectories(Tree, Directory + SearchRec.Name, Item, IncludeFiles); Item := ItemTemp; end until FindNext(SearchRec) <> 0; FindClose(SearchRec); end; Tree.EndUpdate; end;
Delphi-Quellcode:
function TFrameTreeView.CreateFirstNode(Adir : string):PVirtualNode ;
var LFirstNode : PVirtualNode; LData : PTreeData; begin LFirstNode := TreeView2.AddChild(nil); LData := TreeView2.GetnodeData(LFirstNode); LData^.FFirstFolder := True; LData^.FPath := ADir; LData^.FFolderName := Adir; TreeView2.NodeDataSize := SizeOf(TTreeData); TreeView2.ValidateNode(LFirstNode, False); Result := LFirstNode; end;
Delphi-Quellcode:
function TFrameTreeView.NodePath(Node: TTreeNode): string;
var anode : TTreeNode; begin result := ''; if Node <> nil then begin result := Node.Text +'\'; anode := Node.Parent; while anode <> nil do begin result := anode.Text +'\' +result; anode := anode.Parent; end; end; end; |
AW: TVirtualStringTree AddChild access violation
Wenn ich du wäre würde ich das alles noch einmal komplett umschreiben.
AddChild benutzt man nicht! Man fügt Nodes über RootNodeCount hinzu und einer Liste mit Klasseninstanzen. |
AW: TVirtualStringTree AddChild access violation
Bin nur diesem Tutorial gefolgt:
![]() Aber dann lese ich mich mal in RootNodeCount ein. Danke dafür! |
AW: TVirtualStringTree AddChild access violation
Ganz grob also:
du hast eine Klasse mit Proberties und Informationen von allem was du so sin deinen Baum brauchst. Davon erzeugst du Instanzen und packst die in eine Liste. RootNodeCount ist so groß wie deine Liste groß ist. In Den VST Events greifst du jetzt auf diese Liste zu. |
AW: TVirtualStringTree AddChild access violation
Zitat:
ABER: DieDolly hat schon Recht wenn Sie sagt, dass man AddChild nicht benutzt. Zumindest nicht benutzen sollte. RootNodeCount und ChildCount (vom Event InitChildren) ist auf jeden Fall die bessere Wahl. Zudem entfällt das ganze FreeNode() Zeugs. Und du hast die Daten in einer strukturierten Liste und nicht in einer visuellen Komponente gespeichert. |
AW: TVirtualStringTree AddChild access violation
Teil 1:
Ich habe mich nochmal mit dem Code von unten auseinander gesetzt. Es schein am Befehl Size Of oder ValidateNode zu liegen. Wenn ich danach versuche wieder auf die Daten zuzugreifen, killt er sich.
Delphi-Quellcode:
Teil2: LData := (LNode.GetData); LData^.FPath := Directory+SearchRec.Name; LData^.FFolderName := SearchRec.Name; LData^.FFirstFolder := false; TreeView2.NodeDataSize := SizeOf(PTreeData); TreeView2.ValidateNode(LNode, False); LData := (LNode.GetData); //<--- Will nicht Ich habe mich mit den Vorschlägen auseinander gesetzt, es über RootNodeCount zu lösen. Ich habe also ein Recusives Object erzeugt, in dem alle Daten sind, habe die Oberste Ebene fertig, aber muss ich jetzt wirklich in IniChild die Kinder erzeugen und dann davon die Kindeskinder? Muss ich das recusive aufrufen, oder wird nachdem ich ein Kind erzeugt habe für dieses, das wieder aufgerufen? Ich finde das ganze unglaublich aufwändig dafür, dass ich nur eine Ordnerstruktur abbilden will. |
AW: TVirtualStringTree AddChild access violation
Zitat:
Delphi-Quellcode:
auf die Größe des Pointers. Also wahrscheinlich 4 Byte. Deine Struktur in der die Daten gespeichert werden ist aber sehr wahrscheinlich ungleich 4 Byte. Deshalb schmiert er bei
NodeDataSize
Delphi-Quellcode:
ab. Also einfach die NodeDataSize mit
ValidateNode()
Delphi-Quellcode:
initialisieren. Dann sollte das funktionieren.
TreeView2.NodeDataSize := SizeOf(TTreeData); // <-- ACHTUNG: TTreeData nicht PTreeData
Zitat:
Hoffe die Erklärung bringt dich weiter. Versuch einfach mal mit den Events zu arbeiten. Wenn du nicht weiter kommst, dann stell den SourceCode hier rein und wir schauen nochmal drüber. |
AW: TVirtualStringTree AddChild access violation
Zitat:
Der VST entstand IMHO zu Zeiten von Delphi 4 und Pentium-Prozessoren mit 90 MHz Takt. Da war der Unterschied zum TTreeView noch gewaltig, selbst bei kleineren Bäumen. Klar kannst du mit GetTickCount messen, dass zwischen einer AddChild-Schleife und einer RootNodeCount-Zuweisung soundsoviel Millisekunden Unterschied liegen. Aber das ist Jammern auf hohem Niveau. Im vorliegenden Fall dürfte ohnehin das Auslesen der Datenträgerinfos zum Flaschenhals werden und nicht das Initialisieren vom Tree. |
AW: TVirtualStringTree AddChild access violation
Zitat:
Delphi-Quellcode:
function TFrameTreeView.CreateFirstNode(Adir : string):PVirtualNode ;
var LFirstNode : PVirtualNode; LData : PTreeData; begin LFirstNode := TreeView2.AddChild(nil); LData := TreeView2.GetnodeData(LFirstNode); LData^.FFirstFolder := True; LData^.FPath := ADir; LData^.FFolderName := Adir; TreeView2.NodeDataSize := SizeOf(TTreeData); TreeView2.ValidateNode(LFirstNode, False); Result := LFirstNode; end; |
AW: TVirtualStringTree AddChild access violation
Zitat:
Im vorliegenden Fall hast du eine Dateisystem-Struktur. Willst du jetzt für jeden Ordner, jedes Laufwerk und jeden Symlink ein extra Objekt instantiieren und in einer ObjectList verwalten, nur damit du dir ein bisschen Arbeit beim Freenode sparen kannst? Ich möchte am Beispiel des Erstposters dezent darauf hinweisen, dass ein TSearchRec bereit ein Record ist. Warum nicht den gleich an den Node beppen, wenn er denn schon mal da ist? :wink: Subnodes würde ich gar nicht initial mit erzeugen sondern erst on-demand wenn der Anwender einen Ordner-Node aufklappt. So macht das auch der Explorer. Sonst würde das Öffnen auf einer normalen Windows-Installation ja jedesmal 5 Minuten dauern, weil ein komplettes rekursives Listing gemacht werden müsste :lol: @EricMeyer: Die Zugriffsverletzung in deinem Codebeispiel kommt daher, dass du zuerst versuchst, den Node zu erzeugen und danach erst NodeDataSize zuweist. NodeDataSize brauchst du in deinem Fall nur ein einziges Mal zuweisen und zwar bevor du überhaupt in deine Repeat-Schleife gehst. Der Hinweis mit dem TTreeData statt PTreeData war übrigens richtig. Man kann übrigens auch völlig verschiedene Records innerhalb des selben VST benützen. Deshalb speichert jeder PVirtualNode die NodeDataSize auch separat. Für solche Fälle gibt es das Event OnGetNodeDataSize, das z.B. von der Methode GetNodeData aufgerufen wird. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:12 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