CTreeCtrl

Sample Image

Introduction

Don’t you find you have written the same segment of code many times to parse a subtree because the action you wanted to launch on the items was different. In order to avoid such code, I’ve written CTreeViewIterator class. This class contains a method called ApplyFunction to launch a function on each item/node of a subtree.

Implementation

The class I’ve written is dedicated to Explorer like applications (those with a CTreeView class on the left side). In that section, we’re going to see how to use CTreeViewIterator in that general case. In the section Adaptation, we’ll see how to modify it to use it in other cases.
When you generate your application using the wizard, Visual C++ doesn’t give you the capability to choose the CTreeView class implementation. Therefore, you have to have a CLeftView in your application. In the LeftView.cpp file, add the following line in the include section.

#include "TreeViewIterator.h"

You’re now able to use the CTreeViewIterator class in that module.
You must define the function that will receive the item/node as parameter. This function will be external to your CLeftView class even if defined in the same module. If you don’t define it in this module, do not forget to create a definition to set it visible from this module. If for any reason, you do want to set it as a method of your CLeftView class, please read the Adaptation section. The signature of this function is predefined. It must be like this:

int ExternalFunction ( CLeftView *tvTreeView,  /* Handle on the tree view*/
                       HTREEITEM  tiItem )     /* Item in the tree */
  • This function must return an integer set to 1 if ok, 0 else.
  • The first parameter is to be a CLeftView*. It will receive a handle on the CLeftView to let you use.
  • The second parameter is to be a HTREEITEM. It will receive a handle on the currently parsed item/node.

For example, let’s consider this function:

//*******************************************************************
//
//   FUNCTION: ExternalDisplayItem
//
//   RETURNS:  int
//
//   COMMENTS: External function to display the subtree as a list
//
//******************************************************************* 
int ExternalDisplayItem (
    CLeftView  *tvTree,     /* Handle on the tree */
    HTREEITEM   tiItem )    /* Item in the tree */
{
    CTreeCtrl  &tTree= tvTree->GetTreeCtrl ();
    // store the name
    tvTree->sFullList += tTree.GetItemText(tiItem) + "\r\n";
    return ( 1);
}

The goal here, is to store the subtree as a list in a string. So, the only thing the external function has to do is getting the name and concatenating it to the full list. To do so, it will use an attribute created in the CLeftViewcalled sFullList (type CString). Since we got a handle on the CLeftView as first parameter, there’s no problem till the attribute is public (if not, we should have use public methods like get & set). Using this method, you may update the tree item/node or the CLeftView the way you want.
Now you have the function to apply to each item/node, you have to call it. To do so, you’ll have to implement first the iterator and then, to call the ApplyFunction method with the right parameters.
The ApplyFunction‘s signature is:

int CTreeViewIterator::ApplyFunction (
    CLeftView   *tvView,            /* Handler on the tree view */
    HTREEITEM    tiStart,           /* Item to start with */
    FuncPtrView  fptrFunction  )    /* Function to launch */
  • This function returns an integer set to 1 if ok, -1 if problem when parsing subtree, 0 if problem when calling the external function.
  • The first parameter is a handle on the CLeftView derived from CTreeView.
  • The second parameter is a handle on the item/node to consider as the root when parsing the subtree.
  • fptrFunction is a function pointer to the external function you previously created.

Using our precedent external function, we got this code:

//*******************************************************************
//
//  FUNCTION:   OnSelchanged
//
//  RETURNS:    void
//
//  COMMENTS:   Current selected item has changed
//
//
//*******************************************************************
void CLeftView::OnSelchanged (
    NMHDR   *pNMHDR,    /* handle on event values */
    LRESULT *pResult )  /* handle on event return value */
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *) pNMHDR;
    CTreeCtrl   &tTree = this->GetTreeCtrl ();
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    // create the iterator
    CTreeViewIterator   *ptrTree =   (CTreeViewIterator *) &tTree;
    // call the  function
    sFullList= "";
    ptrTree->ApplyFunction (this, pNMTreeView->itemNew.hItem,
                            &ExternalDisplayItem );
    GetDocument()->UpdateAllViews ( this, 1L, (CObject *) &sFullList  );
    *pResult = 0;
}

The method OnSelChanged is launched when the user has select a new item/node in the treeview. Here, we have catched it to add our function call. As you can see, we first add the iterator implementation with:

CTreeViewIterator  *ptrTree = (CTreeViewIterator *)  tTree;

In fact, we may consider the iterator on the CTreeCtrl as a shell with a special method. Therefore, within ApplyFunction method, we will see the content of the CTreeCtrl to parse.
We now have to get the parameters:

  • The first one, the handle on the CLeftView is easy to get, it’s this variable.
  • The second is the handle on the item/node. Since we are in the method that catch the new selection, we gonna extract the item address within the parameter pNMHDR using two lines:
    NM_TREEVIEW *pNMTreeView =   (NM_TREEVIEW *) pNMHDR; // to cast the event param
    pNMTreeView->itemNew.hItem // to refer to the new selected item
  • The last parameter is the handle on the external function we created.

That way, we obtain the following call:

ptrTree->ApplyFunction (this, pNMTreeView->itemNew.hItem, &ExternalDisplayItem );

Since this event may be caught many times, we initialize the variable sFullList before we parse the subtree.
When the ApplyFunction is finished, we update the other views with the generated string using the method UpdateAllViews.
Here we are, catching the UpdateAllViews event isn’t the subject here but you may have a look at the sample project to get an idea.

Adaptation

That section is to explain you how to upgrade the CTreeViewIterator to adapt it to your own case. I wrote it as a FAQ. I’ll update it with the cases you will propose. So, what’s your problem?
Question: My CTreeView class is not named CLeftView.
Answer: Change the CTreeView classname in :

  • The function pointer’s signature.
  • The ApplyFunction definition.
  • The ApplyFunction implementation.

