假设一个树控件(三层)是这样的根目录
  子项1
      a
      b
      c
      d
  子项2
      e
      f而且,我已经实现了右击abcdef才能弹出一个菜单,而右击“子项1”和“子项2”是不会弹出的。那么现在的问题是,如果我事先左击了“子项1”,然后去直接右击a,这样是不会弹出菜单的,一旦右键弹起,选中状态又恢复到了“子项1”,就好比选中的状态只是暂时转移到了a,也就是如果要直接右击a来弹出菜单,就必须先左击a。
同样,如果事先左击了a,那么再在“子项1”上右击,也能弹出菜单。我想知道怎么样才能通过右击也把焦点转过来而不要用左击?是不是要修改树的属性什么的?

解决方案 »

  1.   

    在RButtonDown中处理,用HitTest判断是否单击的地方是树节点,如果是的话判断是否是你要弹起菜单的节点,如果是的话,设置SelectItem(),然后弹出菜单,这样应该就OK了.
    楼主试试.
      

  2.   

    貌似不行哦。。下面是我在OnRclickTree中的代码 UINT   uFlags;
    CPoint point;
    ::GetCursorPos(&point);
    HTREEITEM t=m_tree.GetSelectedItem();//获得选中的项
    HTREEITEM   hItem = m_tree.HitTest(point,   &uFlags); 
    if   ((hItem   !=   NULL)   &&   (TVHT_ONITEM   &   uFlags)) 

          m_tree.Select(hItem,   TVGN_CARET); 
    } // CString s1=m_tree.GetItemText(hItem);
    // CString s2=m_tree.GetItemText(t);
    // CString s=s1+":"+s2;
    // MessageBox(s);//经测试,s1永远是空的,而s2则能正确获得选择项的文本
    if(!m_tree.ItemHasChildren(hItem))//如果没有子项则弹出菜单
    {
    CMenu m;
    m.LoadMenu(IDR_MENU3);
    m.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,point.x,point.y,this);
    }我这么写的话,不管怎么样,都没有菜单弹出
      

  3.   

    忘了说了,上面:
    HTREEITEM t=m_tree.GetSelectedItem();//获得选中的项
    这样获得的“选中项”也是根据鼠标左击来定的,而不是右击
    求解啊为什么我3楼的做法,不管怎么样,都没有菜单弹出
      

  4.   

    给树形控件添加事件处理程序,消息类型为NM_RCLICK,然后再控件中获取选中项(根,子目录均可),设置不同的右击menu,并添加相应的函数就行了,网上例子挺多的
      

  5.   

    其实,我觉得改成这样子,应该会可以实现想要的效果:
        处理右键的消息:
        UINT   uFlags;
        CPoint point;
        ::GetCursorPos(&point);
        HTREEITEM t=m_tree.GetSelectedItem();//获得选中的项 
        if   ((hItem   !=   NULL)   &&   (TVHT_ONITEM   &   uFlags)) 
        { 
          m_tree.Select(hItem,TVIS_SELECTED); 
        } 
        if(!m_tree.ItemHasChildren(hItem))//如果没有子项则弹出菜单
        {
            CMenu m;
            m.LoadMenu(IDR_MENU3);
            m.GetSubMenu(0)->TrackPopupMenu  (TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,point.x,point.y,this);
        }
      

  6.   

    NM_RCLICK
    void CXXXDlg::OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    // TODO: Add your control notification handler code here
    CPoint point;
    GetCursorPos(&point);
    CPoint pt(point);
    m_tree.ScreenToClient(&point);
    HTREEITEM hItem = m_tree.HitTest(point);
    if(hItem)
    {
    m_tree.SelectItem(hItem); if(!m_tree.ItemHasChildren(hItem))//如果没有子项则弹出菜单
    {
    CMenu m;
    m.LoadMenu(IDR_MENU3);
    m.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this);
    m.DestroyMenu();
    }
    }
    *pResult = 0;
    }
      

  7.   

    多谢7楼,你的方法可以,你又一次帮到我了。。嘿嘿
    不过我还想问下,你代码里面最后那句m.DestroyMenu();我没有加好像也没什么问题。那么加上是为了更严谨么?
      

  8.   

    The DestroyMenu function is used, before an application closes, to destroy the menu and free memory that the loaded menu occupied. 
    这就跟new和delete类似,不delete也不见得程序会崩溃