Programatically scrolling a ListView or TreeView during a drag/drop operation 

To get a TreeView to scroll, the following example reverts to the API call SendMessage().  The key to getting the TreeView to scroll when the mouse cursor is beyond the confines of the TreeView, is to use the OnDragOver event of the control that the mouse moves to.  That is, after a call to BeginDrag(), the only mouse tracking events (the only easily accessible mouse tracking events) are the OnDragOver events.  So depending on what control is above or below your TreeView, you'll use it's OnDragOver event to trigger a scroll.  In the example below, I used the Form's OnDragOver event handler to scroll the TreeView.  Realize, that this method fails if you drag beyond the boundaries of your Form, but there are workarounds for that too.  One workaround would be to create a new caption less transparent Form behind your Form, and trigger a scroll from that Form's OnDragOver. 

KEYWORDS: SendMessage, BeginDrag, OnDragOver 

 

//---------------------------------------------------------------------------
//in source... 

void __fastcall TForm1::TreeView1DragOver(TObject *Sender, TObject 
*Source, int X, int Y, TDragState State, bool &Accept) 

    //Check to see if the Control being dragged is 
    //indeed a TreeView, and decide to accept the drop or not 
    if (Source == Sender) Accept = true
    else Accept = false
    
    //Scroll if out of visibility 
    int offset = TreeView1->Font->Height; 
    if (Y >= TreeView1->Height + offset) 
    { 
        SendMessage(TreeView1->Handle, WM_VSCROLL, SB_LINEDOWN, 0); 
    } 
    if (Y <= 0) 
    { 
        SendMessage(TreeView1->Handle, WM_VSCROLL, SB_LINEUP, 0); 
    } 

//--------------------------------------------------------------------------------

void __fastcall TForm1::TreeView1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) 

    if (!dynamic_cast<TTreeView *>(Sender)) return

    //Convert Sender into a TTreeView 
    TTreeView *DragTreeView = (TTreeView *)Sender; 

    //Begin the dragging process 
    DragTreeView->BeginDrag(0); 

//--------------------------------------------------------------------------------

void __fastcall TForm1::FormDragOver(TObject *Sender, TObject *Source, 
int X, int Y, TDragState State, bool &Accept) 

    Accept = false

    //Scroll if out of visibility 
    int offset = TreeView1->Font->Height; 
    if (Y >= TreeView1->Height + offset) 
    { 
        SendMessage(TreeView1->Handle, WM_VSCROLL, SB_LINEDOWN, 0); 
    } 
    if (Y <= 0) 
    { 
        SendMessage(TreeView1->Handle, WM_VSCROLL, SB_LINEUP, 0); 
    } 

 


 
 

Note that I didn't include the OnDragDrop event handler, as this method changes according to the destination of the drop.