CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Jun 2003
    Posts
    91

    How to populate CTreeCtrl from list of paths?

    Hi,

    I have been going crazy trying to come up with a recursive function for populating a CTreeCtrl from a list of paths in the database like shown below:

    c:\documents and settings\owner\file.htm
    c:\test\test2\file2.htm
    c:\test\tset3\file3.htm
    c:\documents and settings\owner\testagain\testagain.htm

    I am sure someone else has already done this before, so I am hoping someone can post some code. I would be grateful for any help I could receive. Thanks in advance

    Here is what I have so far, but it is not working if I try to add more than 3 levels deep and I don't even know if I am on the right track.:

    Code:
    //add a root item
    TV_INSERTSTRUCT TreeCtrlItem; 
       TreeCtrlItem.hParent       = TVI_ROOT; 
       TreeCtrlItem.hInsertAfter  = TVI_LAST; 
       TreeCtrlItem.item.mask     = TVIF_TEXT | TVIF_PARAM; 
       TreeCtrlItem.item.pszText  = _T("c:\\"); 
       TreeCtrlItem.item.lParam   = (long)"c:\\"; 
       HTREEITEM hTreeItem1       = m_Tree.InsertItem(&TreeCtrlItem); 
    
    AddPath("c:\\hello\\test\\"); //this works
    //AddPath("c:\\hello\test\\again\\"); //this crashes if uncommented
    
    ....
    
    void CTreeViewTestDlg::AddPath(CString cszPath)
    {
    	HTREEITEM hParent = NULL;
    	int nPos = 0;
    	CString cszCaption = "";
    	CString cszKey = cszPath;
    
    	if(cszPath.Mid(cszPath.GetLength()-1, 1) == "\\")
    	{
    		cszPath = cszPath.Mid(0, cszPath.GetLength()-1);
    	}
    	nPos = cszPath.ReverseFind('\\');
    	cszCaption = cszPath.Mid(nPos+1, cszPath.GetLength());
    	cszPath = cszPath.Mid(0, nPos+1);
    
    
    	//does the node already exist?
    	HTREEITEM bExists = DoesNodeExists(cszPath, m_Tree.GetRootItem());
    	if(bExists== NULL)
    	{
    		//add 
    		//AfxMessageBox("Exists");
    		AddPath(cszPath);
    	}
    
    
    	bExists = DoesNodeExists(cszPath, m_Tree.GetRootItem());
    	
    	  TV_INSERTSTRUCT TreeCtrlItem; 
    
    
    	  TVITEM test; 
    	memset(&test, 0, sizeof(TVITEM));
    	test.hItem = bExists;
    	
    	m_Tree.GetItem(&test);
    	
    	CString csztest;
    	csztest.Format("%s", test.lParam);
    
    
       TreeCtrlItem.hParent       = bExists; 
       TreeCtrlItem.hInsertAfter  = TVI_LAST; 
       TreeCtrlItem.item.mask     = TVIF_TEXT | TVIF_PARAM; 
    
       LPSTR caption = (LPSTR)(LPCTSTR)cszCaption; 
       TreeCtrlItem.item.pszText  = caption;
    
       LPSTR ps = (LPSTR)(LPCTSTR)cszKey; 
       TreeCtrlItem.item.lParam   = (long)ps; 
    
       HTREEITEM hTreeItem1       = m_Tree.InsertItem(&TreeCtrlItem); 
    	
    
    }
    
    HTREEITEM CTreeViewTestDlg::DoesNodeExists(CString cszPath, HTREEITEM hRootItem)
    {
    	HTREEITEM hTreeItem=NULL;
    
    	//check the root item
    
    	TVITEM TreeCtrlItem2; 
    	memset(&TreeCtrlItem2, 0, sizeof(TVITEM));
    	TreeCtrlItem2.hItem = hRootItem;
    	
    	m_Tree.GetItem(&TreeCtrlItem2);
    	
    	CString cszLParam;
    	cszLParam.Format("%s", TreeCtrlItem2.lParam);
    
    	if(cszLParam == cszPath)
    		return hRootItem;
    
    	//check rest of tree
    	HTREEITEM hItem = m_Tree.GetChildItem(hRootItem); 
        while (NULL != hItem) 
        { 
    			TVITEM TreeCtrlItem2;
    		memset(&TreeCtrlItem2, 0, sizeof(TVITEM));
    		TreeCtrlItem2.hItem = hItem;
    		
    		m_Tree.GetItem(&TreeCtrlItem2);
    		
    		CString cszLParam;
    		cszLParam.Format("%s", TreeCtrlItem2.lParam);
    		
    		if(cszLParam == cszPath)
    			return hItem;
    
            DoesNodeExists(cszPath, hItem); 
    
    
            // Move on to next sibling 
            hItem = m_Tree.GetNextSiblingItem(hItem); 
        } 
    
    
    
    	return hTreeItem;
    }

  2. #2
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: How to populate CTreeCtrl from list of paths?

    Quote Originally Posted by revg75
    I have been going crazy trying to come up with a recursive function for populating a CTreeCtrl from a list of paths in the database like shown below:

    I am sure someone else has already done this before, so I am hoping someone can post some code.
    Sure, many have done that. Take a look at this article, for example (there are other related articles in the same section).

  3. #3
    Join Date
    Jun 2003
    Posts
    91

    Re: How to populate CTreeCtrl from list of paths?

    Thanks for the reply, but there is one problem.

    The example you gave me is much easier to do such a thing because it is given one single path and then it just starts adding children (everything is in order).

    In my example my paths are not in any particular order. Like I said they could like shown below:

    c:\my folder\test\
    c:\my folder\test\the big test\
    c:\documents and settings\test\another folder\
    c:\my folder\nothing\test\

    So the problem is that these could be in any order . I can't just start by adding one root item and attach child items to it.

    know what I mean?
    Can anyone help?

    Thanks

  4. #4
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: How to populate CTreeCtrl from list of paths?

    Quote Originally Posted by revg75
    So the problem is that these could be in any order . I can't just start by adding one root item and attach child items to it.
    If the strings can come in any order (and you have no way of sorting them), then you need to parse each new path string, beginning from the left (you can easily do that by looking for the '\'). For every substring you get, you walk the current tree item level and search for the corresponding item (if it is not found, you add it). Then you take the next substring, and do the same with the child items of the current item - that's where the recursion comes in, it's really straightforward.

  5. #5
    Join Date
    Jan 2005
    Posts
    248

    Re: How to populate CTreeCtrl from list of paths?

    This may help:

    As you can see its easy to add a child.. You just insert an item and the last parameter is the parents HTREEITEM. So if you took my code and simply changed what top pointed to in the loop it you can easily control the heiarchy of the tree.

  6. #6
    Join Date
    Jan 2005
    Posts
    248

    Re: How to populate CTreeCtrl from list of paths?

    Code Below:

    Quote Originally Posted by messin18
    HTREEITEM top;
    if(PathVec.size() > 0){top = CarTreeptr->InsertItem("Cars");}
    else{top = CarTreeptr->InsertItem("No Cars In Selected Working Directory");}
    for(unsigned i = 0; i < uniqueCat.size(); i++)
    {

    HTREEITEM h1 = CarTreeptr->InsertItem(uniqueCat[i].c_str(),top);
    map<string,string>::iterator it;

    for(it = FullCatName.begin(); it != FullCatName.end(); ++it)
    {
    if(it->second == uniqueCat[i])
    {
    CarTreeptr->InsertItem(it->first.c_str(), h1)
    }
    }
    }
    uniqueCat.clear();

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured