15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Раскрытие ветвей во время перетаскивания

Здесь приводится пример элемента управления, который раскрывает ветвь через две секунды после того, как над ним завис курсор с перетаскиваемым элементом.
Члены-перемнные, которые должны быть объявлены:


        CImageList*     m_pDragImage;
        HTREEITEM       m_htiDrag, m_htiDrop, m_htiOldDrop;
        bool            m_bLDragging;
        UINT            m_idTimer;
     

Код включенный в обработчик OnMouseMove():


if( m_idTimer && hti == m_htiOldDrop )
{
        KillTimer( m_idTimer );
        m_idTimer = 0;
}
                        
if( !m_idTimer )
        m_idTimer = SetTimer( 1000, 2000, NULL );

Теперь в ответе на сообщение таймера, мы подсвечиваем элемент и проверяем нет ли у него разветвлений. Если есть, разворачиваем их.


void CDragView::OnTimer(UINT nIDEvent) 
{
        if( nIDEvent == m_idTimer )
        {
                CTreeCtrl& theTree = GetTreeCtrl();
                HTREEITEM htiFloat = theTree.GetDropHilightItem();
                if( htiFloat && htiFloat == m_htiDrop )
                {
                        if( theTree.ItemHasChildren( htiFloat ) )
                                theTree.Expand( htiFloat, TVE_EXPAND );
                }
        }

        CTreeView::OnTimer(nIDEvent);
}

Приведенный ниже код поможет Вам более полно оценить метод:



void CDragView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	m_htiDrag = pNMTreeView->itemNew.hItem;
	m_htiDrop = NULL;

	m_pDragImage = GetTreeCtrl().CreateDragImage( m_htiDrag );
	if( !m_pDragImage )
		return;

	m_bLDragging = true;

	CPoint pt(0,0);
	
	IMAGEINFO ii;
	m_pDragImage->GetImageInfo( 0, &ii );
	pt.x = (ii.rcImage.right - ii.rcImage.left) / 2;
	pt.y = (ii.rcImage.bottom - ii.rcImage.top) / 2;

	m_pDragImage->BeginDrag( 0, pt );
	pt = pNMTreeView->ptDrag;
	ClientToScreen( &pt );
	m_pDragImage->DragEnter(NULL,pt);
	
	SetCapture();

	*pResult = 0;
}

void CDragView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CTreeView::OnLButtonUp(nFlags, point);

	if( m_bLDragging )
	{
		CTreeCtrl& theTree = GetTreeCtrl();

		m_bLDragging = false;

		CImageList::DragLeave(this);
		CImageList::EndDrag();

		ReleaseCapture();

		delete m_pDragImage;

		theTree.SelectDropTarget(NULL);
		m_htiOldDrop = NULL;

		if( m_htiDrag == m_htiDrop )
			return;

		HTREEITEM htiParent = m_htiDrop;
		while( (htiParent = theTree.GetParentItem(htiParent)) != NULL )
		{
			if( htiParent == m_htiDrag ) return;
		}

		theTree.Expand( m_htiDrop, TVE_EXPAND );

		HTREEITEM htiNew = CopyBranch( m_htiDrag, m_htiDrop, TVI_LAST );
		theTree.DeleteItem(m_htiDrag);
		theTree.SelectItem( htiNew );

		if( m_idTimer )
		{
			KillTimer( m_idTimer );
			m_idTimer = 0;
		}
	}
}

void CDragView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CTreeView::OnMouseMove(nFlags, point);

	HTREEITEM hti;
	UINT      flags;

	if( m_bLDragging )
	{
		CTreeCtrl& theTree = GetTreeCtrl();
		POINT pt = point;
		ClientToScreen( &pt );
		CImageList::DragMove(pt);
		
		hti = theTree.HitTest(point,&flags);
		if( hti != NULL )
		{
			CImageList::DragShowNolock(FALSE);

			if( m_htiOldDrop == NULL )
				m_htiOldDrop = theTree.GetDropHilightItem();

			theTree.SelectDropTarget(hti);
			
			m_htiDrop = hti;
			
			if( m_idTimer && hti == m_htiOldDrop )
			{
				KillTimer( m_idTimer );
				m_idTimer = 0;
			}
			
			if( !m_idTimer )
				m_idTimer = SetTimer( 1000, 2000, NULL );

			CImageList::DragShowNolock(TRUE);
		}
	}
}

HTREEITEM CDragView::CopyItem
	(
		HTREEITEM hti,
		HTREEITEM htiNewParent,
		HTREEITEM htiAfter // = TVI_LAST
	)
{
	CTreeCtrl& theTree = GetTreeCtrl();

	TVINSERTSTRUCT insert;
	::ZeroMemory(&insert, sizeof(TVINSERTSTRUCT));

	HTREEITEM htiNew = NULL;
	CString text;

	insert.item.hItem = hti;
	insert.item.mask = TVIF_CHILDREN|TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
	theTree.GetItem(&(insert.item));
	text = theTree.GetItemText( hti );

	insert.item.cchTextMax = text.GetLength();
	insert.item.pszText = text.LockBuffer();

	insert.hParent = htiNewParent;
	insert.hInsertAfter = htiAfter;
	insert.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
	htiNew = theTree.InsertItem(&insert);
	text.UnlockBuffer();

	theTree.SetItemData( htiNew, theTree.GetItemData( hti ) );
	theTree.SetItemState( htiNew, theTree.GetItemState( hti,
                            TVIS_STATEIMAGEMASK ), TVIS_STATEIMAGEMASK );

	return htiNew;
}

HTREEITEM CDragView::CopyBranch
	(
		HTREEITEM hti,
		HTREEITEM htiNewParent,
		HTREEITEM htiAfter // = TVI_LAST
	)
{
	CTreeCtrl& theTree = GetTreeCtrl();

	HTREEITEM htiChild = NULL;

	HTREEITEM htiNew = CopyItem( hti, htiNewParent, htiAfter );
	htiChild = theTree.GetChildItem( hti );
	while( htiChild != NULL )
	{
		CopyBranch( htiChild, htiNew );
		htiChild = theTree.GetNextSiblingItem( htiChild );
	}

	return htiNew;
}

void CDragView::OnDestroy() 
{
	CImageList* pImage = GetTreeCtrl().GetImageList( TVSIL_NORMAL );
	delete pImage;

	if( m_idTimer )
	{
		KillTimer( m_idTimer );
		m_idTimer = 0;
	}

	CTreeView::OnDestroy();
}

 

Источник: ProtoSphere