title: Delphi treeview drag and drop between nodes
body: <p>I want to allow the user to arrange a treeView's nodes as he likes, but I am running into a lot of problems. Like for example:</p>
  
  <ul>
  <li>After I do a few drag and drops, the treeview stops responding and I
  have to kill the app. Also if I start dragging and give up (press
  cancel, or drop it back from where i Picked it) the application hangs... and I can't do anything</li>
  <li>If a user wants to re-arange the order of 3 nodes that are child of
  the same main node, he can't do it like in other applications. Why?
  Isn't there any method to allow the user to drop his node in BETWEEN
  2 other nodes? Delphi seems to allow the user to drop a nod only on
  top of another. </li>
  </ul>
  
  <p>That's not good. I want a behavior like in this picture</p>
  
  <p><img src="https://i.stack.imgur.com/W8klE.jpg" alt="enter image description here"></p>
  
  <p>So the destination of the Node3, should be between Node1 and Node2. Of course the drop ON TOP of a node should be available, but this BETWEEN NODES functionality should be available too.</p>
  
  <p>My code so far is:</p>
  
  <pre><code>procedure TForm3.FormCreate(Sender: TObject);
  begin
    tv.FullExpand;
  end;
  
  procedure TForm3.tvDragDrop(Sender, Source: TObject; X, Y: Integer);
  var
    TargetNode, SourceNode : TTreeNode;
  begin
    with TV do
    begin
      TargetNode := GetNodeAt(X,Y); // Get target node
      SourceNode := Selected;
      if (TargetNode = nil) then
      begin
        EndDrag(False);
        Exit;
      end;
      MoveNode(TargetNode,SourceNode);
      SourceNode.Free;
    end;
  end;
  
  procedure TForm3.tvDragOver(Sender, Source: TObject; X, Y: Integer;
    State: TDragState; var Accept: Boolean);
  begin
    if (Sender = TV) then // If TRUE than accept the draged item
    begin
      Accept := True;
    end;
  end;
  procedure TForm3.tvEndDrag(Sender, Target: TObject; X, Y: Integer);
  begin
    TV.Repaint;
  end;
  
  procedure TForm3.tvMouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  begin
    tv.BeginDrag(false,-1);
  end;
  
  Procedure TForm3.MoveNode(TargetNode, SourceNode : TTreeNode);
  var
    nodeTmp : TTreeNode;
    i : Integer;
  begin
    with TV do
    begin
      nodeTmp := Items.AddChild(TargetNode,SourceNode.Text);
      for i := 0 to SourceNode.Count -1 do
      begin
        MoveNode(nodeTmp,SourceNode.Item[i]);
      end;
    end;
  end;
  </code></pre>
  
  <p>where of course TV is a TTreeView.</p>