Click here to Skip to main content
15,894,362 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.8K   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

 
QuestionHow to add button control in one of the columns Pin
cool_jay26-Aug-04 0:00
cool_jay26-Aug-04 0:00 
GeneralImplementation for "ExpandAll" Pin
nocknock11-Aug-04 21:57
nocknock11-Aug-04 21:57 
GeneralRe: Implementation for "ExpandAll" Pin
Norrie Taylor22-Feb-05 7:58
Norrie Taylor22-Feb-05 7:58 
GeneralRe: Implementation for "ExpandAll" Pin
Steve Kowald29-Jun-05 8:57
Steve Kowald29-Jun-05 8:57 
QuestionHow can I change color of the specified treelist item Pin
nocknock11-Aug-04 20:48
nocknock11-Aug-04 20:48 
Questiontransparent tree control ? Pin
Seshagiri4-Aug-04 0:23
Seshagiri4-Aug-04 0:23 
GeneralDDL to LIB Pin
Member 9414921-Jun-04 20:44
Member 9414921-Jun-04 20:44 
GeneralRe: DDL to LIB Pin
Rilhas10-Jul-04 9:25
Rilhas10-Jul-04 9:25 
Hi,

I want to do the same as you, and there are, in fact, problems with the process. The main problem lies with resource access. This is a problem with any LIB, since LIB's can hold code and data, but not resources. This means that any "example.lib" library cannot hold a bitmap or a wave file inside it, under the form of a resource.

******************************************************
By the way TigerX: great module! Exactly right for me!
******************************************************

We can, however, incorporate any data element into a LIB as data. For example, I've written a small C program that takes a file name <file_name> and a C name <c_name> and reads the file <file_name> (as binary) and creates a C file with a variable <c_name> and another <c_name>_size similar to:

// This was generated from "file_name" on yyyy-mm-dd
char c_name[]={
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
0x02, 0x12, 0x00, 0xfa, 0xcc, 0xcc, 0xac,
0x00, 0x67, 0x11, 0x11, 0x11, 0x11, 0x10
};
const long c_name_size=sizeof(c_name);

If your LIB exports these data elements, then you can reconstruct the original data buffer, for example, storing it back to file at run-time, or using it directly from memory.

Although you could try this to load resources from a LIB file, Windows does not provide functions that let you load and store a resource from a binary memory buffer (as far as I know), like the memory buffer that a LIB can provide. The Windows functions all load resources from EXE's and DLL's. As for storing them to a memory buffer, this also is dificult to do (but necessary to get a binary representation of the resource inside the LIB in the first place).

But CBitmap, for example, is derived from a CObject. And a CObject is serializable! Well, not all CObject's: CBitmap is not serializable.

So, and until someone finds an simpler or prettier way to solve your (our) problem, I chose to tell you about the easy way, in 6 small steps, for which I assume you are familiar with VC6 and understand preprocessor, compiler, linker, export, executable, DLL, and LIB concepts (let me know if you don't):

1) Create a LIB project.

2) Create a LIB tester project (that uses the LIB and not the DLL).

3) Transfer the resources from the TurboDLL to the LIB tester project (the LIB project will not need them since it will be unable to export them, so the LIB tester project should be their holder).

4) Change the source files of the CTreeListCtrl so as to let them know where to get the resources from.

5) Build the LIB tester program.

6) Run the LIB tester to see if it runs ok.


Now with a little more detail.

___________________________________________________
1) Create a LIB project.

In the same workspace as TurboDLL add a new Static Library project, with MFC support. I didn't need pre-compiled header support. By using the same workspace it is very simple to copy file references and project settings.

The LIB project should have the same H and CPP fies as the TurboDLL project. You will also need to copy some predefined symbols from TurboDLL for the project to build ok. You find these in Project/Settings/C/C++/General/Preprocessor definitions.

___________________________________________________
2) Do the same as in 1), but select an MFC executable project instead of a static LIB project. Do not include the TurboDLL CPP source files, because this code will come from the LIB.

So, by building the project you will get a lot of unresolved externals. The simplest way to incorporate the LIB is to set a dependency, in Project/Dependencies. You should make the LIB tester project depend on the LIB project. VC6 is very smart, and will know where the LIB is (and distinguish between Debug and Release automatically!) and link with it.

If you are doing it ok, then you will get a successful compilation, although not clean (with some warnings which may be ignored at this stage). If you try to run it you should get an assertion failure, and so the program is not useful yet.

___________________________________________________
3) Transfer the resources from the TurboDLL to the LIB tester project.

Since both projects are in the same workspace, you may copy the BITMAP resources from the TurboDLL to the LIB tester (note that only references are copied, not the files).

I don't know exactly what resources are needed, since I have had contact with the CTreeListCtrl for only a couple of hours yet, just enough to get it running as a LIB without looking at the details. So copying the bitmaps is enough for the thing to run the same demo as TurboDemo, althoug some things behave diferently (like the cursor for resizing the header columns).

___________________________________________________
4) Change the source files of the CTreeListCtrl so as to let them know where to get the resources from.

