Solved

Tree Control

Posted on 2003-12-04
16
544 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:VS_Learner
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
I have already tried this code (i.e using GetCursorPos to get the point ) , but unfortunately i am getting hItem as NULL always ..
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 11

Expert Comment

by:KurtVon
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility

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
Comment Utility
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
Comment Utility
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
Comment Utility
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 20 total points
Comment Utility
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

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

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.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

771 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

10 Experts available now in Live!

Get 1:1 Help Now