Solved

CTreeView / CTreeCtrl

Posted on 2002-05-07
19
2,789 Views
Last Modified: 2013-11-20
I'm about to implement a tree, which is in a dockable "toolbar" type window in an MDI app.  The elements will be changed dynamically.  My working prototype uses a CTreeCtrl.

The catch is that I need to implement a dialog window, containing two trees, both the same as the floating tree view.  The idea is for the user to be able to select two tree elements to link together on this dialog.

Can I base two CTreeViews on the floating CTreeCtrl?  Is it an acceptable solution?  How do I connect the two views to the original CTreeCtrl?
0
Comment
Question by:IainHere
  • 6
  • 5
  • 4
  • +2
19 Comments
 
LVL 1

Expert Comment

by:Yechezkel
Comment Utility
I don't really see where CTreeView comes into the question. So far as I understand, CTreeView is only for the Document/View architecture and wouldn't be used in a dialog.

My suggestion would be to copy the entire tree structure from the floating CTreeCtrl to the two CTreeCtrls in the dialog by hand. Tedious, but I can't see any better way.
0
 
LVL 4

Author Comment

by:IainHere
Comment Utility
What I want is a way to get a new view on a CTreeCtrl.  If I can't use a dialog for that (which I'm a little suprised by - the document exists in the for of the CTreeCtrl, so why not just plop a view on a dialog?) then I'll just have to derive my "dialog" from CMDIChildWnd or whatever.

The question is - how do I do it?
0
 
LVL 16

Expert Comment

by:AlexNek
Comment Utility
2 IainHere
Could I please you a little expand your task. As I understood you have one CTreeView with document and you want to create the same tree twice on the dialog.
You can realize what you need if you:
- Create class CMyTreeData that hold your tree data.
- Create class CMyTreeFiller that create tree based on CTreeCtrl and CMyTreeData classes.
- CMyTreeData must be data member of your document.

When you need tree in the CTreeView get CTreeCtrl /*CTreeCtrl& CTreeView::GetTreeCtrl()*/ and fill it with CMyTreeFiller. When you create the dialog set pointer in dialog to your document and fills two trees with CMyTreeFiller.

