dcsimg

Class for drag-drop enabled TreeView

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


I wrote a base class from which the MFC users can derive their TreeView classes in a document-view based application instead of CTreeView. This class adds to CtreeView build-in drag-and-drop support.

All that the developer have to do is to add this class to the AppWizard generated project (with CTreeView as a View base class) and to replace the base of the view class from CTreeView to CTreeViewExt. After that, he/she has to overwrite the virtual functions of the base, which interface is self explantory.

That's all, the drag-and-drop tree view will be up and running !

Header file

#if !defined(AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_)
#define AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// TreeViewExt.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CTreeViewExt view

class CTreeViewExt : public CTreeView
{
protected:
	CTreeViewExt();           // protected constructor used by dynamic creation
	DECLARE_DYNCREATE(CTreeViewExt)

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CTreeViewExt)
	protected:
	virtual void OnDraw(CDC* pDC);      // overridden to draw this view
	//}}AFX_VIRTUAL

// Implementation
protected:
	HTREEITEM m_hDraggedItem;
	BOOL m_bDraggingNow;
	CImageList *m_pDragImageList;
	virtual ~CTreeViewExt();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

	// Generated message map functions
protected:
	virtual void CopyItemProperties(HTREEITEM hNewItem, HTREEITEM hDraggedItem);
	virtual BOOL IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget);
	virtual BOOL ItemCanBeDragged(HTREEITEM hItem);
	//{{AFX_MSG(CTreeViewExt)
	afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_)

Implementation file

// TreeViewExt.cpp : implementation file
//

#include "stdafx.h"
#include "TreeViewExt.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTreeViewExt

IMPLEMENT_DYNCREATE(CTreeViewExt, CTreeView)

CTreeViewExt::CTreeViewExt()
{
	m_bDraggingNow		= FALSE;
	m_hDraggedItem		= NULL;
	m_pDragImageList	= NULL;
}

CTreeViewExt::~CTreeViewExt()
{
}


BEGIN_MESSAGE_MAP(CTreeViewExt, CTreeView)
	//{{AFX_MSG_MAP(CTreeViewExt)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTreeViewExt drawing

void CTreeViewExt::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CTreeViewExt diagnostics

#ifdef _DEBUG
void CTreeViewExt::AssertValid() const
{
	CTreeView::AssertValid();
}

void CTreeViewExt::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTreeViewExt message handlers

void CTreeViewExt::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	if (!m_bDraggingNow)
	{
		if (ItemCanBeDragged(pNMTreeView->itemNew.hItem))
		{
			CTreeCtrl& tree = GetTreeCtrl();
			tree.SetCapture();
			m_bDraggingNow = TRUE;
			m_hDraggedItem = pNMTreeView->itemNew.hItem;
			tree.Select(m_hDraggedItem, TVGN_CARET);
			m_pDragImageList = tree.CreateDragImage(m_hDraggedItem);
			m_pDragImageList->DragEnter(&tree, pNMTreeView->ptDrag);
			m_pDragImageList->BeginDrag(0, CPoint(0, 0));
		}
	}
	
	*pResult = 0;
}

void CTreeViewExt::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (m_bDraggingNow)
	{
		CTreeCtrl& tree = GetTreeCtrl();
		m_pDragImageList->DragEnter(&tree, point);
		m_pDragImageList->DragMove(point);
	}
	
	CTreeView::OnMouseMove(nFlags, point);
}

void CTreeViewExt::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (m_bDraggingNow)
	{
		ReleaseCapture();

		m_bDraggingNow = FALSE;
		m_pDragImageList->EndDrag();
		delete m_pDragImageList;
		m_pDragImageList = NULL;

		CTreeCtrl& tree = GetTreeCtrl();
		UINT flags;
		HTREEITEM hTargetItem = tree.HitTest(point, &flags);
		if (hTargetItem != NULL && IsItemCanBeDroppedOn(m_hDraggedItem, hTargetItem))
		{
			HTREEITEM hNewItem = tree.InsertItem("Untitled", hTargetItem);
			CopyItemProperties(hNewItem, m_hDraggedItem);
			if (nFlags != MK_CONTROL)
				tree.DeleteItem(m_hDraggedItem);
		}	

		m_hDraggedItem = NULL;
	}
	
	CTreeView::OnLButtonUp(nFlags, point);
}

BOOL CTreeViewExt::ItemCanBeDragged(HTREEITEM hItem)
{
	return FALSE;
}

BOOL CTreeViewExt::IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget)
{
	return FALSE;
}

void CTreeViewExt::CopyItemProperties(HTREEITEM hNewItem, HTREEITEM hDraggedItem)
{

}



Comments

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

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