![]() |
TVirtualStringTree -> XML
Hi,
ich programmiere derzeit ein Projektmanagementsystem, bei dem, in einem TVirtualStringTree ( ![]() Beim beenden sollen diese Daten in eine XML-Datei gespeichert werden. Dazu muss man wissen, dass der Sinn vom TVST ist, dass jede Node eigentlich ein record (bzw. ein Pointer auf ein Record) ist und somit die Node an sich die Daten beeinhaltet (meiner Meinung nach das genialste, was jemals erfunden wurde ;)). Nun werden die Daten aber nicht richtig gespeichert. Der Aufbau ist der folgende (in den [ stehen die vers. Eigenschaften, die sichtbar sind):
Code:
Meine Prozedur zum speichern sieht folgendermaßen aus:
+ Projekt [Projektverzeichnis, Projektname, Projektsprache, Projektprogrammiersprache]
|- Sourcefile [Dateiname, Programmiersprache |- Sourcefile + Projekt + Projekt |- Sourcefile |- Sourcefile |- Sourcefile |- Sourcefile + Projekt . . .
Delphi-Quellcode:
Beim speichern bricht er einfach ab mit einer AccessViolation, aber ohne eine Zeile anzugeben. Grund? Ich habe keine Ahnung.
type
TData = record mode: byte; // 0 = Project // 1 = Sourcefile Name: WideString; PrgLanguage: WideString; // Programminglanguage Language: WideString; // Language / only 0 ProjectDir: WideString; // only 0 FileName: WideString; // only 1 end; PData = ^TData; {...} procedure TMainForm.SaveToXML(aFileName: string); var xmlDoc: IXMLDOMDocument2; mainNode, subNode, subsubNode: IXMLDOMNode; curData, curSubData: TData; rootnode, subrootnode: PVirtualNode; i, j: integer; f: TextFile; begin DeleteFile(aFileName); AssignFile(f, aFileName); Rewrite(f); writeln(f, '<?xml version="1.0"?>'); writeln(f, '<projects>'); writeln(f, '</projects>'); CloseFile(f); xmlDoc := CoDOMDocument40.Create(); xmlDoc.load(aFileName); if XMLDoc.parseError.errorCode <> 0 then begin ShowMessage('XML Fehler: ' + #13#10 + XMLDoc.parseError.reason + #13#10 + 'Source: ' + xmldoc.parseError.srcText); xmldoc := nil; end; rootNode := vstProjects.RootNode; for i:=0 to vstProjects.RootNodeCount - 1 do begin curData := PData(vstProjects.GetNodeData(rootNode))^; if not Assigned(@curData) then break; mainNode := xmlDoc.createElement('project'); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('name'); subNode.text := curData.Name; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('prglanguage'); subNode.text := curData.PrgLanguage; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('language'); subNode.text := curData.Language; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('projectdir'); subNode.text := curData.ProjectDir; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('sourcefiles'); subRootNode := rootNode.LastChild; for j:=0 to rootNode.ChildCount - 1 do begin curSubData := PData(vstProjects.GetNodeData(subRootNode))^; xmlDoc.documentElement.appendChild(mainNode); subsubNode := xmlDoc.createElement('name'); subsubNode.text := curSubData.Name; subNode.appendChild(subsubNode); xmlDoc.documentElement.appendChild(mainNode); subsubNode := xmlDoc.createElement('prglanguage'); subsubNode.text := curSubData.PrgLanguage; subNode.appendChild(subsubNode); xmlDoc.documentElement.appendChild(mainNode); subsubNode := xmlDoc.createElement('filename'); subsubNode.text := curSubData.FileName; subNode.appendChild(subsubNode); subRootNode := subRootNode.NextSibling; end; mainNode.appendChild(subNode); xmlDoc.save(aFileName); rootNode := rootNode.NextSibling; end; end; Habt ihr eine Idee? Ich vermute, dass ich einen Fehler beim Umgang mit den Pointern gemacht habe. Chris |
Re: TVirtualStringTree -> XML
Der ist schwer nachzuvollziehen ;-) Setze doch mal ein paar Messageboxen und schaue, wenn er abbricht, vielleicht kommst Du damit der "bösen" Zeile auf die Schliche.
...:cat:... |
Re: TVirtualStringTree -> XML
setz doch einfach in der ersten zeile des Algos einen Haltepunkt und geh die Prozedure Zeile für Zeile durch, dann ist wenigstens schon mal die Zeile identifiziert.
|
Re: TVirtualStringTree -> XML
Ich glaube der Fehler liegt am Ende der inneren Schleife
Delphi-Quellcode:
...:cat:...
subRootNode := subRootNode.NextSibling;
|
Re: TVirtualStringTree -> XML
Hm... eine Idee wäre es, aber lt. den Haltepunkten ist der Fehler noch vor dem
Delphi-Quellcode:
Chris
rootNode := vstProjects.RootNode;
|
Re: TVirtualStringTree -> XML
Auf ganz suspekte Art und Weise gibt es angeblich in der Zeile
Delphi-Quellcode:
den Fehler. Das habe ich mir auch irgendwo schon gedacht, denn irgendwie habe ich das Gefühl, dass der Source an dieser Stelle äußerst daneben ist... :\
curData := PData(vstProjects.GetNodeData(rootNode))^;
Chris |
Re: TVirtualStringTree -> XML
:wall: Das ist einfach nicht zu fassen! :cry:
Egal, was ich mache: der Fehler bleibt. Ich habe inzwischen alle möglichen Möglichkeiten, meiner Meinung nach, ausprobiert, aber es hat bisher nichts gebracht.. :evil: Chris |
Re: TVirtualStringTree -> XML
*jetzt die dp nerv und alle mods aggressiv mach*
Kann mir denn niemand helfen? :cry: Also der Fehler besteht darin, dass die Daten der rootNode-Variable nicht existieren. Allerdings müssen sie das eigentlich... :( Chris |
Re: TVirtualStringTree -> XML
Poste doch mal den Code, wo Du die Daten in der Root-Node speicherst.
...:cat:... |
Re: TVirtualStringTree -> XML
Liste der Anhänge anzeigen (Anzahl: 1)
Hm...
Ich hänge das ganze einfach mal an. Eigentlich braucht man zusätzlich nur noch TVST der aktuellen Version. SynEdit ist verwerflich. Aber zur "Übersichtlichkeit" wegen hier mal die weiteren wichtigen Stellen:
Delphi-Quellcode:
Chris
procedure TMainForm.miNewProjectClick(Sender: TObject); // neues Projekt
var newNode: PVirtualNode; newData: PData; begin newNode := vstProjects.AddChild(nil); vstProjects.Text[newNode, 1] := 'test'; newData := vstProjects.GetNodeData(newNode); newData^.mode := 0; newData^.Name := vstProjects.DefaultText; newData^.ProjectDir := ''; end; procedure TMainForm.miiCreateNewClick(Sender: TObject); // neue Datei var selData: PData; selNode: PVirtualNode; newData: PData; newNode: PVirtualNode; begin vstProjects.BeginUpdate; selNode := vstProjects.FocusedNode; if not Assigned(selNode) then Exit; selData := vstProjects.GetNodeData(selNode); if selData^.mode <> 0 then selNode := selNode.Parent; newNode := vstProjects.AddChild(selNode); newData := vstProjects.GetNodeData(newNode); newData^.mode := 1; newData^.Name := 'Neue Sourcefile'; newData^.PrgLanguage := selData^.PrgLanguage; vstProjects.FullExpand(selNode); vstProjects.EndUpdate; vstProjects.Refresh; end; |
Re: TVirtualStringTree -> XML
Bevor ich mir den VST installiere, tue mir mal den Gefallen und poste noch vstProjects.GetNodeData(....);
Danke, ...:cat:... |
Re: TVirtualStringTree -> XML
vstProjects ist das VST. Hier GetNodeData(...);:
Delphi-Quellcode:
Chris
{Copy & Paste from VirtualTrees.pas by http://www.delphi-gems.com}
function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer; // Returns the address of the user defined data area in the node. begin Assert(FNodeDataSize > 0, 'NodeDataSize not initialized.'); if (FNodeDataSize <= 0) or (Node = nil) or (Node = FRoot) then Result := nil else Result := PChar(@Node.Data) + FTotalInternalDataSize; end; |
Re: TVirtualStringTree -> XML
Ich weiss zwar nicht, was Du in der Proc erreichen willst, aber für die RootNode gibt die wohl immer nil zurück.
Code:
...:cat:...
{Copy & Paste from VirtualTrees.pas by http://www.delphi-gems.com}
function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer; // Returns the address of the user defined data area in the node. begin Assert(FNodeDataSize > 0, 'NodeDataSize not initialized.'); if (FNodeDataSize <= 0) or (Node = nil) [u][b][color=#ff0008]or (Node = FRoot) [/color][/b][/u]then Result := nil else Result := PChar(@Node.Data) + FTotalInternalDataSize; end; |
Re: TVirtualStringTree -> XML
:shock:
:wiejetzt: Hm... das ist schlecht... Sehr schlecht. Und was kann man da tun? Chris |
Re: TVirtualStringTree -> XML
Du solltest in Deinen Code mal direkt auf das Data zugreifen, oder den Node-Data Pointer separat speichern und darauf zurück zu greifen. Vielleicht hilft es Dir. Oder Du versuchst, die Original Sourcen (nach Backup!) zu ändern und neu kompilieren.
...:cat:.... |
Re: TVirtualStringTree -> XML
*ächz* Gott sei Dank gibt es sowas, wie MSN Messenger. Mit philwo's Hilfe habe ich es dann doch hinbekommen.
so sieht das ganze jetzt aus:
Code:
Chris
procedure TMainForm.SaveToXML(aFileName: string);
var xmlDoc: IXMLDOMDocument2; mainNode, subNode, subsubNode: IXMLDOMNode; curData, curSubData: TData; rootnode, subrootnode: PVirtualNode; i, j: integer; f: TextFile; begin DeleteFile(aFileName); AssignFile(f, aFileName); Rewrite(f); writeln(f, '<?xml version="1.0"?>'); writeln(f, '<projects>'); writeln(f, '</projects>'); CloseFile(f); xmlDoc := CoDOMDocument40.Create(); xmlDoc.load(aFileName); xmlDoc.setProperty('NewParser', true); if XMLDoc.parseError.errorCode <> 0 then begin ShowMessage('XML Fehler: ' + #13#10 + XMLDoc.parseError.reason + #13#10 + 'Source: ' + xmldoc.parseError.srcText); xmldoc := nil; end; [color=#ff0000] rootNode := vstProjects.RootNode.FirstChild; [/color] for i:=0 to vstProjects.RootNodeCount - 1 do begin if rootNode = nil then Exit; curData := PData(vstProjects.GetNodeData(rootNode))^; if not Assigned(@curData)then ShowMessage('Alert'); mainNode := xmlDoc.createElement('project'); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('name'); subNode.text := curData.Name; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('prglanguage'); subNode.text := curData.PrgLanguage; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('language'); subNode.text := curData.Language; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('projectdir'); subNode.text := curData.ProjectDir; mainNode.appendChild(subNode); xmlDoc.documentElement.appendChild(mainNode); subNode := xmlDoc.createElement('sourcefiles'); [color=#ff0000] subRootNode := rootNode.FirstChild;[/color] for j:=0 to rootNode.ChildCount - 1 do begin curSubData := PData(vstProjects.GetNodeData(subRootNode))^; xmlDoc.documentElement.appendChild(mainNode); subsubNode := xmlDoc.createElement('name'); subsubNode.text := curSubData.Name; subNode.appendChild(subsubNode); xmlDoc.documentElement.appendChild(mainNode); subsubNode := xmlDoc.createElement('prglanguage'); subsubNode.text := curSubData.PrgLanguage; subNode.appendChild(subsubNode); xmlDoc.documentElement.appendChild(mainNode); subsubNode := xmlDoc.createElement('filename'); subsubNode.text := curSubData.FileName; subNode.appendChild(subsubNode); subRootNode := subRootNode.NextSibling; end; mainNode.appendChild(subNode); xmlDoc.save(aFileName); rootNode := rootNode.NextSibling; end; end; |
Re: TVirtualStringTree -> XML
Super, dann schalte noch die "offene Frage" aus und Du darfst weiterprogrammieren :coder:
...:cat:... P.S.: Ich habe nichts gesagt, ist schon geschehen ;-) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:23 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