MFC:使用ContextMenuManager来TrackPopupMenu会使CTreeView项不时保留TVGN_DROPHILITE状态

问题描述

我对CTreeView上下文菜单一个奇怪的问题。我只是在下面的代码调用pPopup->TrackPopupMenu()。没问题,但是不会自动更新状态文本和图标。因此,在Internet上搜索后,我发现MFC功能包中有一个ContextMenuManager(我现在使用的是BCGControlBar Pro,它是功能包所基于的)。

我尝试在下面的代码中使用ContextMenuManager(将#if 1更改为0),并且在它起作用时,我发现有时(多次)之后,选定的树项将不会显示突出显示,只是闪烁并返回到右键单击的项目,例如TVGN_DROPHIILITE仍处于打开状态。 (我确认TVGN_DROPHILITE是右键单击通过OnNMRClick()函数上的调试打印项选择树项的工具)。另外,如果我启用了treeCtrl.SelectDropTarget(NULL),它可以解决此问题,但是我不必这样做吗?

我真的很想使用ContextMenuManager,但是这个问题是个表演障碍。有人知道发生了什么吗?

void CMyTreeView::OnNMRClick(NMHDR *pNMHDR,LRESULT *pResult)
{
    CDebugPrint::DebugPrint(_T("NMRClick: In DropHighlightItem %p\n"),GetTreeCtrl().GetDropHilightItem());

    // Send WM_CONTEXTMENU to self
    SendMessage(WM_CONTEXTMENU,(WParaM)m_hWnd,GetMessagePos());

    CDebugPrint::DebugPrint(_T("NMRClick: Out DropHighlightItem %p\n"),GetTreeCtrl().GetDropHilightItem());

    *pResult = 0;
}


void CMyTreeView::OnContextMenu(CWnd* pWnd,CPoint ptMousePos)
{
    HTREEITEM htItem;
    CTreeCtrl &treeCtrl=GetTreeCtrl();

    //
    // ...
    //
  
    // the popup is stored in a resource
    cmenu menu;
    menu.LoadMenu(IDR_TREE_CONTEXT_MENU);
    cmenu* pPopup = menu.GetSubMenu(0);

   #if 1
    UINT id=pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RETURNCMD,ptMousePos.x,ptMousePos.y,this);
   #else
    CBCGPContextMenuManager *manager = theApp.GetContextMenuManager();
    UINT id;
    if (manager) {
      id=manager->TrackPopupMenu(pPopup->GetSafeHmenu(),this);
      // treeCtrl.SelectDropTarget(NULL);  // fixes issue
    }
    else id=0;
   #endif
   
   //
   // ...
   //
}

解决方法

TVGN_DROPHILITE是一个临时选择,仅在拖放操作期间有效。为什么你搞砸了?

如果有的话,您应该使用TVGN_CARET

但是,问题是右键单击没有选择被单击的项目。如果您喜欢这种行为(我喜欢),请自行选择。

奇怪的是,您// Send WM_CONTEXTMENU to self-WM_CONTEXTMENU应该由系统发送给您,以响应右键单击。