Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Zwei Knoten in VirtualStringTree vertauschen


Keks - Do 09.09.10 01:13
Titel: Zwei Knoten in VirtualStringTree vertauschen
Ich würde gerne beim Drag and Drop eines Knotens auf einen anderen die beiden Knoten (samt jeweiliger Unterknoten) vertauschen.
Vermutlich wäre es das beste, deren Pointer zu vertauschen. Leider gelingt mir dies nicht.

Ich dachte, ich versuche das mal so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type
  PTreeData = ^TTreeData;
  TTreeData = record
    //...
  end;

procedure TForm1.VSTDragDrop(Sender: TBaseVirtualTree; Source: TObject;
  DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
  Pt: TPoint; var Effect: Integer; Mode: TDropMode);
var
  tmpData, DataN1, DataN2 : PTreeData;
begin
  DataN1 := VST.GetNodeData(Sender.DropTargetNode);
  DataN2 := VST.GetNodeData(Sender.FocusedNode);
  GetMem(tmpData, SizeOf(PTreeData));

  tmpData^ := DataN1^;
  DataN1^ := DataN2^;
  DataN2^ := tmpData^;
end;

Bei der Zuweisung tmpData^ := DataN1^; kommt dann eine Zugriffsverletzung.
Ehrlich gesagt, weiß ich aber gar nicht, ob mein Ansatz überhaupt so richtig ist.

Kann mir bitte jemand dabei helfen? Würde mich sehr freuen!


Peter Schmelzer - So 26.09.10 11:16

Hallo Keks,

wenn Du mit GetMem nur Speicher für einen Zeiger reservierst, kannst Du nicht derefenziert Daten eines Records rein schreiben.

Du solltest den Speicher des Record reservieren:
GetMem(tmpData, SizeOf(TTreeData));

Peter


MaxWurzel - Do 28.10.10 10:08

Mit MoveTo funktioniert es auch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TMainForm.VXMLTDragDrop(Sender: TBaseVirtualTree;
  Source: TObject; DataObject: IDataObject; Formats: TFormatArray;
  Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode);
var node: PVirtualnode;
    nodenext: PVirtualnode;
    nodebefore: PVirtualnode;
begin
  node :=  sender.GetNodeAt(Pt.X,Pt.Y);
  nodenext := sender.FocusedNode.NextSibling;
  nodebefore := sender.FocusedNode.PrevSibling;
  Sender.MoveTo(Sender.FocusedNode, sender.GetNodeAt(Pt.X,Pt.Y),amInsertAfter,false);
  if assigned(nodenext) then
     Sender.MoveTo(node,nodenext,amInsertBefore,false)
  else
   Sender.MoveTo(node,nodebefore,amInsertAfter,false);
end;