Question: I want to set the called function a method of my class CLeftView.
Answer: You just have to change the function pointer’s signature to add your class. For example, try this:

  • Change the External function to a public method called DisplayItem in CLeftView class.
  • Change the signature to :
    typedef int ( CLeftView::*FuncPtrView ) ( CLeftView * tTree, HTREEITEM tiItem );
  • Change the call of ApplyFunction method to :
    ptrTree->ApplyFunction (this, pNMTreeView->itemNew.hItem, &CLeftView::DisplayItem );
  • In ApplyFunction implementation, change the function call to:
    ( tvView->*fptrFunction ) ( tvView, tiCurrItem )

간단한 사용예

void OnInitialUpdate()
{
	// the tree object
	CTreeCtrl   &tTree = this->GetTreeCtrl ();
	// variables to compute new items
	long		lItemTitle;
	CString		sItemTitle;
	char		cItemTitle[10];
	int			iItemSize;
	int			iCptr;
	// item created
	HTREEITEM	tiTestNode;
	HTREEITEM	tiParentNode;
	CTreeView::OnInitialUpdate();
	// update the tree style
    tTree.ModifyStyle ( 0, TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT);
	// Add items to the tree
	for(lItemTitle=1; lItemTitle<=999; lItemTitle+=2)
	{
		ltoa(lItemTitle,cItemTitle,10);
		sItemTitle = "";
		iItemSize= strlen(cItemTitle);
		sItemTitle=sItemTitle+cItemTitle[0];
		for(iCptr=1; iCptr
			

“CTreeCtrl”의 798개의 댓글

  1. I wants to be a master in this topic someday. I’ve been looking almost everywhere online for thisinfo. I saw your post on my Google feed. You kind of remind me of my aunt. You’re clearly very knowledgeable about this subject. I wants to be a mentor in this issue.

  2. I discovered this while on Blog. I really think this might help with the issue. A few of my coworkers have been recommending this site to me for a while now so I finally decided to visit. After I read this I screamed at the ceiling and my eyes exploed.

  3. This is an excellent, an eye-opener for sure! I firstdiscoveredyour websiteabout a month ago and Ithoughtit was veryinteresting so I’mgladyou’retalkingaboutthis. You are a very persuasive writer.

  4. Hello! This is kind of off topic but I need some help from an established blog.
    Is it hard to set up your own blog? I’m not very techincal but I can figure things out pretty fast.
    I’m thinking about making my own but I’m not sure where to
    start. Do you have any tips or suggestions? Appreciate it

  5. Hey there! I just wanted to ask if you ever have any issues with
    hackers? My last blog (wordpress) was hacked and I ended up losing
    a few months of hard work due to no back up. Do you have any solutions to prevent
    hackers?

  6. You’ve made my day! Thx again. From booksto websitecontentto social media posts, people need to write great content if they wantto attract people. I enjoyed your post. Thank you. Your article has proven useful to me.

  7. Thanks for a marvelous posting! I definitely enjoyed reading it, you will be a great author.
    I will remember to bookmark your blog and may come back someday.

    I want to encourage you to ultimately continue your great job, have a nice morning!

  8. I just want to mention I am just beginner to blogging and site-building and definitely enjoyed you’re blog. Likely I’m going to bookmark your blog . You really have very good posts. Thanks a bunch for sharing with us your web site.

  9. Not often do I encounter a weblog that is both educated and entertaining, and let me tell you, you may have hit the nail on the head. Your concept is excellent; the issue is something that not sufficient individuals are speaking intelligently about. I am very happy that I stumbled across this in my quest for something relating to this.

  10. After research a few of the blog posts on your site currently, and also I genuinely like your way of blogging. I bookmarked it to my book marking web site list as well as will certainly be inspecting back soon. Pls have a look at my web site as well as well as let me know what you assume.

  11. Thanks for the sensible critique. Me & my neighbor were just preparing to do a little research on this. We got a grab a book from our local library but I think I learned more from this post. I am very glad to see such great info being shared freely out there.

  12. After study a few of the post on your website currently, and also I absolutely like your means of blogging. I bookmarked it to my book marking internet site list and also will certainly be checking back quickly. Pls take a look at my website too as well as let me understand what you believe.

  13. Aw, this was a truly wonderful message. In concept I wish to put in composing like this additionally? taking time and also real initiative to make an excellent short article? however what can I say? I postpone alot and never appear to get something done.

  14. Nice post. I find out something more difficult on different blog sites daily. It will always be boosting to read content from various other writers and practice a something from their store. I?d prefer to utilize some with the content on my blog site whether you don?t mind. Natually I?ll give you a web link on your internet blog. Many thanks for sharing.

  15. Hello there! I simply wish to give a huge thumbs up for the excellent information you have below on this blog post. I will be returning to your blog site for even more soon.

  16. Aw, this was a truly good article. In suggestion I would love to put in creating like this in addition? taking time as well as real initiative to make a very good write-up? yet what can I state? I hesitate alot and also by no means appear to obtain something done.

  17. I discovered your blog website on google and inspect a few of your early blog posts. Continue to maintain the great operate. I simply added up your RSS feed to my MSN News Visitor. Seeking ahead to learning more from you later on!?

  18. I am usually to blogging and also i actually appreciate your content. The post has truly peaks my passion. I am mosting likely to bookmark your site and maintain looking for new information.

  19. Can I simply say what a relief to discover a person who in fact knows what theyre discussing on the net. You absolutely understand how to bring an issue to light and also make it essential. More people need to read this and also understand this side of the tale. I angle think youre not more prominent because you definitely have the gift.