Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TVirtualStringTree: nachträglich Objekt am Knoten tauschen (https://www.delphipraxis.net/150426-tvirtualstringtree-nachtraeglich-objekt-am-knoten-tauschen.html)

Brainshock 16. Apr 2010 09:36


TVirtualStringTree: nachträglich Objekt am Knoten tauschen
 
Moin,

ist es möglich nachträglich das Objekt an einem Node des VirtualTreeView zu tauschen?

1. Erstellen
Delphi-Quellcode:
data:= TMyData.Create;
vst.AddChild(nil, data);
2. Später soll der Knoten auf eine anderes Objekt zeigen.


PS: Bisher habe ich einen neuen Knoten mit den neuen Daten hinter den alten eingefügt und den alten danach gelöscht. Vllt. gehts aber auch irgendwie nur mit austauschen.

s.h.a.r.k 16. Apr 2010 09:45

Re: TVirtualStringTree: nachträglich Objekt am Knoten tausch
 
Klar kannst du das tauschen ;)

Brainshock 16. Apr 2010 10:54

Re: TVirtualStringTree: nachträglich Objekt am Knoten tausch
 
Hehe, sag mal wie :).

generic 16. Apr 2010 11:21

Re: TVirtualStringTree: nachträglich Objekt am Knoten tausch
 
an jedem TVirtualNode gibt es ein Zeiger Data bzw. ab dort ist ein Speicherbereich für die Daten.
Meist 4 Byte für einen Zeiger, wenn du mit Objekten arbeitest.
In diese 4 Bytes legst du deinen neuen Zeiger rein.


Delphi-Quellcode:
  TVirtualNode = packed record
    Index,                  // index of node with regard to its parent
    ChildCount: Cardinal;   // number of child nodes
    NodeHeight: Word;       // height in pixels
    States: TVirtualNodeStates; // states describing various properties of the node (expanded, initialized etc.)
    Align: Byte;            // line/button alignment
    CheckState: TCheckState; // indicates the current check state (e.g. checked, pressed etc.)
    CheckType: TCheckType;  // indicates which check type shall be used for this node
    Dummy: Byte;            // dummy value to fill DWORD boundary
    TotalCount,             // sum of this node, all of its child nodes and their child nodes etc.
    TotalHeight: Cardinal;  // height in pixels this node covers on screen including the height of all of its
                             // children
    // Note: Some copy routines require that all pointers (as well as the data area) in a node are
    //       located at the end of the node! Hence if you want to add new member fields (except pointers to internal
    //       data) then put them before field Parent.
    Parent,                 // reference to the node's parent (for the root this contains the treeview)
    PrevSibling,            // link to the node's previous sibling or nil if it is the first node
    NextSibling,            // link to the node's next sibling or nil if it is the last node
    FirstChild,             // link to the node's first child...
    LastChild: PVirtualNode; // link to the node's last child...
    Data: record end;       // this is a placeholder, each node gets extra data determined by NodeDataSize
  end;
Bei AddChild findest du diesen Code welcher den Zeiger bzw. den Inhalt setzt:

Delphi-Quellcode:
   
function TBaseVirtualTree.AddChild(Parent: PVirtualNode; UserData: Pointer = nil): PVirtualNode;
    if Assigned(UserData) then
      if FNodeDataSize >= 4 then
      begin
        NodeData := Pointer(PChar(@Result.Data) + FTotalInternalDataSize);
        NodeData^ := UserData;
        Include(Result.States, vsInitialUserData);
      end
result ist ein PVirtualNode

semo 17. Apr 2010 09:43

Re: TVirtualStringTree: nachträglich Objekt am Knoten tausch
 
Warum setzt du denn nicht gleich die Werte des TMyData Objekts in dem alten Knoten,
anstatt einen neuen Knoten zu erstellen, diesem das neue TMyData Objekt zu übergeben und den aten Knoten zu löschen?

Also etwa so:

Delphi-Quellcode:
var
  OldNodeData : PMyData;
