与树形控件有关的、常用的结构是TVITEM、TVINSERTSTRUCT 、NMTREEVIEW(NM_TREEVIEW )。前两个是用于插入节点时使用,而NMTREEVIEW是与树形控件的通告消息相关的结构。 当用鼠标左键拖拽树形控件时,控件会发出TVN_BEGINDRAG通告消息;当用鼠标右键拖拽时,则会发出TVN_BEGINRDRAG通告消息。拖拽树形控件时需要使用到IImageList::BeginDrag函数: IImageList::BeginDrag creates a temporary image list that is used for dragging. In response to subsequent WM_MOUSEMOVE messages, you can move the drag image by using IImageList::DragMove. To end the drag operation, you can use IImageList::EndDrag. 通常使用CTreeCtrl::CreateDragImage函数创建一个被拖拽节点的图像并返回一个CImageList指针(注意被拖拽的数据节点必须包含图像,否则返回的CImageList指针为空),然后利用该指针来调用CImageList::BeginDrag函数。除此之外还需要调用CImageList::DragEnter函数锁定、更新窗口,并在指定的位置显示被拖拽的图像: static BOOL PASCAL DragEnter( CWnd* pWndLock, CPoint point ); If pWndLock is NULL, this function draws the image in the display context associated with the desktop window, and coordinates are relative to the upper left corner of the screen. 注意BeginDrag函数只是在拖拽开始时创建要拖拽的图像,而DragEnter函数则显示该图像。 最后调用CWnd::SetCapture函数使后续所有的鼠标输入都发送到当前的CWnd对象而不管鼠标的位置(因为CImageList::DragEnter函数的第一个参数为NULL时表示在与桌面窗口相关的窗口,可以说就是当前程序的框架窗口,但不包括其他应用程序的窗口上显示被拖拽的图像。因此要使得被拖拽的图像在所有的窗口上而不仅仅是应用程序的框架窗口上显示,就需要调用CWnd::SetCapture函数。一旦调用了SetCapture函数,则在当前应用程序的非框架窗口,包括系统菜单上的鼠标按键动作均被发送到当前CWnd 对象,直到调用ReleaseCapture为止)。 然后就是在鼠标移动的消息响应函数中调用CImageList::DragMove函数移动被拖拽的图像,使之与鼠标的移动位置同步。最后是调用CImageList::DragShowNolock函数隐藏或显示拖拽的图像,但它并不是必须的,也可以不调用,因此之前已经调用过CImageList::DragEnter函数显示拖拽的图像了。当传递true值显示拖拽的图像时,DragShowNolock在这个过程中不像DragEnter函数一样锁定窗口。 值得注意的是,在拖拽节点过程中可以使用CTreeCtrl::HitTest函数判断鼠标滑动过程中所经过的点是否位于树形控件的某一个节点之上,如果是,则返回该树形节点的HTREEITEM。此时可以使用CTreeCtrl::SelectDropTarget函数或CTreeCtrl::SelectItem函数来高亮显示该节点。