简体   繁体   English

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

[英]How do I create a right-click menu in a list control?

( IDE : Visual C++ 6.0 ) (IDE:Visual C ++ 6.0)

I want to use the list control to create a program like Windows Task Manager. 我想使用列表控件来创建Windows Task Manager之类的程序。

It adds information (item) of the process received through api and displays it through list control. 它添加通过api接收的进程的信息(项目),并通过列表控件显示它。

What I want to do is to right-click on a specific item and a dialog box will appear like a real task manager. 我要做的是右键单击特定项目,然后将出现一个对话框,就像一个真正的任务管理器。

As a result of searching, it seems to use OnContextMenu(CWnd*, CPoint) function, but it does not understand how it works. 作为搜索的结果,似乎使用了OnContextMenu(CWnd *,CPoint)函数,但它不了解其工作原理。

I'd like you to provide a simple example. 我希望您提供一个简单的例子。

Thank you :) 谢谢 :)

This is a working sample extracted from a project of mine. 这是从我的项目中提取的工作样本。 Please take note, that this code is working on VS'15 and likely also on VS'10. 请注意,该代码在VS'15上也可能在VS'10上工作。 I do not have the 1998 version... it's been 20 years already. 我还没有1998年版……已经20年了。

I left some comments in the code. 我在代码中留下了一些注释。 Please read up on these. 请仔细阅读这些。

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);
}

In order to display the menu, you have to create one first. 为了显示菜单,您必须先创建一个。

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM