DefTreeDragHandler

>>-aMessageExtensions~DefTreeDragHandler-----------------------><


A tree view control cannot handle a drag-and-drop operation within the tree view. Therefore, you can connect the DefTreeDragHandler method with the BEGINDRAG or BEGINRDRAG notification message (see ConnectTreeNotify) to allow the moving of an item or a node with all its subitems from one parent node to another within a tree view. The cursor shape is changed to a crosshair during the drag operation. If the cursor is moved over the item dragged, the cursor shape is changed to a slashed circle. You can cancel the drag operation by clicking the other mouse button while holding the button that started the drag operation.

The DefTreeDragHandler is implemented as follows:

 
::method DefTreeDragHandler
   use arg id, item, pt
   tc = self~GetTreeControl(id)
   hc = tc~Cursor_Cross   /* change cursor and store current */
   parse value tc~GetRect with left top right bottom
   oldItem = 0
   nocurs = 0
   lmb = self~IsMouseButtonDown("LEFT")
   rmb = self~IsMouseButtonDown("RIGHT")
   call time "R"
   do while (lmb \= 0 | rmb \= 0) & \(lmb \= 0 & rmb \= 0)
     pos = self~CursorPos
     parse var pos x y
     parse value tc~ScreenToClient(x, y) with newx newy
      ht = tc~HitTest(newx, newy)
      if ht \= 0 & ht~wordpos("ONITEM") > 0 then do
          parse var ht newParent where
          /* check if droptarget is the current parent or one of the dragged
             item&apos;s children */
          if newParent \= Item & newParent \= tc~Parent(Item) & tc~IsAncestor,
             (Item,newParent) = 0
          then do
             is. = tc~ItemInfo(newParent)
             if is.!State~Wordpos("INDROP") = 0 then
             do
                call time "R"
                tc~DropHighlight(newParent)
                if nocurs \= 0 then do
                  tc~RestoreCursorShape(nocurs) /*restore old cursor (cross)*/
                  nocurs = 0
                end
             end
             else if time("E") > 1 then do  /* expand node after 1 second */
                 if is.!Children \= 0 & is.!State~Wordpos("EXPANDED") = 0 then
                 tc~expand(newParent)
             end
          end
          else do
             if nocurs = 0 then do
                nocurs = tc~Cursor_No  /* set no cursor and retrieve
                                              current cursor (cross) */
                tc~DropHighlight  /* remove drop highlight */
             end
          end
      end
      else do
          if newParent \= 0 then do
             /* necessary to redraw cursor when moving on a valid item again */
              tc~DropHighlight  /* remove drop highlight */
              newParent = 0
          end
          if nocurs = 0 then nocurs = tc~Cursor_No  /* set no cursor and
                                      retrieve current cursor (cross) */
          /* handle scrolling */
          fvItem = tc~FirstVisible
          if (ybottom) & (tc~NextVisible(fvItem) \= 0) then do
              tc~MakeFirstVisible(tc~NextVisible(fvItem))
              if y-bottom < 200 then call sleepms 200-(y-bottom)
          end
      end
      lmb = self~IsMouseButtonDown("LEFT")
      rmb = self~IsMouseButtonDown("RIGHT")
   end
   if ht~wordpos("ONITEM") > 0 & lmb = 0 & rmb = 0 then do /* if mouse on item
                                                  and both mouse buttons up */
       item = tc~MoveItem(Item, newParent, 1)  /* move item under newParent */
   end
   tc~DropHighlight(0)  /* remove drop highlight */
   tc~select(item)      /* select item */
   tc~EnsureVisible(item)
   tc~RestoreCursorShape(hc)  /* restore old cursor */
   pos = self~CursorPos
   parse var pos x y
   self~SetCursorPos(x+1, y+1)  /* move cursor to force redraw */