To minimize the impacts, you should do a backward compatible change. The problem lies in the CTreeListResource constructor and destructor in "TurboDLL.cpp", which call AfxSetResourceHandle(TurboDLL.hResource) and thus change the resource origin from the MFC EXE (the LIB tester) to the LIB (but which the source code still thinks is a DLL, and thus is not valid at run-time).

The objective is to let the LIB use the LIB tester's resources, so these constructors and destructors should do nothing, since, by default, resources will be loaded from the EXE.

You can achieve this in a number of ways. The least intrusive is for you to create a "TurboDLL_lib.cpp" file, which implements an empty constructor and destructor for CTreeListCtrl (all of the remaining code may be deleted).

The LIB project should then include "TurboDLL_lib.cpp" instead of "TurboDLL.cpp". This means you didn't change any of TigerX's code.

TigerX should probably do it diferently. If he wants the same source code to be compatible with both DLL and LIB projects, then he would use the _LIB preprocessor definition in the LIB project, to make decisions in the code like:

#ifndef _LIB
// _LIB not defined, it is a DLL project
... code for the DLL ...
#else
// _LIB defined, it is a LIB project
... code for the LIB, probably testing the
availability of all the required resources...
#endif

___________________________________________________
5) Build the LIB tester program.

When you build the program you will probably get a number of warnings. I have not yet looked at them carefully, ignoring them seems to work. If you do a Rebuild All, the dependencies will cause the LIB to be rebuilt before the LIB tester, and the process will be:

5.1) The LIB is built, with code for the CTreeListCtrl and it's data, but not the resources.

5.2) The LIB tester EXE is built, with code for CTreeListCtrl comming from the LIB project, and with the remainder code for the application. This project will also provide the resources for your application, and the resources for CTreeListCtrl. These will all be linked into the EXE (of the LIB tester).

___________________________________________________
6) Run the LIB tester to see if it runs ok.

It should run ok. As I pointed out the mouse cursor fails to change correctly when you try to resize the columns. This should be easy, just copy the cursors also. I have not yet tried it, but it seems to be a reasonable solution.


To sumarize: this is the easy method, not the cleanest. For every new project you must take along the bitmap files, and recreate the bitmap references, ID's, as well as cursors and the rest. After the project is setup, it should be self-suficient, and the EXE it builds should not require any external DLL's. The way I did it was to enforce the existence of all resources, opening an explanatory dialog box when a resource is missing. This allows me to ensure that any EXE project has all it needs, and that nothing has been forgotten.

I hope this helps,
Rogério


Rogerio Rilhas
rogerio.rilhas@mail.pt

QuestionHow to get the first visible item of screen? Pin
freehawk11-May-04 22:49
freehawk11-May-04 22:49 
AnswerRe: How to get the first visible item of screen? Pin
vrumfundel16-May-04 10:29
vrumfundel16-May-04 10:29 
QuestionHow to set the font color of cell in the list? Pin
freehawk11-May-04 21:42
freehawk11-May-04 21:42 
AnswerRe: How to set the font color of cell in the list? Pin
itaifrenkel31-May-04 4:39
itaifrenkel31-May-04 4:39 
QuestionCan edit box or combo box be added into the cell of list? Pin
freehawk9-May-04 19:36
freehawk9-May-04 19:36 
AnswerRe: Can edit box or combo box be added into the cell of list? Pin
vrumfundel11-May-04 9:52
vrumfundel11-May-04 9:52 
GeneralRe: Can edit box or combo box be added into the cell of list? Pin
freehawk11-May-04 15:06
freehawk11-May-04 15:06 
GeneralRe: Can edit box or combo box be added into the cell of list? Pin
freehawk14-May-04 18:21
freehawk14-May-04 18:21 
GeneralRe: Can edit box or combo box be added into the cell of list? Pin
petes9-Nov-04 22:25
professionalpetes9-Nov-04 22:25 
Generali'm rookie in MFC Pin
browar5-May-04 6:12
browar5-May-04 6:12 
GeneralRe: i'm rookie in MFC Pin
browar6-May-04 9:33
browar6-May-04 9:33 
GeneralProblem: Debug-Version faster than Release-Version Pin
Anonymous17-Mar-04 21:37
Anonymous17-Mar-04 21:37 
GeneralRe: Problem: Debug-Version faster than Release-Version Pin
Anonymous18-Mar-04 1:52
Anonymous18-Mar-04 1:52 
GeneralRe: Problem: Debug-Version faster than Release-Version Pin
Anonymous18-Mar-04 1:57
Anonymous18-Mar-04 1:57 
GeneralRe: Problem: Debug-Version faster than Release-Version Pin
TigerX22-Mar-04 16:46
professionalTigerX22-Mar-04 16:46 
GeneralRe: Problem: Debug-Version faster than Release-Version Pin
songsongsong29-Oct-04 20:21
songsongsong29-Oct-04 20:21 
GeneralRe: Problem: Debug-Version faster than Release-Version Pin
Anonymous11-Jan-05 16:38
Anonymous11-Jan-05 16:38 

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.