delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback



Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi








Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (6)


A Gardener's Guide To The Tree View: Part IIIGo to Ghannodahn Kirrel's websiteComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
The Art of Transplants (Drag and Drop)
Product:
Delphi 4.x (or higher)
Category:
VCL-General
Skill Level:
Scoring:
Last Update:
04/10/2001
Search Keys:
delphi delphi3000 article borland vcl code-snippet drag drop treeview kirrel vcl tutorial
Times Scored:
7
Visits:
7670
Uploader: Ghannodahn Kirrel
Company: RealityCheck Studios
Reference: The Infinity Citadel
Component Download: http://www.icitadel.com/tech_resource/articles/downloads/treeviewdemo3.zip
 
Question/Problem/Abstract:
In Part III of the TreeView tutorial series, we will review the code necessary to achieve drag and drop with a tree view. As always, the source code is included in the component link at the top of this article.
Answer:



First off, I'd like to say that I am seriously enjoying these tutorials.  From a personal standpoint, they're helping to reinforce concepts that I've taken for granted, such as pointers and typecasting.  I hope that these articles are of use to you wonderful developers out there, who are helping to strengthen the backbone of the Information Age.  If you have learned anything from these tutorials, then I consider it a worthwhile effort.

If you have any questions or comments, please feel free to post a question to the forums, or to e-mail me personally at ghannodahn@icitadel.com.

Without further adieu, I will provide the anxious, impatient and/or paranoid users with the implementation source code to achieve drag and drop functionality with the TreeView component.


procedure TfrmTreeViewDemo3.tvwDemoMouseDown(Sender: TObject;
          Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
   // The tvwDemoMouseDown even fires when a mouse button is pressed
   //    while the cursor is sitting inside the TreeView.

var
   HitNode: TTreeNode;
begin
   // First, we're going to ensure that the left mouse button was
   //    pressed.  If any other button was pressed, then we'll ignore
   //    this event.

   if ( Button = mbLeft ) then
   begin
      // We'll set the HitNode variable to point to the TreeNode
      //    that the mouse is sitting on, if applicable.  This is
      //    accomplished by the GetNodeAt function of the TreeView
      //    component.  Our event provides us with the current mouse
      //    position ( x and y ), and the function will return a pointer
      //    to a TreeNode.

      HitNode := tvwDemo.GetNodeAt( X, Y );

      // Next, we are going to ensure that a node was actually hit.
      //    instead of the mouse sitting in empty space in the TreeView.
      //    For more complex checks, we can get a HitTests set.  For
      //    the time being, this method will suffice.  If no node
      //    is being hovered over by the mouse, GetNodeAt will return
      //    nil.

      if not( HitNode = nil ) then
      begin
         // Next, we're going to make sure that the node in question
         //    has a parent.  Since we're going to be handling dragging
         //    and dropping only with the nodes in this TreeView,
         //    there is no need to allow the dragging of the root node.

         if not( HitNode.Parent = nil ) then
         begin
            // If all these conditions are met, then we'll begin the
            //    drag operation.  This will set the cursor to the
            //    DragIcon property of the TreeView.  BeginDrag takes
            //    a single parameter, a boolean that specifies whether
            //    the drag should begin immediately, or wait for the
            //    user to start moving the mouse with the button
            //    depressed.  For standard Windows operation and in
            //    my opinion a much cleaner implementation, set this
            //    parameter to false.

            tvwDemo.BeginDrag( false );

            // In addition, we'll set the form-level variable
            //    FDragNode to our dragged TreeNode.  We'll need to
            //    retrieve it for dropping and validation purposes.

            FDragNode := HitNode;
         end;
      end;
   end;
end;

procedure TfrmTreeViewDemo3.tvwDemoDragOver( Sender, Source:
          TObject; X, Y: Integer; State: TDragState;
          var Accept: Boolean );
// The tvwDemoDragOver event fires when a dragged object is moved over
//    the TreeView component.  At this point, we can do whatever
//    processing necessary to validate the current drop target.

   function HasAsAncestor( SourceNode, CheckedNode: TTreeNode ): boolean;
   // This function declaration is scoped to the tvwDemoDragOver
   //    procedure and is not accessible from beyond the main
   //    procedure code.  This is useful for purposes of
   //    encapsulation, as well as readibility of your interface
   //    section.  Procedure scoping should be used when
   //    applicable, but make sure to plan ahead.  If I think I may
   //    need this function outside of this procedure at some point
   //    in the future, it would be beneficial to instead place it in
   //    a code repository, or better yet extend the functionality of
   //    the TTreeNode component to handle this ability.  We'll cover
   //    the customization of our TreeView component in a later
   //    tutorial.


   // The HasAsAncestor function checks to see if SourceNode is a
   //    decendant of CheckedNode.  This is neccessary to our
   //    validation process, and the purpose of the function will be
   //    discussed below.

   begin
      // We're going to default the result of this function to True.
      //    If our node passes all the tests, then at the end of the
      //    procedure we will set the Result to false.

      Result := true;

      // If the SourceNode is equal to or is the parent of
      //    CheckedNode, then we will return true.

      if ( ( CheckedNode = SourceNode ) or ( SourceNode.Parent = CheckedNode ) ) then
      begin
         exit;
      end;

      // We will now move up the hierarchy of CheckedNode's ancestors,
      //    looking for a match with SourceNode.  If one is found,
      //    then we will return true.

      while not( CheckedNode.Parent = nil ) do
      begin
         if ( CheckedNode = SourceNode ) then
         begin
            exit;
         end;

         CheckedNode := CheckedNode.Parent;
      end;

      // If all conditions have been passed, then we will return
      //    false.

      Result := false;
   end;
var
   // DropNode will point to the TreeNode that the mouse is
      //    hovering over.

   DropNode:   TTreeNode;
begin
   // If our drag source is not a TTreeView, then we'll ignore this
   //    event.

   if ( Source is TTreeView ) then
   begin
      // If it is, we're going to set DropNode to point to the
      //    TreeNode that is being dragged over.

      DropNode := tvwDemo.GetNodeAt( X, Y );

      // If we are not dragging over an actual node, then we'll ignore
      //    this event.

      if not( DropNode = nil ) then
      begin
         // Ensure that the node being dropped is not a decendant of
         //    the dragged node.  This way, nodes that are children,
         //    grandchildren, etc. of the dragged node are not valid
         //    drop targets.  Accepting a drag like that could have
         //    some serious logical drawbacks.

         Accept   := not( HasAsAncestor( FDragNode, DropNode ) );
      end;
   end;
end;

procedure TfrmTreeViewDemo3.tvwDemoDragDrop(Sender, Source:
          TObject; X, Y: Integer);
// The tvwDemoDragDrop procedure is fired when our dragged node is
//    dropped onto a valid target.

var
   // DropNode will point to the TreeNode that the mouse is hovering
   //    over.

   DropNode:   TTreeNode;
begin
   // If our drag source is not a TTreeView, then we'll ignore this
   //    event.

   if ( Source is TTreeView ) then
   begin
      // If it is, we're going to set DropNode to point to the
      //    TreeNode that is being dragged over.

      DropNode := tvwDemo.GetNodeAt( X, Y );

      // If a valid node is being dropped on, then we'll continue.
      if not( DropNode = nil ) then
      begin
         // First, we'll fire off the MoveTo method of TTreeNode.
         //    This method takes two parameters... one is the node to
         //    move to, and the second is of type TNodeAttachMode.
         //    This is an enumeration allowing several different
         //    options for where the node being moved ends up in
         //    relation to the destination node.  In our case,
         //    naAddChild will move the node to be the last child of
         //    the destination.

         FDragNode.MoveTo( DropNode, naAddChild );
      end;
   end;
end;

procedure TfrmTreeViewDemo3.tvwDemoEndDrag(Sender, Target:
          TObject; X, Y: Integer);
// The tvwDemoEndDrag procedure fires off when a drag is ended.  This
//    either happens when we manually end the drag ( with the EndDrag
//    method ), or when the mouse button is released.

begin
   // We want to clear our form-level variable once the drag has
   //    ended.

   FDragNode := nil;
end;


As always, the source code is included in the component link at the top of this article.

For interested readers, the next part of the TreeView tutorial series will be dealing with loading information from a database, as well as a possibly different approach to hierarchal data storage and retrieval that proved much faster that a simple recursive function.





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Treeview and drag-n-drop
    Sathya (Mar 7 2001 4:24AM)

I need to do Drag-n-drop in tree view like windows explorer in asp. Can any body help me in this aspects
Respond

RE: Treeview and drag-n-drop
Ghannodahn Kirrel (May 13 2001 9:33PM)

ASP could only really handle the server-side processing of that. What is/are your target browser(s)? JavaScript and DHTML are necessary, and Behaviors/Action Sheets could make the development much more efficient.
Respond

Using dragdrop and Imagelist
    Thomas Løvlie (Oct 4 2000 2:24AM)

This is more a question for help than a comment.

I have a TTreeView and I use a modified version of your dragdrop example (which I might add was an extremly helpful article). Then I added an Imagelist to add some color to the plain treeview, after that whenever I click on a node that can be dragged then it shows the dragged node. do you have any solution for this? To test just add an imagelist (standard size 16x16) and try
Respond

RE: Using dragdrop and Imagelist
Sathya (Mar 7 2001 4:31AM)

Can u send me that code with tree and drag-n-drop
Respond

component download
    Kurt Mueller (Sep 13 2000 4:28AM)

can't download from your IP-Adress
'Page not found'
Kurt
Respond

RE: component download
Ghannodahn Kirrel (Sep 13 2000 8:47AM)

I have moved the source downloads to a full-time web server.  This should alleviate any difficulties in downloading the components.  My sincerest apologies for the trouble.

"The line between genius and insanity is measured by success."
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


   


  Community Ad of
E. DSpirito
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)