VS2010生成的类视图中,树形控件的类是CViewTree,正常情况是可以获得节点的如:
void CViewTree::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: Add your control notification handler code here
DWORD dw = GetMessagePos(); // Mouse position 
CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw)); 
this->ScreenToClient(&p);  UINT htFlags = 0; 
HTREEITEM hHitItem= this->HitTest(p, &htFlags); // Find tree item which was clicked. 
//hHitItem为当前选中的节点
if(hHitItem   ==   NULL) 
return; 
if( NULL != hHitItem )
{...}
}
在这个树控件中添加了一个右键菜单,但是点击菜单时获取的树节点出错,总是第二次选择菜单功能时get的坐标以及节点,看了很多资料,看别的用CTreeCtrl m_ctltree来控制获得树节点就可以,我觉得可能是CViewTree的this和m_ctltree不一样的原因。但是不知道怎么解决!求大神帮忙~~~~

解决方案 »

  1.   

    有NMHDR *pNMHDR不用,为什么还要获取鼠标位置?
      

  2.   

    TVITEM结构里就有所点击item的handle
    开头加一句
    LPTVITEM pTreeItem=(LPTVITEM)pNMHDR;
    pTreeItem->hItem就是HTREEITEM
      

  3.   


    试了一下,pTreeItem->hItem是空的,貌似获取不到
      

  4.   

    写错
    NMTREEVIEW* pTreeNM=(NMTREEVIEW*)pNMHDR;
    里面
    TVITEM itemOld;
    TVITEM itemNew;可以得知句柄
      

  5.   


    试了一下,用itemNew.hItem和itemOld.hItem,都是空的,不好意思啊,有没有别的办法啊,主要问题是点击menu会又获取一次节点,所以总是出错
      

  6.   

    用GetCursorPos代替GetMessagePos试试
      

  7.   

    NMTREEVIEW::ptDrag应该也是一个坐标
      

  8.   


    我觉得还是得把代码都贴出来才能找到根~
    我的右键弹出menu函数:void CViewTree::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
    {
    // TODO: Add your control notification handler code here

    POINT pt;
    GetCursorPos(&pt);

    this->ScreenToClient(&pt); 

    UINT htFlags = TVHT_ONITEM; 
    HTREEITEM hHitItem= this->HitTest(pt, &htFlags); // Find tree item which was clicked. 
    //hHitItem为当前选中的节点
    if(hHitItem   ==   NULL) 
    return; 
    if( NULL != hHitItem)
    {
    CString temp = this->GetItemText(hHitItem);

    this->SelectItem(hHitItem);
    CMenu menu;
    menu.LoadMenu(IDR_POPUP_TREE);
    CMenu *pop = menu.GetSubMenu(0);
    POINT ptMouse;
    GetCursorPos(&ptMouse);
    pop->TrackPopupMenu                   (TPM_LEFTALIGN|TPM_LEFTBUTTON,ptMouse.x,ptMouse.y,this);
    }

    //::AfxMessageBox(GetItemText(hHitItem.hItem));
    *pResult = 0;
    }菜单响应函数:
    void CViewTree::OnNewClass(){
    /*1:
            POINT pt;
    GetCursorPos(&pt);
    //DWORD dw = GetCursorPos(pt); // Mouse position 
    //CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw)); 
    this->ScreenToClient(&pt);  UINT htFlags = 0; 
    HTREEITEM hHitItem= this->HitTest(pt, &htFlags); */
            // 2: 
    HTREEITEM hHitItem = this->GetSelectedItem();
    //hHitItem为当前选中的节点
    if(hHitItem   ==   NULL) {

    ::AfxMessageBox(_T("null"));
    }
    if( NULL != hHitItem)
    {
    CString strItem = this->GetItemText(hHitItem);
    ::AfxMessageBox(strItem);
    } //HTREEITEM hNew=this->InsertItem(_T("111"),1,0,this->GetSelectedItem());

    }
    消息响应函数中1,2两种方法获得selected树节点都不行,都是获取的第二次点击的位置~求助!!~~~
      

  9.   

    还是写上
    NMTREEVIEW* pTreeNM=(NMTREEVIEW*)pNMHDR;
    检查pTreeNM->ptDrag的点位是否有用OnNewClass看上去是一个ON_COMMAND回调?
    那么在按下子菜单选择的同时焦点还是在子菜单上,可能有影响,不知道SetFocus有用否?
      

  10.   

    是ON_COMMAND,您说的有道理,setforcus应该加在哪里呢?是弹出菜单后吗?明天去试试
      

  11.   

    在OnNewClass发生时,弹出的菜单已经早就获得焦点,焦点是否应该返回到tree上,也不太清楚是否是这个原因
      

  12.   


    去掉setforcus还是不行,我想换一种思路,让ClassView类获得CViewTree类的ON_COMMAND,可是总是没有反应,不知道这样写对不对:
    void CViewTree::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
    {
    // TODO: Add your control notification handler code here
    //NMTREEVIEW* pTreeNM=(NMTREEVIEW*)pNMHDR;
    //TVITEM  hHitItem = pTreeNM->itemNew;
    POINT pt;
    GetCursorPos(&pt);
    //DWORD dw = GetCursorPos(pt); // Mouse position 
    //CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw)); 
    this->ScreenToClient(&pt); 
    /*DWORD dw = GetMessagePos(); // Mouse position 
    CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw)); 
    this->ScreenToClient(&p); */ UINT htFlags = TVHT_ONITEM; 
    HTREEITEM hHitItem= this->HitTest(pt, &htFlags); // Find tree item which was clicked. 
    //hHitItem为当前选中的节点
    if(hHitItem   ==   NULL) 
    return; 
    if( NULL != hHitItem)
    {
    CString temp = this->GetItemText(hHitItem);
    if(temp != _T("生理部位")){
    this->SelectItem(hHitItem);
    //this->SetFocus();
    CMenu menu;
    menu.LoadMenu(IDR_POPUP_TREE);
    CMenu *pop = menu.GetSubMenu(0);
    POINT ptMouse;
    GetCursorPos(&ptMouse);
    CMainFrame *pMain=(CMainFrame *)AfxGetApp()->m_pMainWnd;
    CClassView *pView=(CClassView *)pMain->GetActiveView(); pop->TrackPopupMenu(TPM_LEFTALIGN,ptMouse.x,ptMouse.y,pView);
    }
    }
    *pResult = 0;
    }
    消息响应在ClassWizard加的,可是就是木有反应,不知道大神有什么招没~
      

  13.   

    现在CClassView 可以响应菜单ON_COMMAND了,可是还是获取树节点有问题,还是那个问题!快抓狂了!
    //CMainFrame *pMain=(CMainFrame *)AfxGetApp()->m_pMainWnd;
    //CClassView *pView=(CClassView *)pMain->GetActiveView();pop->TrackPopupMenu(TPM_LEFTALIGN,ptMouse.x,ptMouse.y,this->GetParent());
    这样弹出可以在CClassView响应,响应函数:
    void CClassView::OnNewclass()
    {
    // TODO: Add your command handler code here
    HTREEITEM hHitItem = m_wndClassView.GetSelectedItem();
    if(hHitItem   ==   NULL) {

    ::AfxMessageBox(_T("111"));
    }
    if( NULL != hHitItem)
    {
    CString strItem = m_wndClassView.GetItemText(hHitItem);
    ::AfxMessageBox(_T("111"));
    ::AfxMessageBox(strItem);
    }
    }
    还是获取的是再次点击的节点!郁闷啊!好像点击菜单的时候是再获取一次树控件的焦点,再去响应菜单函数的!怎么搞啊!!!纠结!!
      

  14.   

    我也遇到过这样的问题,楼主看看是不是CClassView类里有个OnContextMenu搞的鬼。把一切有关焦点和SelectItem等的注释了试试!!
      

  15.   


    是的是的!!好了!!太感谢了!!!
    这是VS2010自动生成的类视图的OnContextMenu函数:
    void CClassView::OnContextMenu(CWnd* pWnd, CPoint point)
    {
    CTreeCtrl* pWndTree = (CTreeCtrl*)&m_wndClassView;
    ASSERT_VALID(pWndTree); if (pWnd != pWndTree)
    {
    CDockablePane::OnContextMenu(pWnd, point);
    return;
    } if (point != CPoint(-1, -1))
    {
    // 选择已单击的项:
    CPoint ptTree = point;
    pWndTree->ScreenToClient(&ptTree); UINT flags = 0;
    HTREEITEM hTreeItem = pWndTree->HitTest(ptTree, &flags);
    if (hTreeItem != NULL)
    {
    //pWndTree->SelectItem(hTreeItem);   //注释掉
    }
    } //pWndTree->SetFocus();    //注释掉
    CMenu menu;
    menu.LoadMenu(IDR_POPUP_SORT); CMenu* pSumMenu = menu.GetSubMenu(0); if (AfxGetMainWnd()->IsKindOf(RUNTIME_CLASS(CMDIFrameWndEx)))
    {
    CMFCPopupMenu* pPopupMenu = new CMFCPopupMenu; if (!pPopupMenu->Create(this, point.x, point.y, (HMENU)pSumMenu->m_hMenu, FALSE, TRUE))
    return; ((CMDIFrameWndEx*)AfxGetMainWnd())->OnShowPopupMenu(pPopupMenu);
    UpdateDialogControls(this, FALSE);
    }
    }就好了!!!!
      

  16.   

    感谢mcmcmc给我SetFocus的提示!
    感谢amoxilin314给我OnContextMenu提示!!
    感激不尽!!
      

  17.   

    OnContextMenu第一次听到这货,VS2005飘过,