Link to home
Start Free TrialLog in
Avatar of skyhook8
skyhook8

asked on

Using CTreeCtrl From A Derived Class

I've created an Explorer like application using MFC wizard. I then created a generic class which is derived from CLeftView. I can then add this code -

CTreeCtrl &pTree = GetTreeCtrl();
pTree.ModifyStyle(0, TVS_HASBUTTONS | TVS_HASLINES, SWP_SHOWWINDOW);

to a function in the new class which will compile okay but when I run it and access the function I get "Debug Assertion Failed!".

Is it possible to control a tree from any other class than CLeftView and if so how?

Thanks in advance.
Avatar of Vinayak Kumbar
Vinayak Kumbar

Hi,

I assume u r doing it in Ur derived class. Then u r not checking for the validity of pointer, thats why it is crashing do as

CTreeCtrl &pTree = GetTreeCtrl();
if(pTree)
pTree.ModifyStyle(0, TVS_HASBUTTONS | TVS_HASLINES, SWP_SHOWWINDOW);

That will solve the crash.
VinExpert
Also,

Where are you modifying the style - are you doing this in the constructor? If so, the tree ctrl hasn’t been created at this point. You should be modifying this style in the function PreCreateWindow(…)

Something like

CleftViewDerivation::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= TVS_HASBUTTONS | TVS_HASLINES;
return CleftView::PreCreatewindow(cs);
}
Avatar of skyhook8

ASKER

You guys are responding faster than I can try your ideas!

I added the "if(pTree)" and it runs without crashing now but nothing shows up in the left pane.

void CTreeEx::PutTree()
{
CTreeCtrl &pTree = GetTreeCtrl();
if(pTree)pTree.ModifyStyle(0, TVS_HASBUTTONS | TVS_HASLINES, SWP_SHOWWINDOW);

TV_INSERTSTRUCT tvinsert;
tvinsert.hParent = NULL;
tvinsert.item.mask = TVIF_SELECTEDIMAGE | TVIF_TEXT;
tvinsert.item.pszText = "Org";
if(pTree)HTREEITEM hRoot = pTree.InsertItem(&tvinsert);
return;
}

This is being called from OnInitialUpdate() in CLeftView.
Can you show us the OnInitialUpdate() code. Is this a dialog or form?
HI,

Try modifying ur PutTree() code as
void CTreeviewView::PutTree()
{
      CTreeCtrl *pTree = &(this->GetTreeCtrl());
      if(pTree)
      {
            long wd = GetWindowLong(pTree->GetSafeHwnd(), GWL_STYLE);
            wd += TVS_HASBUTTONS + TVS_HASLINES;
            SetWindowLong(pTree->GetSafeHwnd(), GWL_STYLE, wd );            
      }

      TV_INSERTSTRUCT tvinsert;
      tvinsert.hParent = TVI_ROOT ;
      tvinsert.hInsertAfter = TVI_LAST;

      tvinsert.item.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_CHILDREN | TVIF_STATE | TVS_CHECKBOXES;
      tvinsert.item.hItem = NULL;
      tvinsert.item.state = 0;
      tvinsert.item.stateMask = 0x03;
      tvinsert.item.cchTextMax = 60;
      tvinsert.item.iSelectedImage = 0;
      tvinsert.item.cChildren = 1;
      tvinsert.item.lParam = 0;

      tvinsert.item.pszText = "NUMBERS";
      HTREEITEM Par1 ;
      if(pTree)
            Par1 = pTree->InsertItem(&tvinsert);

      tvinsert.hParent = Par1 ;
      tvinsert.item.cChildren = 0;
      tvinsert.item.pszText = "child";
      if(pTree)
            HTREEITEM child = pTree->InsertItem(&tvinsert);

      return;
}

Try it out.
VinExpert
sorry - ignore my bit about is this a dialog or form.

But I would still like to see where you are trying to modify the tree style. The reason why it's not asserting anymore is simply because that code is now no longer being called - which really doesn't help you much...
Tried the new code. Getting a "Debug Assertion Failed!" again. This line causes the problem:

if(pTree)
Par1 = pTree->InsertItem(&tvinsert);

Here's the OnInitialUpdate() code:

void CLeftView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
CTreeEx te;
te.PutTree();
}

Ideas?
skyhook, I think you might be a little confused about what you trying to achieve and how to go about it using OOP and MFC.

What exactly are you trying to do? Are you just trying to modify the style of the CLeftView class?


Adjusted points to 70
I'm attempting to add items to the tree in the left window pane using "void CTreeEx::PutTree()".

I can do it easily from "void CLeftView::OnInitialUpdate()" but when I call the previous function from the latter I get into trouble. CTreeEx is derived from CLeftView.

There's no doubt that I'm confused. But I've come a long way and I don't intend to stop here.{:>

The "rowlist" example from MSDN adds items to a list from a derived class but I can't figure out why it works.
Okay, well your trouble is OOP in general I think :-) For the time being I suggest you forget entirely about your derived CLeftTree (CTreeEx).

What you should do to get things working is first override PreCreateWindow() in CLeftTree like the following:

BOOL CLeftView::PreCreateWindow(CREATESTRUCT& cs)
{
    cs.Style |= TVS_HASBUTTONS | TVS_HASLINES;
      return CTreeView::PreCreateWindow(cs);
}

This will get the styles you want. Then in OnInitialUpdate(..) add the items to the tree.

As far as I can tell, you have no need to derive a class from CLeftTree and if you did, you go about it in a different way entirly.
I'm going to be calling ldap lookups from the derived class and I want to be able to add items to the tree while in a ldap_next_entry loop. I could do the loop from within CLeftView but I figured that a separate class for the ldap functions would be a more organized way of doing things.

Does that make sense?
I guess Scotty is right in saying that your problem is actually OOP in general.

Because...the very code you have written works on my machine.

The situation...SDI, two panes, left CMyTree(derived from CTreeView) and right CMyListView(from CListView).
CMyTreeView::::OnInitialUpdate()
{
      CTreeView::OnInitialUpdate();
      PutTree();
}

PutTree is your function. Works well.



Luck,
Waseem.
Hi,

From InitialUpdate just call PutTree();

OR
do one more thing(of which I am not so comfertable)
In InitialUpdate() set the timer as
SetTimer(1, 10, NULL);

Then map the WM_TIMER message and do
KillTimer(1);
PutTree();

Try it out.
VinExpert
What is it that you are actually trying to suggest VinExpert...I guess the guy already is in a soup....


Waseem.
Hi,

I am sorry skyhook8, if I am confusing U. But I thought to put it.

VinExpert
Okay, let's start over:

Using MFC AppWizard (exe), create an Explorer like application. Now create a new class and then from that class add tree items to the left pane.

Is it possible? Details please.

BTW: Thanks to all for your time and patience.
ASKER CERTIFIED SOLUTION
Avatar of ScottyDawg
ScottyDawg

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Eureka! Thanks so much!

For archival purposes, please note the change I had to make to OnInitialUpdate():

void CLeftView::OnInitialUpdate()
{
    CTreeView::OnInitialUpdate();
 
    CTreeCtrl& TreeCtrl = GetTreeCtrl();
    CTreeHelper CTreeHelper(&TreeCtrl);
     
    CTreeHelper.Populate();
}


Thanks again and everyone please forgive me for not making my question clearer from the beginning.


Ooops yes - sorry I knocked it up hastily.