dragNdrop两个VirtualTreeView

时间:2017-06-02 09:50:33

标签: delphi drag-and-drop virtualtreeview

如何在两个VirtualTreeView之间复制所有列?在我的情况下,只复制第一个。

image here

我使用的是VirtualTreeView v6.6。

我正在使用的代码:

type
  PItemNode1 = ^TItemNode1;

  TItemNode1 = record
    Name: WideString;
    Order: string;
    Quantity:String;
  end;

type
  PItemNode2 = ^TItemNode2;

  TItemNode2 = record
    Name: WideString;
    Order: string;
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Node: PVirtualNode;
begin
  VT.NodeDataSize := SizeOf(TItemNode1);
  VT2.NodeDataSize := SizeOf(TItemNode2);
  VT.RootNodeCount := 2;
  VT2.RootNodeCount := 10;
end;

插入OLE数据的步骤

procedure TForm1.InsertData(Sender: TVirtualStringTree; DataObject: IDataObject;
  Formats: TFormatArray; Effect: Integer; Mode: TVTNodeAttachMode);
var
  FormatAccepted: Boolean; 
  i: Integer;
begin

  FormatAccepted := false;
  for i := 0 to High(Formats) do
  begin
    if Formats[i] = CF_VIRTUALTREE then
    begin
      if not FormatAccepted then
      begin
        Sender.ProcessDrop(DataObject, Sender.DropTargetNode, Effect, Mode);
        FormatAccepted := True;
      end;
    end;
  end;
end;

拖放操作

procedure TForm1.VT2DragAllowed(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; var Allowed: Boolean);
begin
  Allowed := True;
end;

procedure TForm1.VT2DragDrop(Sender: TBaseVirtualTree; Source: TObject;
  DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
  Pt: TPoint; var Effect: Integer; Mode: TDropMode);
  procedure DetermineEffect;
  begin
    if Shift = [] then
    begin
      if Source = Sender then
        Effect := DROPEFFECT_MOVE
      else
        Effect := DROPEFFECT_COPY;
    end
    else
    begin
      if (Shift = [ssAlt]) or (Shift = [ssCtrl, ssAlt]) then
        Effect := DROPEFFECT_LINK
      else if Shift = [ssCtrl] then
        Effect := DROPEFFECT_COPY
      else
    end;
  end;

var
  Attachmode: TVTNodeAttachMode;
  Nodes: TNodeArray;
  i: Integer;
begin
  Nodes := nil;
  case Mode of
    dmAbove:
      Attachmode := amInsertBefore;
    dmOnNode:
      Attachmode := amAddChildLast;
    dmBelow:
      Attachmode := amInsertAfter;
  else
    Attachmode := amNowhere;
  end;
  if DataObject = nil then
  begin
  //VCL
    if Source is TVirtualStringTree then
    begin
      DetermineEffect;

      Nodes := VT2.GetSortedSelection(True);

      if Effect = DROPEFFECT_COPY then
      begin
        for i := 0 to High(Nodes) do
          VT2.CopyTo(Nodes[i], Sender.DropTargetNode, Attachmode, false);
      end
      else
        for i := 0 to High(Nodes) do
          VT2.MoveTo(Nodes[i], Sender.DropTargetNode, Attachmode, false);
    end;
  end
  else
  begin
    // OLE drag&drop.
    if Source is TBaseVirtualTree then
      DetermineEffect
    else
    begin
      if Boolean(Effect and DROPEFFECT_COPY) then
        Effect := DROPEFFECT_COPY
      else
        Effect := DROPEFFECT_MOVE;
    end;
    InsertData(Sender as TVirtualStringTree, DataObject, Formats, Effect,
      Attachmode);
  end;
end;

procedure TForm1.VT2DragOver(Sender: TBaseVirtualTree; Source: TObject;
  Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode;
  var Effect: Integer; var Accept: Boolean);
// Return True, if AParent - child node of ANode.
  function IsNodeParent(AParent, ANode: PVirtualNode): Boolean;
  var
    NextParent: PVirtualNode;
  begin
    NextParent := AParent;
    repeat
      NextParent := NextParent.Parent;
    until (NextParent = Sender.RootNode) or (NextParent = nil) or
      (NextParent = ANode);
    Result := ANode = NextParent;
  end;

var
  i: Integer;
  Nodes: TNodeArray;
begin
  Accept := True;
  if (Assigned(Sender.DropTargetNode)) and
    (Sender.DropTargetNode <> Sender.RootNode) then
    Nodes := (Sender as TVirtualStringTree).GetSortedSelection(True);
  if Length(Nodes) > 0 then
  begin
    for i := 0 to Length(Nodes) - 1 do
    begin
      Accept :=
        (not IsNodeParent(Sender.DropTargetNode, Nodes[i]))
        and (not(Sender.DropTargetNode = Nodes[i]));
      if not Accept then Exit;
    end;
  end;
end;

初始化VT2的节点(上图中的右VT)并获取它们的文本

procedure TForm1.VT2GetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  ItemNode: PItemNode2;

begin
  ItemNode := Sender.GetNodeData(Node);
  if Assigned(ItemNode) then
  begin
    case Column of
      0:
        CellText := ItemNode^.Name;
      1:
        CellText := ItemNode^.Order;
    end;
  end;
end;

procedure TForm1.VT2InitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  ItemNode: PItemNode2;
begin
  ItemNode := Sender.GetNodeData(Node);
  if Assigned(ItemNode) then
    if Length(ItemNode^.Name) = 0 then
      ItemNode^.Name := 'Node Index № ' + IntToStr(Node.Index);
      ItemNode^.Order := IntToStr(Node.Index);
end;

删除节点后获取新文本

procedure TForm1.VT2NewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; NewText: string);
var
  ItemNode: PItemNode2;
begin
  ItemNode := Sender.GetNodeData(Node);
  if Assigned(ItemNode) then
  begin
    case Column of
      0:
        ItemNode^.Name := NewText;
      1:
        ItemNode^.Order := NewText; // I've checked this line in the debugger. It is skipped
    end;
  end;
end;

初始化VT的节点(上图中的左侧VT)并获取它们的文本

procedure TForm1.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  ItemNode: PItemNode1;
begin
  ItemNode := Sender.GetNodeData(Node);
  if Assigned(ItemNode) then
    case Column of
      0:
        CellText := ItemNode^.Name;
      1:
          CellText := ItemNode^.Order;
    end;
end;
procedure TForm1.VTInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  ItemNode: PItemNode1;
begin
  ItemNode := Sender.GetNodeData(Node);
  if Assigned(ItemNode) then
    if Length(ItemNode^.Name) = 0 then
      ItemNode^.Name := 'VT1_Node № ' + IntToStr(Node.Index);
      ItemNode^.Order := IntToStr(Node.Index);
end;
end.

0 个答案:

没有答案