Yet another idea: create splitter on the view and you show 2 or 3 CTreeView simultaneously.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
IainHere,
You can make a tree control without using CTreeView.  In the dialog box, just choose the tree control from the control palette (it's about halfway down the righthand side of the palette) and draw its rectangle in the dialog.  Then do the same for the second tree control.  Use the ClassWizard to add two CTreeControl objects e.g., m_cltTree_1 and m_cltTree_2 to your CDialog-derived class.

As to 'linking one tree control to another', you will be able to do that programmatically, based upon the current selection in each tree.  You will create OnSelChangedTree1 and OnSelChangedTree2 handlers using the ClassWizard.

If you explain a little more clearly what you mean by 'linking' the trees I'm sure we can provide more specific help.

-- Dan
0
 

Expert Comment

by:TheFriend
Comment Utility
No you can not.
CTreeView is a subclassed SysTreeView32 CCtrlView descendant.

I think the concept of your last question is wrong.

Your best solution would be to create another tree on the dialog and then send the same messages to the floating  window dispatcher.

0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
>>No you can not
Yes you can.
The only reason you might say that is because you have confused CTreeView (the CView-derived object, part of the MFC document/view architecture) with the Win32 Common Control "TreeView"  There are similarities in the name, but the differences are critical.

What I have proposed is to get the CView-derived crap out of the picture (Views require special handling -- you need to do lots of tricky stuff to put a View into a dialog), and just use CTreeCtrl directly.

-- Dan
0
 

Expert Comment

by:TheFriend
Comment Utility
Dan,
he is talking of objects, instances of classes at runtime. CTreeView is a subclassed control which takes over the control dispatcher. As far as I understand he has one CTreeCtrl object loaded with tree braches/items, and he wants to make 2 'view-ports' of the same CTreeCtrl. Well he might be able to display one CTreeCtrl through one CTreeView but, he loose the appearance of the CTreeCtrl, since the owner and the parent of the CTreeView will become the new parent/owner and the messages will be dispatch in the handler. When the second CTreeView gets into the play it will take over everything from CTreeView.

Agron
0
 
LVL 16

Expert Comment

by:AlexNek
Comment Utility
2 TheFriend
I can't see as Dan any problem for your notice. It can be a sync problem if data stored ONLY in CTreeView. But if data stored in separately class it must be not a big problem.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
If the only goal is to have two trees that show the same data (and IainHere is silent on this point), then the answer is simple:

When working with a tree control, you always end up writing a function named "PopulateTree" or something like that.  Well to copy one tree to another, just call your 'PopulateTree' function twice -- one for each of the CTreeCtrl objects.

-- Dan
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 4

Author Comment

by:IainHere
Comment Utility
>>and IainHere is silent on this point
sorry - been away.

Dan, you're right.  All I want is to see the same info on the two trees within the dialog as I have on the floating one.

I thought it would be possible to make a tree view which looks at the same info as the floating one.  It seems that this is unpossible - could you confirm this for me?

The main reason I wanted to do it like that is because each tree element is mapped to some information in the program.  I would like to reuse this mapping in the two new trees.  It sounds like my only option is to store lots of copies of this mapping [HTREEITEM->instance].

>>explain a little more clearly what you mean by 'linking' the trees
I guess this might have been a red herring - the tree items represent probabilistic inputs to a model.  The dialog containing two trees is to allow the user to correlate the inputs (eg say length of thread is related to heat of debate)
0
 
LVL 16

Expert Comment

by:AlexNek
Comment Utility
2 IainHere
>The main reason I wanted to do it like that is because each tree element is mapped to some information
in the program.
Is it mean that you already have a class with stored tree item data and hierarchy (not HTREEITEM, only data). If you already have this class try to add function FillTree(CTreeCtrl* pTree) if you don't want to use filler class.
I always divide my classes at least for two parts - data class, view class.

0
 
LVL 4

Author Comment

by:IainHere
Comment Utility
AlexNek, I'm still in the design stage, so no code yet (except for test code for the floating tree).  What you outline is roughly what I plan.

Could you verify that I'll need to recreate the mapping HTREEITEM->instance for each of the trees, please?  Then I'll close this out.

Thanks,
Iain.
0
 
LVL 16

Expert Comment

by:AlexNek
Comment Utility
2 IainHere
Do you want to reuse HTREEITEM handle, is that your question?
0
 
LVL 4

Author Comment

by:IainHere
Comment Utility
Yes, I suppose that is the most transparent way of doing it.  Is that possible?

I'm currently planning (based on this thread) to store all of my information calculation info in a std::vector, passing this vector into a ConstructTree function every time I create a new tree.  I will also need a std::map HTREEITEM->instance (ie reference to element of the std::vector) for each tree.  It seems messy.
0
 
LVL 16

Expert Comment

by:AlexNek
Comment Utility
2 IainHere
If you want to reuse HTREEITEM we need at least the function CTreeCtrl::InsertItem(HTREEITEM) as I think. So I don't know this way.
If you use vector where you store information about tree hierarchy? In object pointed via vector?
I don't know exactly you task but if I do it then I create a base data class for my tree Item, create inherited classes for different data tree item and build from this structure exactly data tree (not a vector). From this structure I can easy create the tree view. I can easy add and modify this data structure. I can pass pointer to this data structure to the tree item and use LPSTR_TEXTCALLBACK. So you can easy refresh all tree controls if text in one must be changed. For each tree control you can store mapping "data pointer"-"HTREEITEM" if you need it.
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 150 total points
Comment Utility
IainHere,
You will need only one copy of the data.  Your code that constructs and populates the tree will use that same data for each tree.  What part of this do you not understand.  I will be glad to explain.

It would also be possible to construct a second CTreeCtrl by walking the nodes of the first CTreeCtrl and using the data to build the hieraachy of the second.  It may even be possible to provide two CTreeCtrls that view the exact same TreeView common control (I don't think so because each tree must maintain state data, so if this were possible, then the selection would change on the second when the user clicked on the first).  

So there are (or might be) several alternaives.  The point is:
     Why Bother?  
You have a function that populates a CTreeCtrl from some data.  Just call that function twice.

-- Dan
0
 

Expert Comment

by:TheFriend
Comment Utility
2 IainHere,

if MFC were complete you could do something like this:

     CFile file( "myfile.ar", CFile::modeCreate | CFile::modeReadWrite);
     CArchive ar( &file, CArchive::store);
     m_tree1.Serialize( ar);
     ar.Close();
     ar.~CArchive();
     file.Close();
     file.~CFile();


     CFile file( "myfile.ar", CFile::modeRead);
     CArchive ar( &file, CArchive::load);
     m_tree2.Serialize( ar);
     ar.Close();
     file.Close();

-----

or maybe:

m_tree1 >> m_tree2;

You still can do things like this, just that you have to work under the hood first, and later turn the key.

If you are interested in something like this, just let me know. I would like to add this feature to the controls in my library, but I need one more (very strong) reason to start doing it.

But again, it is much easier to do the way Dan says. But, since the tree items are loaded dynamicaly, and probably they wont fit the same data structure, your MyGlobals::PopulateTree() would become very large.

Thus, I suggest again. The messages that tree1 receives, send them to the second one (tree2)

eg:

tree1::OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
  dockWindow->tree2->SendMessage( message, wParam, lParam);
}

When you add an item to tree1, the same item is automaically added to tree2 as well.

In this function (method) you can also filter messages you don't want to send to the other tree control.

eg:
if( message != TVN_BEGINDRAG &&
    message != TVN_BEGINRDRAG)
{ // this would mess up the drap&drop of the other control

  dockWindow->tree2->SendMessage( message, wParam, lParam);

}

If you have mouse-over highlighting on, then you must translate the mouse coordinates as if the mouse is passing over the other control as well. see WM_MOUSEMOVE

Don't make this feature to work both ways. Endless loop, right?



Agron
0
 
LVL 4

Author Comment

by:IainHere
Comment Utility
Thanks for all the help, people.

I'm going to review my options and I'll close this in a couple of days.
0
 
LVL 4

Author Comment

by:IainHere
Comment Utility
Thanks Dan.

>>You have a function that populates a CTreeCtrl from some data.  Just call that function twice.

OK.  That's what I'm doing.  I got a little confused around the Ctrl/View business, and thought I should be able to have three views of the same info.  As you say, "Why Bother".  Thanks again (+apologies for not closing sooner)
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Windows Drag & Drop Location 2 85
paragon account problem 9 96
abstract class with all non abstract mentods 6 71
Sed question 2 45
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now