树形控件(CTreeCtrl)节点间拖动实现

当用户开始拖动CTreeCtrl中的一个节点时,将发送消息TVN_BEGINDRAG(左键拖动)或TVN_BEGINRDRAG(右键拖动)到父窗口,然后是响应WM_MOVE消息,最后当松开鼠标时,停止拖动操作,整个过程就是这样。主要涉及到以下几个消息:TVN_BEGINDRAG或TVN_BEGINRDRAG,WM_MOUSEMOVE,WM_LBUTTONUP或WM_RBUTTONUP,分别对应处理函数如下:

 

void CLayerMgrTreeCtrl::OnDrag(NMHDR *pNMHDR, LRESULT *pResult)
{

   //hBeforeDrag为开始拖动时鼠标拖动的节点句柄
   hBeforeDrag = ((LPNMTREEVIEW)pNMHDR)->itemOld.hItem;
   Main_OnBeginDrag(m_hWnd, (LPNMTREEVIEW)pNMHDR);
}

void CLayerMgrTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   Main_OnMouseMove(::GetParent(m_hWnd), m_hWnd, point.x, point.y);
   CTreeCtrl::OnMouseMove(nFlags, point);
}

void CLayerMgrTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   if (g_fDragging) 
    { 
       //拖放结束
        ImageList_EndDrag(); 
        ShowCursor(TRUE); 
        g_fDragging = FALSE;  
    } 
    return; 
}

// Main_OnBeginDrag - begins dragging an item in a tree-view control. 
// hwndTV - handle to the image list. 
// lpnmtv - address of information about the item being dragged.

void CLayerMgrTreeCtrl::Main_OnBeginDrag(HWND hwndTV, LPNMTREEVIEW lpnmtv) 
{ 
    HIMAGELIST himl;    // handle to image list 
    RECT rcItem;        // bounding rectangle of item 
    DWORD dwLevel;      // heading level of item 
    DWORD dwIndent;     // amount that child items are indented 
    TVHITTESTINFO tvht;

     tvht.pt.x = lpnmtv->ptDrag.x;
    tvht.pt.y = lpnmtv->ptDrag.y;
    hBeforeDrag = TreeView_HitTest(hwndTV, &tvht);
    // Tell the tree-view control to create an image to use 
    // for dragging. 
    himl = TreeView_CreateDragImage(hwndTV, lpnmtv->itemNew.hItem);

    // Get the bounding rectangle of the item being dragged. 
    TreeView_GetItemRect(hwndTV, lpnmtv->itemNew.hItem, &rcItem, TRUE);

    // Get the heading level and the amount that the child items are 
    // indented. 
    dwLevel = lpnmtv->itemNew.lParam; 
    dwIndent = (DWORD)::SendMessage(hwndTV, TVM_GETINDENT, 0, 0);

    // Start the drag operation. 
    ImageList_BeginDrag(himl, 0, 0, 0);
    ImageList_DragEnter(hwndTV, 50, 50);

    // Hide the mouse pointer, and direct mouse input to the 
    // parent window. 
    ShowCursor(FALSE); 
    g_fDragging = TRUE; 
    return;

}

// Main_OnMouseMove - drags an item in a tree-view control, 
// highlighting the item that is the target. 
// hwndParent - handle to the parent window. 
// hwndTV - handle to the tree-view control.
// xCur and yCur - x- and y-coordinates of the mouse pointer.

void CLayerMgrTreeCtrl::Main_OnMouseMove(HWND hwndParent, HWND hwndTV, LONG xCur, LONG yCur) 
{ 
    HTREEITEM htiTarget; // handle to target item 
    TVHITTESTINFO tvht; // hit test information

    if (g_fDragging) 
    { 
        // Drag the item to the current position of the mouse pointer. 
        ImageList_DragMove(xCur, yCur);

        // Find out if the pointer is on the item. If it is, 
        // highlight the item as a drop target. 
        tvht.pt.x = xCur; 
        tvht.pt.y = yCur; 
        CPoint pt ;
        pt.x = xCur;
        pt.y = yCur;
       CImageList::DragMove( pt );
       //鼠标经过时高亮显示
        CImageList::DragShowNolock( false ); //避免鼠标经过时留下难看的痕迹
        if ((htiTarget = TreeView_HitTest(hwndTV, &tvht)) != NULL) 
        {

           //hAfterDrag为拖动时鼠标所在的节点句柄,即拖动结束后的节点句柄
          hAfterDrag = htiTarget;

           TreeView_SelectItem(hwndTV, htiTarget);

           /* 我这里之前用了下面这个函数,是从其他地方看到的,拖动时正常,但拖动后会产生选中某项时

             * 不高亮显示了,让我检查了好久,郁闷,大家用的时候也注意点 */
           //TreeView_SelectDropTarget(hwndTV, htiTarget);
        } 
         CImageList::DragShowNolock( true );
    } 
    return; 
}

你可能感兴趣的:(拖动,CTreeCtrl,节点拖动)