代码之家  ›  专栏  ›  技术社区  ›  areum

如何在列表控件中创建右键单击菜单?

  •  1
  • areum  · 技术社区  · 7 年前

    (IDE:Visual C++6.0)

    我想使用列表控件创建一个类似Windows任务管理器的程序。

    它添加通过api接收的流程信息(项),并通过列表控件显示。

    我想做的是右键单击一个特定的项目,一个对话框就会像一个真正的任务管理器一样出现。

    作为搜索的结果,它似乎使用了OnContextMenu(CWnd*,CPoint)函数,但它不了解它是如何工作的。

    我希望你提供一个简单的例子。

    谢谢:)

    1 回复  |  直到 7 年前
        1
  •  5
  •   Blacktempel    7 年前

    这是从我的一个项目中提取的工作样本。 请注意,此代码适用于VS'15和 可能的 同样在VS'10上。我没有1998年的版本。。。已经20年了。

    我在代码中留下了一些注释。请仔细阅读这些。

    CMenu m_Menu; //Class member
    
    m_Menu.CreateMenu(); //Call this once only (I do it in PreSubclassWindow)
    
    //class CMenuListCtrl : public CListCtrl
    void CMenuListCtrl::OnContextMenu(CWnd *pWnd, CPoint ptMousePos)
    {
        //Some people might use a keyboard and not the mouse
        if (ptMousePos.x == -1 && ptMousePos.y == -1)
        {
            auto nSelectedItem = GetSelectionMark(); //Get the selected item in the CListCtrl
            if (nSelectedItem == -1)
                return;
    
            //Find the position
            CRect itemRect;
            GetItemRect(nSelectedItem, &itemRect, LVIR_BOUNDS);
            ClientToScreen(&itemRect);
            ptMousePos.x = itemRect.left + (itemRect.Width() / 10); //Some offset to display the menu user-friendly
            ptMousePos.y = itemRect.top + itemRect.Height() / 2;
        }
    
        CPoint hitPoint = ptMousePos;
        ScreenToClient(&hitPoint);
    
        //Fix header pop-up bug
        CHeaderCtrl *pHeader = GetHeaderCtrl();
        HDHITTESTINFO hitTestHeader = {0};
        hitTestHeader.pt = hitPoint;
    
        //The header doesn't need a context-menu, the item does
        if (pHeader->HitTest(&hitTestHeader) != -1)
            return;
    
        UINT uFlags = 0;
        HitTest(hitPoint, &uFlags);
        if (uFlags & LVHT_NOWHERE)
            return;
    
        //Get the previously created menu
        CMenu *pPopUp = nullptr;
        pPopUp = m_Menu.GetSubMenu(0);
    
        if (pPopUp)
            pPopUp->TrackPopupMenu(TPM_LEFTALIGN, ptMousePos.x, ptMousePos.y, this);
    }
    

    要显示菜单,必须先创建一个菜单。

    CMenu submenu;
    submenu.CreatePopupMenu();
    submenu.AppendMenuW(MF_STRING, IDC_COPY_POPUP,          L"&Copy");
    submenu.AppendMenuW(MF_SEPARATOR);
    submenu.AppendMenuW(MF_STRING, IDC_DELETE_POPUP,        L"&Delete");
    m_Menu.AppendMenuW(MF_POPUP, reinterpret_cast<UINT_PTR>(submenu.m_hMenu), L"");
    
    submenu.Detach();