Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Tree Control

Posted on 2003-12-04
16
Medium Priority
?
594 Views
Last Modified: 2013-11-20
I have written the following code as an handler when an item in a Tree Control is right clicked.

NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW);
    HTREEITEM hSelected = pNMTreeView->itemNew.hItem;

But i am getting hSelected as NULL always

What could be the error ???

Thanks in advance!!!
0
Comment
Question by:VS_Learner
  • 8
  • 8
16 Comments
 
LVL 11

Expert Comment

by:KurtVon
ID: 9874637
According to MS docs:

itemNew
TV_ITEM structure that contains information about the new item state. This member is zero for messages that do not use it.

Unfortunately, since right clicking does not actually select an item in the tree, the value here is 0.  On the bright side, that means you aren't doing anything wrong, Windows is just being annoying.  If you want to find out where the right-click occurred, you need to use the ptDrag to find the item under the cursor.  Unfortunately this means stepping through a loop with GetNextVisibleItem and GetItemRect sinc ethere is no GetItemFromPoint member of CTreeCtrl.

Hope this helps.
0
 

Author Comment

by:VS_Learner
ID: 9879226
Could anyone present a sample code as to how to find the item(in the tree control) on which the right click has occured??

Thanks
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9882549
Hmm, I have some such code at home, but that would take a while to get (that's why I recognized your problem, went through the same thing myself).  It went something like:

CRect rcItem;
HTREEITEM hItem = m_TreeCtrl.GetFirstVisibleItem();
while (hItem != NULL)
{
    m_TreeCtrl.GetItemRect(hItem, rcItem, FALSE);
    if (rcItem.PtInRect(pNMTreeView->ptDrag)
        break;
    else
        hItem = m_TreeCtrl.GetNextVisibleItem(hItem);
}

if (hItem != NULL)
{
    // The non-null hItem is the item that was clicked in.
}

This was done by hand, so watch out for typos.

Hope this helps.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:VS_Learner
ID: 9886953
Hi KurtVon ,
                Thanks for writing the code . But unfortunately i am getting the hItem as NULL always irrespective of where ever i click.
Like it is never going into the 'if loop' .so its never breaking and hItem is always becoming NULL.
And i think in the code while calling the function GetItemRect ..the second argument should be a pointer to the CRect structure.(coz..its an input parameter i guess.).But still the code isn't working.
I have also tried calling GetCursorPos and giving that point as an argument to PtInRect ..But even that isn't working.

So please help me out in finding out the error!!!!!!!

Thanks again.!!!
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9896778
Hmm, the code works perfectly for me.  What message are you trapping?  I used the TVN_BEGINRDRAG, but that meant I had to move the mouse a bit while the button was down.

And the CRect should not be a pointer.  GetItemRect takes a pointer to a RECT, but a CRect can be a pointer to a RECT through a typecast.  Using the & will work too, but only because a CRect is descended from RECT and has no virtual functions.  In general, typecast operators are safer than assumptions like that.
0
 

Author Comment

by:VS_Learner
ID: 9897192
I am trapping the NM_RCLICK ( right mouse click )..Like I want to display a menu (when right-clicked ) to only some items in the tree control.So i want to know whether an item is clicked or not , and if clicked which item?? Hope I am clear .!

Thanks
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9897239
NM_RCLICK only notifies when the mouse button is released.  But if that's okay, the problem is simple, the notification message does not send a NM_TREEVIEW object.  To get the mouse position you will need to use this code:

    CPoint ptDrag;
    GetCursorPos(&ptDrag);
    m_TreeCtrl.ScreenToClient(&ptDrag);

then just check the CRect position with ptDrag.

Hope this helps.
0
 

Author Comment

by:VS_Learner
ID: 9897304
I have already tried this code (i.e using GetCursorPos to get the point ) , but unfortunately i am getting hItem as NULL always ..
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9897525
I assume you did the ScreenToClient too (for the control).  Very odd since it works perfectly for me.

Does it do into the while loop, or does it skip over the loop on the first try?  If it skips, then GetFirstVisibleItem is returning NULL, which would mean that the tree control is reporting no visible items.  If it is going into teh loop, but not finding any item for the rectangle, it may be that GetItemRect has the third parameter set to TRUE somehow, and is only allowing teh selection of text.  Try clicking on the text itself.

Hope this helps.
0
 

Author Comment

by:VS_Learner
ID: 9903415
Irrespective of whereever i click , it is going through the while loop i ( i = GetVisibleCount) number of times. And that "i" value is perfectly right..(I checked it ) . It is only that in the "while" loop always "else" is getting executed. I have also checked everyother possible thing.The only thing is that , the point where i click is "never" in the rectangle of any visible item.

Thanks
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9904145
What are the coordinates of the click point?  It almost sounds like ScreenToClient isn't working properly.  Make sure you are calling it for the tree control object, not for the dialog.  Also check the coordinates of the rectangles.

Also make sure you really are using the point collected in GetCursorPos to compare against the rectangles.  If that still doesn't work, could you post the code up to the end of the while loop?  I'll compare it to what I have and see if I can find the problem.
0
 

Author Comment

by:VS_Learner
ID: 9904933

Here is the code upto end of while loop...

void CFolderPage::OnNMRclickTreeview(NMHDR *pNMHDR, LRESULT *pResult)
{

        CRect rcItem;

       HTREEITEM hItem = m_treectrl.GetFirstVisibleItem();
       while (hItem != NULL)
      {
      m_treectrl.GetItemRect(hItem, rcItem, FALSE);
      POINT point ;
      GetCursorPos(&point) ;
      m_treectrl.ScreenToClient(&point);
      if ( rcItem.PtInRect(point) )
            break;
      else
            hItem = m_treectrl.GetNextVisibleItem(hItem);
      }
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9905280
Odd, that looks like it should work.  You can make the code more efficient by taking the GetCursorPos out of the while loop (since you only care about where the curosr was when the loop was entered).  of course, it will not work while debugging since the mouse is moved, so test it without a breakpoint or make sure the breakpoint is after the cursor position is retrieved:

void CFolderPage::OnNMRclickTreeview(NMHDR *pNMHDR, LRESULT *pResult)
{
    CRect rcItem;
    POINT point ;

    GetCursorPos(&point) ;
    m_treectrl.ScreenToClient(&point);
    HTREEITEM hItem = m_treectrl.GetFirstVisibleItem(); // put breakpoint here or later
    while (hItem != NULL)
    {
        m_treectrl.GetItemRect(hItem, rcItem, FALSE);
        if ( rcItem.PtInRect(point) )
            break;
        else
            hItem = m_treectrl.GetNextVisibleItem(hItem);
    }

that way the cursor position will be where you clicked rather than where you moved the mouse after it was hit.  Then check the point against each rect and see if it makes any more sense why it wouldn't work.

Hope this helps.
0
 

Author Comment

by:VS_Learner
ID: 9905443
Hey ...Its working!!!...when i moved the 3 lines ( getting cursor pos) above the while loop.Its working fine..!!!
Thank You Very much for taking some time to test the code.
Actually now i got the actual error..!!! when i added debugging code ( like putting some messageboxes ) the cursor is moving to the "ok" button of the messagebox and the actual click point is missing everytime when it enters the while loop!!!

Thanks Once Again!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0
 

Author Comment

by:VS_Learner
ID: 9905529
I need to attach the same functionality for a list control box...So can i use the same type of code for that too..Or any changes are required???

Thank You
0
 
LVL 11

Accepted Solution

by:
KurtVon earned 80 total points
ID: 9905788
To do this with a list control is easier, since CListCtrl::HitTest will return the index of the item the point is in automatically, so no need for the while loop.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
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.
With just a little bit of  SQL and VBA, many doors open to cool things like synchronize a list box to display data relevant to other information on a form.  If you have never written code or looked at an SQL statement before, no problem! ...  give i…
Suggested Courses
Course of the Month21 days, 5 hours left to enroll

810 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