Drag and Drop Enhancement - Auto expand while hovering


I used the code from CodeGuru to implement the Drag and Drop processing in my tree control. I wanted to modify this slightly so that a node would automaticall expand when I dragged a node over a drop target and hovered over it. This is similar to what occurs in Windows Explorer.

The following code snippet could be used in conjunction with the Drag and Drop code offered previously in CodeGuru.

The first step is to add two new variables to your class definition, a Hover Timer Id, and a Hover Point. The Timer Id identifies the timer that is started when you are dragging a tree node and you hover over a drop node for a certain period of time. The Hover Point stores the current point of the hover. This value needs to be stored as it is not available in the OnTimer event handler.

Two events must be defined, if not defined already. They are OnTimer and OnMouseMove. I used the Class Wizard to create them. The following code chunk is from the header file for the tree control. The only items that I included are those that need to be added.


class CMyTree : public CTreeCtrl
{
		.
		. // Definition
		.
private:
	UINT			m_nHoverTimerID;
	POINT			m_HoverPoint;
		.
		.	// Other definition
		.
protected:
	// Generated message map function
	//{{AFX_MSG(CMyTree
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	//}}AFX_MS
	DECLARE_MESSAGE_MAP()
}


In the .cpp file, code needs to be added to two functions: OnMouseMove and OnTimer. In OnMouseMove, the hover timer is constantly checked for existence, and if it exists, it is deleted. You only want the OnTimer event called when the mouse pointer is still for a certain period of time. The SetTimer will create a timer, and after the expiration of the selected time period, will send a message triggering the OnTimer event. In the OnTimer event handler, it is a simple matter to kill the timer, get the item currently being hovered over, and issuing an expand node command.

BEGIN_MESSAGE_MAP(CMyTree, CTreeCtrl)
	//{{AFX_MSG_MAP(CMyTree
	ON_WM_TIMER()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MA
	END_MESSAGE_MAP()

void CMyTree::OnMouseMove(UINT nFlags, CPoint point) 
{
	HTREEITEM		hitem;
	UINT			flags;

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

	if (m_bDragging)
	{
		ASSERT(m_pImageList != NULL);
		m_pImageList->DragMove(point);

		m_nHoverTimerID = SetTimer(2, 750, NULL);
		m_HoverPoint = point;

		if ((hitem = HitTest(point, &flags)) != NULL)
		{
			m_pImageList->DragLeave(this);
			SelectDropTarget(hitem);
			m_hitemDrop = hitem;
			m_pImageList->DragEnter(this, point);
		}

		m_pImageList->DragShowNolock(TRUE);
	}
	
	CTreeCtrl::OnMouseMove(nFlags, point);
}

void CMyTree::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 )
		{
			SelectItem( trItem );
			Expand(trItem,TVE_EXPAND);	
		}
	}
	else
	{
		CTreeCtrl::OnTimer(nIDEvent);
	}
}



Comments

  • Fixing bug: cluttering after expanding

    Posted by Legacy on 05/10/2003 12:00am

    Originally posted by: Pika


    At first, thank you Pete for your code! Very useful!

    I've noticed that after tree item is expanded (under the mouse pointer) the tree control moves the piece of screen down (to free space to show child items). And my dragged image is moved there also!! :( and it stays there until the tree is updated somehow.
    So, my solution was to refresh tree control on expanding. Here it is:


    void CMyTree::OnTimer(UINT nIDEvent)
    {
    ...
    trItem = HitTest(m_HoverPoint, &uFlag);

    if ( trItem )
    {
    //ADDED!!!:
    // hide the dragged image
    CImageList::DragShowNolock(FALSE);

    SelectItem( trItem );
    Expand(trItem,TVE_EXPAND);

    //ADDED!!:
    // update the tree control
    InvalidateRect(NULL);
    UpdateWindow();
    // show dragged image back
    CImageList::DragShowNolock(TRUE);

    }
    ...
    }

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 18, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT While the idea of using facial and or gesture recognitions to create a modern, intuitive game seems attractive, some developers may want to leverage Unity 3D as a way to accelerate their development. There are many different ways in which Intel and Unity Technologies have been working together to helps speed the develop of games with the Intel® RealSense™ SDK (Software Developer Kit), so come hear from a panel of experts on what we've done …

  • Live Event Date: April 30, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT It's likely today that you'll need to recover a single database far more than you'll need to recover all of SQL Server – and yet, your backup and recovery strategy focuses on recovering the enterprise, and not daily recovery needs of that enterprise. Join Rick Vanover from Veeam, as we discuss the hype and reality of recovering your SQL databases at a granular level, tools vs. backups, where virtualization fits in, and how to successfully …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date