高分求教:如何在treeview中用鼠标拖动来改变节点位置?在线给分!谢谢!

解决方案 »

  1.   

    怎么没有人回答? 因为不自己编写DragDrop事件是做不到的
      

  2.   

    需要对dragover,dragdrop写代码,举例如下:
    (tree的dragmode属性设为dmAutomatic)procedure Tform1.treeDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    var
      Node: TTreeNode;
    begin
      Accept := False;
      if Sender = Source then
      begin
        Node := TTreeView(Sender).GetNodeAt(X, Y);
        if Node = nil then Exit;
        if (Node.Parent = nil) or (TTreeView(Sender).Selected.Parent = nil) then Exit;
        Accept := True;
      end
    end;procedure Tform1.treeDragDrop(Sender, Source: TObject; X, Y: Integer);
    var
      AnItem: TTreeNode;
      AttachMode: TNodeAttachMode;
      Hit: THitTests;
    begin
      if Source = Sender then
      begin
        if Tree.Selected = nil then Exit;
        Hit := tree.GetHitTestInfoAt(X, Y);
        AnItem := tree.GetNodeAt(X, Y);
        if (Hit - [htOnItem, htOnIcon, htOnIndent, htOnbutton] <> Hit) then
        begin
          if (htOnItem in Hit) or (htOnIcon in Hit) then
          begin
            AttachMode := naAddChild;
            TTreeView(Source).Selected.MoveTo(AnItem, AttachMode);
          end
          else if (htOnIndent in Hit) or (htOnbutton in Hit) then
          begin
            AttachMode := naInsert;
            TTreeView(Source).Selected.MoveTo(AnItem, AttachMode);
          end;
        end;
      end;
    end;
      

  3.   

    给大家一段比较通用的代码,我自己一直用这个,很好用,经整理,如下:功能说明:
    在一个或者多个TTreeView之间拖动TTreeNode的代码,
    以两个TTreeView作为例子。
    剪贴TTreeNode参考下面的代码就可以做到。源代码:
    {在两个TTreeView之间拖动TTreeNode}
    {当然一个和多个是相同原理}
    {原作者信息}
    {
    Member Name inthe
    Date Account Created 10/10/98
    Expert Points 576944
    Profile Work in Music industry as an Engineer dealing with electrics, mechanical, electronics,pneumatics ,Plcs etc..
    Programming is my hobby, mostly delphi but have some knowledge of others such as c/c++,asm,php,ladder/stl etc.
    with computers ive had experience with Debian, Mandrake,OS-9 ,3.1/win9*,nt/2k
    ,macOS and a few other RTOS.
    }{zdcnow(磁效应)2002-8-21下载于E-E}
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls, StdCtrls;type
      TForm1 = class(TForm)
        TreeView1: TTreeView;
        TreeView2: TTreeView;
        procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
        procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
          State: TDragState; var Accept: Boolean);
        procedure TreeView2DragOver(Sender, Source: TObject; X, Y: Integer;
          State: TDragState; var Accept: Boolean);
        procedure TreeView2DragDrop(Sender, Source: TObject; X, Y: Integer);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
    implementation{$R *.DFM}procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
     State: TDragState; var Accept: Boolean);
    begin
      Accept := Source is TTreeView;
    end;procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
      procedure CopyChildNode(ASNode:TTreeNode;var ADNode:TTreeNode);
      var
        i:integer;
        CNode:TTreeNode;
      begin
       for i:=0 to ASNode.Count-1 do
       begin
         CNode:=TTreeView(Sender).Items.AddChild(ADNode,ASNode.Item[i].Text);
         if ASNode.Item[i].HasChildren then
           CopyChildNode(ASNode.Item[i],CNode);
       end;
      end;
    var
      NNode, SNode, DNode : TTreeNode;
    begin
      SNode := TTreeView(Source).Selected;
      DNode := TTreeView(Sender).GetNodeAt(X, Y);  if DNode = nil then
        NNode := TTreeView(Sender).Items.Add(nil, SNode.Text)
      else
        NNode := TTreeView(Sender).Items.AddChild(DNode, SNode.text);
      if SNode.HasChildren then CopyChildNode(SNode,NNode);
      SNode.Delete;
    end;procedure TForm1.TreeView2DragOver(Sender, Source: TObject; X, Y: Integer;
     State: TDragState; var Accept: Boolean);
    begin
      Accept := Source is TTreeView;
    end;procedure TForm1.TreeView2DragDrop(Sender, Source: TObject; X, Y: Integer);
      procedure CopyChildNode(ASNode:TTreeNode;var ADNode:TTreeNode);
      var
        i:integer;
        CNode:TTreeNode;
      begin
       for i:=0 to ASNode.Count-1 do
       begin
         CNode:=TTreeView(Sender).Items.AddChild(ADNode,ASNode.Item[i].Text);
         if ASNode.Item[i].HasChildren then
           CopyChildNode(ASNode.Item[i],CNode);
       end;
      end;
    var
      NNode, SNode, DNode : TTreeNode;
    begin
      SNode := TTreeView(Source).Selected;
      DNode := TTreeView(Sender).GetNodeAt(X, Y);  if DNode = nil then
        NNode := TTreeView(Sender).Items.Add(nil, SNode.Text)
      else
        NNode := TTreeView(Sender).Items.AddChild(DNode, SNode.text);
      if SNode.HasChildren then CopyChildNode(SNode,NNode);
      SNode.Delete;
    end;end.
      

  4.   

    //下面代码实现treeview中结点通过拖拽改变位置和两个listview中的item通过拖拽在两个listview调动位置
    unit Main;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls, ExtCtrls, StdCtrls;type
      TScrollDirection = (sdUp, sdDown, sdNone);  TForm1 = class(TForm)
        TreeView1: TTreeView;
        ImageList1: TImageList;
        ListView1: TListView;
        ListView2: TListView;
        Timer1: TTimer;
        Button1: TButton;
        Label1: TLabel;
        Label2: TLabel;
        Label3: TLabel;
        Label4: TLabel;
        procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
          State: TDragState; var Accept: Boolean);
        procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
        procedure FormCreate(Sender: TObject);
        procedure ListView1DragOver(Sender, Source: TObject; X, Y: Integer;
          State: TDragState; var Accept: Boolean);
        procedure ListView2DragDrop(Sender, Source: TObject; X, Y: Integer);
        procedure Timer1Timer(Sender: TObject);
        procedure ListView1EndDrag(Sender, Target: TObject; X, Y: Integer);
        procedure TreeView1EndDrag(Sender, Target: TObject; X, Y: Integer);
        procedure Button1Click(Sender: TObject);
      private
        TargetWin: TWinControl;
        ScrollDirection: TScrollDirection;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}var
      //the maximum distance from the top or bottom of
      //the WinControls in which a drag scroll will occur...
      SCROLLMARGIN: integer = 18;//---------------------------------------------------------------------procedure TForm1.FormCreate(Sender: TObject);
    var
      rect: TRect;
    begin
      Treeview1.fullexpand;
      //Get the height of a listview item for
      //a better value for SCROLLMARGIN...
      rect := Listview1.items[0].DisplayRect(drBounds);
      SCROLLMARGIN := rect.bottom-rect.Top;
    end;
    //---------------------------------------------------------------------procedure TForm1.Button1Click(Sender: TObject);
    begin
      close;
    end;//---------------------------------------------------------------------
    // This demonstrates dragging of nodes within a treeview...
    //---------------------------------------------------------------------procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    begin
      Accept := Source = Sender;
      if not Accept then exit;  //See if scrolling is needed...
      with TTreeView(Sender) do
      begin
        if (Y < SCROLLMARGIN) then
          ScrollDirection := sdUp
        else if (Y > ClientHeight - SCROLLMARGIN) then
          ScrollDirection := sdDown
        else
          ScrollDirection := sdNone;    if ScrollDirection = sdNone then
          Timer1.enabled := false
        else
        begin
          TargetWin := TWinControl(Sender);
          Timer1.enabled := true;
        end;
      end;
    end;
    //---------------------------------------------------------------------procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    begin
      with TTreeView(Sender) do
      begin
        if (Sender <> Source) or (DropTarget = nil) or
          (DropTarget = Selected) then exit;
        Selected.MoveTo(DropTarget,naAddChildFirst);
      end;
    end;
    //---------------------------------------------------------------------procedure TForm1.TreeView1EndDrag(Sender, Target: TObject; X, Y: Integer);
    begin
      Timer1.enabled := false;
    end;//---------------------------------------------------------------------
    // This demonstrates dragging of nodes between listviews...
    //---------------------------------------------------------------------procedure TForm1.ListView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    begin
      if (Source is TListView) {and (Source <> Sender)} then
        Accept := true else
        Accept := false;
      if not Accept then exit;  //OK, now see if scrolling is needed...
      with TListView(Sender) do
      begin
        if (Y < SCROLLMARGIN*2) then //nb: allow for the listview header
          ScrollDirection := sdUp
        else if (Y > ClientHeight - SCROLLMARGIN) then
          ScrollDirection := sdDown
        else
          ScrollDirection := sdNone;    if ScrollDirection = sdNone then
          Timer1.enabled := false
        else
        begin
          TargetWin := TWinControl(Sender);
          Timer1.enabled := true;
        end;
      end;
    end;
    //---------------------------------------------------------------------procedure TForm1.ListView2DragDrop(Sender, Source: TObject; X, Y: Integer);
    var
      ListItem: TListItem;
    begin
      Timer1.enabled := false;
      if not (Source is TListView) or (Source = Sender) then exit;
      with TListView(Source).Selected do
      begin
        ListItem := TListView(Sender).items.add;
        ListItem.Caption := Caption;
        ListItem.ImageIndex := ImageIndex;
        Delete; //deletes source item after adding target item
      end;
    end;
    //---------------------------------------------------------------------procedure TForm1.ListView1EndDrag(Sender, Target: TObject; X, Y: Integer);
    begin
      Timer1.enabled := false;
    end;//---------------------------------------------------------------------
    // Timer used with all WinControls for scrolling...
    //---------------------------------------------------------------------procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      //Note: Timer1.interval = 100 but this can changed
      //to speed up or slow down the scroll rate.
      ImageList1.HideDragImage;
      with TargetWin do
        if ScrollDirection = sdUp then
          sendmessage(handle,WM_VSCROLL,SB_LINEUP,0) else
          sendmessage(handle,WM_VSCROLL,SB_LINEDOWN,0);
      ImageList1.ShowDragImage;
    end;end.
      

  5.   

    我这个代码比较短,不过用着也挺。如果有问题,烦劳告诉我,我再改进。
    这是在一个TreeView里移动的,稍改一下,就可用于多个的情形了。
    procedure TForm1.tvDragDrop(Sender, Source: TObject; X, Y: Integer);
    var
      node:ttreenode;
    begin
      node:=tv.getNodeAt(X, Y);
      if node<> tv.Selected then
        tv.Selected.MoveTo(node,naAddChild );
    end;procedure TForm1.tvDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    begin
      accept:=sender=source;
    end;