begin
  if Assigned(ANode) then
  begin
    OldNodeData := VST.GetNodeData(ANode);
    if Assigned(OldNodeData) then
    begin
      OldNodeData^.Field1 := XYZ;
      OldNodeData^.Field2 := 123;
    end;
  end;
end;

Brainshock 3. Mai 2010 13:22

Re: TVirtualStringTree: nachträglich Objekt am Knoten tausch
 
Hier nun meine Lösung:

1. Ich habe eine abgeleitete Klasse vom Tree erstellt:

Delphi-Quellcode:
uses
  VirtualTrees;

type
  TVirtualStringTreeEx = class(TVirtualStringTree)
  public
    procedure ReplaceNodeData(Node: PVirtualNode; UserData: Pointer);
  end;
 
implementation

{ TVirtualStringTreeEx }

procedure TVirtualStringTreeEx.ReplaceNodeData(Node: PVirtualNode;
  UserData: Pointer);
var
  NodeData: ^Pointer;
begin
  if Assigned(UserData) then
   if NodeDataSize >= 4 then
   begin
     NodeData := Pointer(PByte(@Node.Data) + TotalInternalDataSize);
     NodeData^ := UserData;
   end  
end;

2. Programmcode aufs Ersetzen angepaßt:

Delphi-Quellcode:
var
  lNewData: TMyData;
  lNode: PVirtualNode;  
begin
  lNode:= vstData.FocusedNode;
  // lNewData besorgen
  ...
  // Daten ersetzen
  TVirtualStringTreeEx(vstData).ReplaceNodeData(lNode, lNewData);
end;
Ich hoffe es stimmt soweit und hilft vielleicht jemanden weiter.

Danke für die Hilfe.

Gruß, Matthias

Keks 8. Sep 2010 00:34

AW: TVirtualStringTree: nachträglich Objekt am Knoten tauschen
 
Ich würde gerne im DragDrop-Ereignis die beiden Knoten vertauschen (also FocusedNode mit DropTargetNode). Vermutlich wäre es das beste, deren beide Zeiger zu vertauschen. Leider weiß ich nicht, wie das korrekt geht. Ich denke, dieser Thread geht in eine ähnliche Richtung und ich habe mal etwas herumprobiert, aber es scheitert allein schon daran, dass "TotalInternalDataSize" nicht definiert ist. Könnt Ihr mir bitte kurz aufzeigen, wie man zwei Knoten korrekt vertauschen kann?

Brainshock 10. Sep 2010 09:36

AW: TVirtualStringTree: nachträglich Objekt am Knoten tauschen
 
Probier es mal so, wie ich es oben beschrieben habe.

Du mußt erst eine abgeleitet Klasse von TVirtualStringTree anlegen, diese übernimmt das Austauschen der Daten, siehe 1.
In deiner Methode DragDrop machst du ein cast deines Trees auf die abgeleitet Tree-Klasse TVirtualStringTreeEx(<YourTree>), damit du Zugriff auf die Funktion ReplaceNodeData() bekommst und die Daten austauschen kannst, siehe 2.

Keks 20. Sep 2010 22:37

AW: TVirtualStringTree: nachträglich Objekt am Knoten tauschen
 
Danke für die Antwort und sorry für die Verzögerung...
Was ist denn "TotalInternalDataSize"? Wo ist das denn deklariert?

Brainshock 24. Sep 2010 09:06

AW: TVirtualStringTree: nachträglich Objekt am Knoten tauschen
 
siehe VirtualTrees.pas:

Delphi-Quellcode:
TBaseVirtualTree = class(TCustomControl)
private
  ...
  FTotalInternalDataSize: Cardinal;   // Cache of the sum of the necessary internal data
                                    // size for all tree
...
end;
FTotalInternalDataSize eine private Variable in der Klasse TBaseVirtualTree, sie ist nicht von extern ansprechbar. Über die abgeleitete Klasse TVirtualStringTreeEx kommt man doch daran.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:54 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz