Click here to Skip to main content
15,888,610 members
Articles / Desktop Programming / MFC

A Tree List Control

Rate me:
Please Sign up or sign in to vote.
4.87/5 (83 votes)
19 Sep 2002 1.2M   23.7K   173   189
A Tree List Control

Introduction

This is a class derived from CWnd class. It's a tree control with a list.

Features

Below are some of the many features that CTreeListCtrl has:

  • Compatible with CTreeCtrl & CListCtrl
  • Header drag & drop
  • Drag & drop between CTreeListCtrl
  • Transparent drag window with Alpha blend
  • Double colors of list
  • Background image
  • Check box support
  • Lock box support
  • Embedded modified controls
  • No more in future

Snapshot 1

Image 1

Snapshot 2

Image 2

How to Use It

Add this string into stdafx.h:

C++
#include "..\\TurboDLL\\xTurboDll.h"

Define Your Controls

C++
class CMyTreeListCtrl : public CTreeListCtrl  
{
public:
  CMyTreeListCtrl();
  virtual ~CMyTreeListCtrl();

protected:
  //{{AFX_MSG(CMyTreeListCtrl)
  afx_msg void OnExpanding(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnExpanded(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnUpdating(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnUpdated(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnDragEnter(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnDragLeave(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnDragOver(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnDrop(NMHDR* pNMHDR, LRESULT* pResult);
  //}}AFX_MSG

  DECLARE_MESSAGE_MAP()
};

Use Your Controls

C++
class CTurboDragDlg : public CDialog
{
// Construction
public:
  CTurboDragDlg(CWnd* pParent = NULL);   // standard constructor
        ...
  CImageList  m_ImageList;
  CMyTreeListCtrl  m_tree1;
  CMyTreeListCtrl m_tree2;
        ...
};

CTurboDragDlg::OnInitDialog() 
{
  CDialog::OnInitDialog();
  
  // TODO: Add extra initialization here
  m_ImageList.Create( IDB_BITMAP_TREE, 16, 4, 0xFF00FF );

  CRect rect;
  GetClientRect(&rect);
  rect.DeflateRect( 5, 5, 5, 5 );

  CRect left;
  left = rect;
  left.right = ( rect.left + rect.right ) / 2;

  CRect right;
  right = rect;
  right.left = ( rect.left + rect.right ) / 2;

  m_tree1.Create( 0x50810000, left, this, 0 );
  m_tree2.Create( 0x50810000, right, this, 1 );

        // Add other initialize code here
        ...
        
        return TRUE;  // return TRUE unless you set the focus to a control
  // EXCEPTION: OCX Property Pages should return FALSE
}

Then use it freely.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Chief Technology Officer
China China
He is a Visual C++ developer, MCSE
He has been programming in C/C++ for 7 years, Visual C++ with MFC for 5 years and RDBMS: Oracle, MS SQL for 5 years

Comments and Discussions

 
GeneralRe: Done it, done that... Pin
Hans Dietrich3-Nov-10 4:24
mentorHans Dietrich3-Nov-10 4:24 
GeneralPosted on my Github Pin
Kochise19-Dec-16 8:34
Kochise19-Dec-16 8:34 
GeneralRe: Done it, done that... Pin
skyformat99@gmail.com12-Aug-12 20:01
skyformat99@gmail.com12-Aug-12 20:01 
GeneralBug in void CTreeListCtrl::ExchangeItem( CTreeListItem* pItemA, CTreeListItem* pItemB ) Pin
TomFromCZE12-Nov-05 15:00
TomFromCZE12-Nov-05 15:00 
GeneralRe: Bug in void CTreeListCtrl::ExchangeItem( CTreeListItem* pItemA, CTreeListItem* pItemB ) Pin
rrrado6-Nov-07 3:22
rrrado6-Nov-07 3:22 
GeneralTrying to use it in a non-dialog-based application. Pin
alexR7522-Oct-05 10:59
alexR7522-Oct-05 10:59 
GeneralRe: Trying to use it in a non-dialog-based application. Pin
ochoteau8-Dec-05 2:41
ochoteau8-Dec-05 2:41 
GeneralAdded move enhancements Pin
Peter Shafton31-Aug-05 8:29
Peter Shafton31-Aug-05 8:29 
I couldn't find a way to move a segment of the tree to another segment of the tree, so I extended things a bit to add this support.

First I had to extend the CTreeListCtrl::MoveAfterItem function to allow you to specify a CTreeListItem that is on a different parent tree. I added the following new function...

void CTreeListCtrl::SetLevel( CTreeListItem* pItem, int nLevel )
{
// First set this items level along with all of it's siblings
CTreeListItem* pNext = pItem;
while ( pNext )
{
pNext->m_nLevel = nLevel;
if ( pNext->m_pChild )
SetLevel( pNext->m_pChild, nLevel+1 );
pNext = pNext->m_pNext;
}
}

Then I modified the CTreeListCtrl::MoveAfterItem function to look like this...

void CTreeListCtrl::MoveAfterItem( CTreeListItem* pItem, CTreeListItem* pAfter )
{
// move pItemA after pAfter ( If pAfter == NULL then move as the first child )
ASSERT( pItem != NULL );

CTreeListItem* pParent;
CTreeListItem* pFirst;
CTreeListItem* pPrev;
CTreeListItem* pNext;

pParent = pItem->m_pParent;
pFirst = pParent->m_pChild;
pPrev = pItem->m_pPrev;
pNext = pItem->m_pNext;

if( pAfter == NULL )
{
if( pParent->m_pChild == pItem )
return;
}
else
{
if( pItem == pAfter )
return;
}

if( pParent->m_pChild == pItem )
pParent->m_pChild = pItem->m_pNext;

if( pPrev != NULL )
pPrev->m_pNext = pItem->m_pNext;

if( pNext != NULL )
pNext->m_pPrev = pItem->m_pPrev;

if( pAfter == NULL )
{
pParent->m_pChild = pItem;

pItem->m_pPrev = pFirst->m_pPrev;

pItem->m_pNext = pFirst;
pFirst->m_pPrev = pItem;
}
else
{
pPrev = pAfter;
pNext = pAfter->m_pNext;

pItem->m_pPrev = pPrev;
pPrev->m_pNext = pItem;

pItem->m_pNext = pNext;
if( pNext != NULL )
pNext->m_pPrev = pItem;

// Handle the case where we are moving to a different parent
if ( pParent != pAfter->m_pParent )
{
StatChildDel( pItem, pItem->m_nChild, pItem->m_nVisibleChild );
pItem->m_pParent = pAfter->m_pParent;
StatChildAdd( pItem, pItem->m_nChild, pItem->m_nVisibleChild );

pItem->m_nLevel = pAfter->m_nLevel;
if ( pItem->m_pChild )
SetLevel(pItem->m_pChild, pItem->m_nLevel+1);
}
}

Invalidate();

return;
}

and Finally I added a CTreeListCtrl::MoveBelowItem function to allow us to insert a segment of the tree directly below a parent as the first item....

void CTreeListCtrl::MoveBelowItem( CTreeListItem* pItem, CTreeListItem* pBelow )
{
// move pItemA below pBelow as the first child
ASSERT( pItem != NULL );
ASSERT( pBelow != NULL );

CTreeListItem* pParent;
CTreeListItem* pFirst;
CTreeListItem* pPrev;
CTreeListItem* pNext;

pParent = pItem->m_pParent;
pFirst = pParent->m_pChild;
pPrev = pItem->m_pPrev;
pNext = pItem->m_pNext;

// Can't move below ourselves
if( pItem == pBelow )
return;

// If we are already the first child of this parent
if ( pParent == pBelow )
return;

if( pParent->m_pChild == pItem )
pParent->m_pChild = pItem->m_pNext;

if( pPrev != NULL )
pPrev->m_pNext = pItem->m_pNext;

if( pNext != NULL )
pNext->m_pPrev = pItem->m_pPrev;

pPrev = NULL;
pNext = pBelow->m_pChild;

pItem->m_pPrev = pPrev;
pItem->m_pNext = pNext;
if( pNext != NULL )
pNext->m_pPrev = pItem;

// Handle the case where we are moving to a different parent
if ( pParent != pBelow )
{
StatChildDel( pItem, pItem->m_nChild, pItem->m_nVisibleChild );
pItem->m_pParent = pBelow;
StatChildAdd( pItem, pItem->m_nChild, pItem->m_nVisibleChild );

pItem->m_nLevel = pBelow->m_nLevel + 1;
if ( pItem->m_pChild )
SetLevel(pItem->m_pChild, pItem->m_nLevel+1);
pBelow->m_pChild = pItem;
}
else
{
pParent->m_pChild = pItem;
}


Invalidate();

return;
}
QuestionHow can I get this control as .NET assembly or ActiveX control? Pin
Member 192519730-Apr-05 2:20
Member 192519730-Apr-05 2:20 
AnswerRe: How can I get this control as .NET assembly or ActiveX control? Pin
Kochise13-Jul-05 1:58
Kochise13-Jul-05 1:58 
GeneralGreat Job Pin
mr. Vitaliy A. Genkin6-Apr-05 18:05
mr. Vitaliy A. Genkin6-Apr-05 18:05 
Generalwhy can't get POS:( Pin
No-Cloud-Dagon1-Apr-05 14:36
No-Cloud-Dagon1-Apr-05 14:36 
GeneralUsing my own dialog to edit cells Pin
net_id26-Mar-05 16:35
net_id26-Mar-05 16:35 
GeneralUnable to Respond to a OnSelchanged message Pin
Rolando Cruz31-Jan-05 2:26
Rolando Cruz31-Jan-05 2:26 
GeneralRe: Unable to Respond to a OnSelchanged message Pin
yokosuna1-Dec-05 2:44
yokosuna1-Dec-05 2:44 
GeneralUnable to add TreeListCtrl in PropetyPage Pin
15-Dec-04 2:15
suss15-Dec-04 2:15 
Generaldelete tree Pin
jerry li9-Dec-04 22:47
jerry li9-Dec-04 22:47 
Generalcontrol gets locked Pin
Member 15409728-Oct-04 0:08
Member 15409728-Oct-04 0:08 
GeneralRe: control gets locked Pin
marccaron18-Nov-04 3:50
marccaron18-Nov-04 3:50 
GeneralRe: control gets locked Pin
rpar21-Oct-05 3:48
rpar21-Oct-05 3:48 
GeneralBug when using in release version Pin
pir21-Oct-04 1:57
pir21-Oct-04 1:57 
QuestionHow tu do use it in MFC dll? Pin
TangQin12-Oct-04 5:08
TangQin12-Oct-04 5:08 
AnswerRe: How tu do use it in MFC dll? Pin
marccaron20-Sep-05 11:23
marccaron20-Sep-05 11:23 
GeneralWhy must use MFC in Shared DLL Pin
liuliu7-Sep-04 17:57
liuliu7-Sep-04 17:57 
QuestionHow to add button control in one of the columns Pin
cool_jay26-Aug-04 0:00
cool_jay26-Aug-04 0:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.