HOWTO: Implementing Basic Drag and Drop In a Tree ControlID: Q214814
|
This article illustrates how to implement basic drag and drop functionality for a tree control using SDK style techniques.
In order to successfully implement drag and drop in a tree control complete the following steps:
From your windows procedure
.
.
.
case WM_NOTIFY:
{
switch(((LPNMHDR)l_parm)->code)
{
case TVN_BEGINDRAG:
{
b_ret = begin_drag((LPNMTREEVIEW)l_parm) ;
break ;
}
}
break ;
.
.
.
BOOL begin_drag(LPNMTREEVIEW p_nmtree)
{
//Create an image list that holds our drag image
h_drag = TreeView_CreateDragImage(h_tree, p_nmtree->itemNew.hItem) ;
//begin the drag operation
ImageList_BeginDrag(h_drag, 0, 0, 0) ;
//hide the cursor
ShowCursor(FALSE) ;
//capture the mouse
SetCapture(GetParent(h_tree)) ;
//set global flag to indicate we are in the middle of a drag operation
g_fdragging = TRUE ;
//convert coordinates to screen coordinates
ClientToScreen(h_tree, &(p_nmtree->ptDrag)) ;
//paint our drag image and lock the screen.
ImageList_DragEnter(NULL, p_nmtree->ptDrag.x, p_nmtree->ptDrag.y) ;
return TRUE ;
}
Once the drag image is created, the next major section of code handles the WM_MOUSEMOVE message. The following code illustrates one way to handle implement WM_MOUSEMOVE to achieve a smooth transition:
From your windows procedure
.
.
.
case WM_MOUSEMOVE:
{
POINT pnt ;
HTREEITEM h_item = NULL ;
pnt.x = GET_X_LPARAM(l_parm) ;
pnt.y = GET_Y_LPARAM(l_parm) ;
if(g_fdragging)
{
//unlock window and allow updates to occur
ImageList_DragLeave(NULL) ;
ClientToScreen(h_wnd, &pnt) ;
//check with the tree control to see if we are on an item
TVHITTESTINFO tv_ht ;
ZeroMemory(&tv_ht, sizeof(TVHITTESTINFO)) ;
tv_ht.flags = TVHT_ONITEM ;
tv_ht.pt.x = pnt.x ;
tv_ht.pt.y = pnt.y ;
ScreenToClient(h_tree, &(tv_ht.pt)) ;
h_item = (HTREEITEM)SendMessage(h_tree, TVM_HITTEST, 0, (LPARAM)&tv_ht) ;
if(h_item)
{ //if we had a hit, then drop highlite the item
SendMessage(h_tree, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)h_item) ;
}
//paint the image in the new location
ImageList_DragMove(pnt.x,pnt.y) ;
//lock the screen again
ImageList_DragEnter(NULL, pnt.x, pnt.y) ;
b_ret = TRUE ;
}
break ;
}
The end of the drag operation occurs when a WM_LBUTTONUP or WM_RBUTTONUP message is received, depending on the type of mouse down event that initiated the drag. If you need to distinguish between the two at the time the drag is initiated, use the Windows API function GetKeyState to determine which mouse button is currently in use; that is, if you are using a different drag image for a right mouse drag or a left mouse drag. The following code illustrates one way to handle WM_LBUTTONUP to end the drag operation.
From your windows procedure
.
.
.
case WM_LBUTTONUP:
{
HTREEITEM h_item = NULL ;
TVHITTESTINFO tv_ht ;
TVITEM tv ;
ZeroMemory(&tv, sizeof(TVITEM)) ;
ZeroMemory(&tv_ht, sizeof(TVHITTESTINFO)) ;
if(g_fdragging)
{
ImageList_DragLeave(NULL) ;
ImageList_EndDrag() ;
ReleaseCapture() ;
//determin if we let up on an item
GetCursorPos(&(tv_ht.pt)) ;
ScreenToClient(h_tree, &(tv_ht.pt)) ;
tv_ht.flags = TVHT_ONITEM ;
h_item = (HTREEITEM)SendMessage(h_tree, TVM_HITTEST, 0, (LPARAM)&tv_ht) ;
ShowCursor(TRUE) ;
g_fdragging = FALSE ;
b_ret = TRUE ;
if(h_item)
{
/*we need to defer changing the selection until done processing this message post message allows us to do this. */
PostMessage(h_wnd, M_CHANGEFOCUS, (WPARAM)0, (LPARAM)h_item) ;
}
}
break ;
}
The code for handling the M_CHANGEFOCUS message (a user defined message) is included only for clarity.
//message define
#define M_CHANGEFOCUS WM_APP + 1 //use 0 for WPARAM and
//HTREEITEM of new item for LPARAM
From your windows procedure
.
.
.
case M_CHANGEFOCUS:
{
TreeView_SelectDropTarget(h_tree, NULL) ;
TreeView_SelectItem(h_tree, (HTREEITEM)l_parm) ;
break ;
}
How an application handles the end of a drag and drop operation is a decision made by the individual developer but if you plan to send further messages to the tree control based on the drag, it is recommended that you use a postmessage scheme. This is a highly recommended method that allows the control to finish processing the mouse message.
Additional query words:
Keywords : kbCtrl kbImgList kbNTOS400 kbWinOS2000 kbSDKPlatform kbTreeView kbGrpUser kbWinOS95 kbWinOS98
Version : WINDOWS:95,98
Platform : WINDOWS
Issue type : kbhowto
Last Reviewed: April 16, 1999