需要实现的操作方式及要求:1) 节点拖动:
简单描述:将一个节点(包括它的所有子孙节点)拖动到其他位置,同时删除该节点原来所在位置。 拖动操作包括两种基本情况: i) 设有非叶子节点x,对x的拖动操作,是指将x从原位置移走,成为非叶子节点y的儿子节点
这种情况下,在拖动前要满足条件:x不能是y的儿子节点
这种拖动操作的影响对象是一个节点下所有的节点,即整个一棵子树x。 上面这种拖动操作会有两种情况: 拖动后,x作为y的第一个儿子节点,如果x所辖叶子节点先于y所辖叶子节点
拖动后,x作为y的最后一个儿子节点,如果y所辖叶子节点先于x所辖叶子节点 ii) 设有叶子节点x, 对x的拖动操作,是指将x从原位置移走,与另一个叶子节点y合并为一个叶子节点
执行这种拖动操作后,如果x的父亲节点没有其他子女,要删除x的父亲节点,并且按照这种原则
依次向上删除节点。 这种拖动操作实际上是为了实现叶子节点的合并
比如树中有两个叶子节点,分别是“计算”和“机”,我们认为这是分词错误,有必要把这两个叶子节点合并为一个。
无论是哪种拖动情况,在拖动后都要满足条件: 不能改变x所辖叶子节点和y所辖叶子节点的位置前后顺序关系例句如下:
s[np[ap[咬死了猎人的]np[狗]],vp[正向这里跑过来]]
s[np[ap[咬死了猎人的],np[狗]],vp[正向这里跑过来]]
s[np[ap[vp[vp[咬死了],np[猎人]],u[的]],np[狗]],vp[dp[正],vp[向这里跑过来]]]
s[np[ap[vp[vp[vp[咬死],u[了]],np[猎人]],u[的]],np[狗]],vp[dp[正],vp[向这里跑过来]]]
s[np[ap[vp[vp[vp[v[咬],v[死]],u[了]],np[猎人]],u[的]],np[狗]],vp[dp[正],vp[pp[p[向],s[这里]],vp[v[跑],v[过来]]]]]
zj[dj[np[他们/r],vp[vp[vp[到/v],np[校园/n]],vp[vp[去/v],vp[vp[玩/v],np[球/n]]]]],M[。/w]][]代表层次,在界面上操作,要满足上面的要求
请大家讨论讨论怎么实现?
简单描述:将一个节点(包括它的所有子孙节点)拖动到其他位置,同时删除该节点原来所在位置。 拖动操作包括两种基本情况: i) 设有非叶子节点x,对x的拖动操作,是指将x从原位置移走,成为非叶子节点y的儿子节点
这种情况下,在拖动前要满足条件:x不能是y的儿子节点
这种拖动操作的影响对象是一个节点下所有的节点,即整个一棵子树x。 上面这种拖动操作会有两种情况: 拖动后,x作为y的第一个儿子节点,如果x所辖叶子节点先于y所辖叶子节点
拖动后,x作为y的最后一个儿子节点,如果y所辖叶子节点先于x所辖叶子节点 ii) 设有叶子节点x, 对x的拖动操作,是指将x从原位置移走,与另一个叶子节点y合并为一个叶子节点
执行这种拖动操作后,如果x的父亲节点没有其他子女,要删除x的父亲节点,并且按照这种原则
依次向上删除节点。 这种拖动操作实际上是为了实现叶子节点的合并
比如树中有两个叶子节点,分别是“计算”和“机”,我们认为这是分词错误,有必要把这两个叶子节点合并为一个。
无论是哪种拖动情况,在拖动后都要满足条件: 不能改变x所辖叶子节点和y所辖叶子节点的位置前后顺序关系例句如下:
s[np[ap[咬死了猎人的]np[狗]],vp[正向这里跑过来]]
s[np[ap[咬死了猎人的],np[狗]],vp[正向这里跑过来]]
s[np[ap[vp[vp[咬死了],np[猎人]],u[的]],np[狗]],vp[dp[正],vp[向这里跑过来]]]
s[np[ap[vp[vp[vp[咬死],u[了]],np[猎人]],u[的]],np[狗]],vp[dp[正],vp[向这里跑过来]]]
s[np[ap[vp[vp[vp[v[咬],v[死]],u[了]],np[猎人]],u[的]],np[狗]],vp[dp[正],vp[pp[p[向],s[这里]],vp[v[跑],v[过来]]]]]
zj[dj[np[他们/r],vp[vp[vp[到/v],np[校园/n]],vp[vp[去/v],vp[vp[玩/v],np[球/n]]]]],M[。/w]][]代表层次,在界面上操作,要满足上面的要求
请大家讨论讨论怎么实现?
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
*pResult = 0; //如果是无意拖曳,则放弃操作
if( (GetTickCount() - m_dwDragStart) < DRAG_DELAY )
return; m_hItemDragS = pNMTreeView->itemNew.hItem;
m_hItemDragD = NULL; //得到用于拖动时显示的图象列表
m_pDragImage = CreateDragImage( m_hItemDragS );
if( !m_pDragImage )
return; m_bDragging = true;
m_pDragImage->BeginDrag ( 0,CPoint(8,8) );
CPoint pt = pNMTreeView->ptDrag;
ClientToScreen( &pt );
m_pDragImage->DragEnter ( this,pt ); //"this"将拖曳动作限制在该窗口
SetCapture(); m_nScrollTimerID = SetTimer( 2,40,NULL );
}void CXTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
HTREEITEM hItem;
UINT flags; //检测鼠标敏感定时器是否存在,如果存在则删除,删除后再定时
if( m_nHoverTimerID )
{
KillTimer( m_nHoverTimerID );
m_nHoverTimerID = 0;
}
m_nHoverTimerID = SetTimer( 1,800,NULL ); //定时为 0.8 秒则自动展开
m_HoverPoint = point; if( m_bDragging )
{
CPoint pt = point;
CImageList::DragMove( pt ); //鼠标经过时高亮显示
CImageList::DragShowNolock( false ); //避免鼠标经过时留下难看的痕迹
if( (hItem = HitTest(point,&flags)) != NULL )
{
SelectDropTarget( hItem );
m_hItemDragD = hItem;
}
CImageList::DragShowNolock( true ); //当条目被拖曳到左边缘时,将条目放在根下
CRect rect;
GetClientRect( &rect );
if( point.x < rect.left + 20 )
m_hItemDragD = NULL;
} CTreeCtrl::OnMouseMove(nFlags, point);
}void CXTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
CTreeCtrl::OnLButtonUp(nFlags, point); if( m_bDragging )
{
m_bDragging = FALSE;
CImageList::DragLeave( this );
CImageList::EndDrag();
ReleaseCapture();
delete m_pDragImage; SelectDropTarget( NULL );
if( m_hItemDragS == m_hItemDragD )
{
KillTimer( m_nScrollTimerID );
return;
} Expand( m_hItemDragD,TVE_EXPAND ); HTREEITEM htiParent = m_hItemDragD;
while( (htiParent = GetParentItem(htiParent)) != NULL )
{
if( htiParent == m_hItemDragS )
{
HTREEITEM htiNewTemp = CopyBranch( m_hItemDragS,NULL,TVI_LAST );
HTREEITEM htiNew = CopyBranch( htiNewTemp,m_hItemDragD,TVI_LAST );
DeleteItem( htiNewTemp );
SelectItem( htiNew );
KillTimer( m_nScrollTimerID );
return;
}
} HTREEITEM htiNew = CopyBranch( m_hItemDragS,m_hItemDragD,TVI_LAST );
DeleteItem( m_hItemDragS );
SelectItem( htiNew );
KillTimer( m_nScrollTimerID );
}
}//拷贝条目
HTREEITEM CXTreeCtrl::CopyItem(HTREEITEM hItem, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{
TV_INSERTSTRUCT tvstruct;
HTREEITEM hNewItem;
CString sText; //得到源条目的信息
tvstruct.item.hItem = hItem;
tvstruct.item.mask = TVIF_CHILDREN|TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
GetItem( &tvstruct.item );
sText = GetItemText( hItem );
tvstruct.item.cchTextMax = sText.GetLength ();
tvstruct.item.pszText = sText.LockBuffer (); //将条目插入到合适的位置
tvstruct.hParent = htiNewParent;
tvstruct.hInsertAfter = htiAfter;
tvstruct.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
hNewItem = InsertItem( &tvstruct );
sText.ReleaseBuffer (); //限制拷贝条目数据和条目状态
SetItemData( hNewItem,GetItemData(hItem) );
SetItemState( hNewItem,GetItemState(hItem,TVIS_STATEIMAGEMASK),TVIS_STATEIMAGEMASK); return hNewItem;
}//拷贝分支
HTREEITEM CXTreeCtrl::CopyBranch(HTREEITEM htiBranch, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{
HTREEITEM hChild;
HTREEITEM hNewItem = CopyItem( htiBranch,htiNewParent,htiAfter );
hChild = GetChildItem( htiBranch ); while( hChild != NULL )
{
CopyBranch( hChild,hNewItem,htiAfter );
hChild = GetNextSiblingItem( hChild );
} return hNewItem;
}void CXTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
//处理无意拖曳
m_dwDragStart = GetTickCount();
CTreeCtrl::OnLButtonDown(nFlags, point);
}void CXTreeCtrl::OnTimer(UINT nIDEvent)
{
//鼠标敏感节点
if( nIDEvent == m_nHoverTimerID )
{
KillTimer( m_nHoverTimerID );
m_nHoverTimerID = 0;
HTREEITEM trItem = 0;
UINT uFlag = 0;
trItem = HitTest( m_HoverPoint,&uFlag );
if( trItem && m_bDragging )
{
SelectItem( trItem );
Expand( trItem,TVE_EXPAND );
}
}
//处理拖曳过程中的滚动问题
else if( nIDEvent == m_nScrollTimerID )
{
m_TimerTicks++;
CPoint pt;
GetCursorPos( &pt );
CRect rect;
GetClientRect( &rect );
ClientToScreen( &rect ); HTREEITEM hItem = GetFirstVisibleItem();
if( pt.y < rect.top +10 )
{
//向上滚动
int slowscroll = 6 - (rect.top + 10 - pt.y )/20;
if( 0 == (m_TimerTicks % ((slowscroll > 0) ? slowscroll : 1)) )
{
CImageList::DragShowNolock ( false );
SendMessage( WM_VSCROLL,SB_LINEUP );
SelectDropTarget( hItem );
m_hItemDragD = hItem;
CImageList::DragShowNolock ( true );
}
}
else if( pt.y > rect.bottom - 10 )
{
//向下滚动
int slowscroll = 6 - (pt.y - rect.bottom + 10)/20;
if( 0 == (m_TimerTicks % ((slowscroll > 0) ? slowscroll : 1)) )
{
CImageList::DragShowNolock ( false );
SendMessage( WM_VSCROLL,SB_LINEDOWN );
int nCount = GetVisibleCount();
for( int i=0 ; i<nCount-1 ; i++ )
hItem = GetNextVisibleItem( hItem );
if( hItem )
SelectDropTarget( hItem );
m_hItemDragD = hItem;
CImageList::DragShowNolock ( true );
}
}
}
else
CTreeCtrl::OnTimer(nIDEvent);
}