[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Tree Control

Posted on 2003-12-04
16
Medium Priority
?
592 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

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

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

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

In this post we will learn different types of Android Layout and some basics of an Android App.
Ready to get certified? Check out some courses that help you prepare for third-party exams.
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.
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
Suggested Courses

650 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