Attach item data to a menu item

This is a work in progress for creating a context menu:

CMenu   mnuContext;
CMenu   *pMnuPopup, *pMnuSwap;

mnuContext.LoadMenu(IDR_MENU_MWB_SWAP);
pMnuPopup = mnuContext.GetSubMenu(0);
if (pMnuPopup != nullptr)
{
    pMnuSwap = pMnuPopup->GetSubMenu(0);
    if (pMnuSwap != nullptr)
    {
        CMenu *pMnuChairman = pMnuSwap->GetSubMenu(0);
        if (pMnuChairman != nullptr)
            pMnuChairman->DeleteMenu(0, MF_BYPOSITION);
        //#TODO Init other pop up menus

        int iChairman = -1; // Reset counters
        for (int i = 0; i < m_cbDates.GetCount(); i++)
        {
            CString strDate, strMenuText;
            m_cbDates.GetLBText(i, strDate);

            CChristianLifeMinistryEntry *pEntry = static_cast<CChristianLifeMinistryEntry*>(m_cbDates.GetItemDataPtr(i));
            if (pEntry->GetChairman() != _T("") && pMnuChairman != nullptr && i != m_iDateIndex)
            {
                iChairman++;
                strMenuText = pEntry->GetChairman() + _T(" (") + strDate + _T(")");
                pMnuChairman->InsertMenu(iChairman, MF_BYPOSITION, ID_SWAP_CHAIRMAN_ITEM + iChairman, strMenuText);
                //# TODO Can I assign the pointer of pEntry? Or the "i" variable?
            }
        }

        pMnuPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,
            pMsg->pt.x, pMsg->pt.y, this, nullptr);
    }
}

As you can see, I am creating a menu item like this:

pMnuChairman->InsertMenu(iChairman, MF_BYPOSITION, ID_SWAP_CHAIRMAN_ITEM + iChairman, strMenuText);

Is it possible for me to associate with this menu item the i variable? Either that, or the the actual pointer (pEntry)?

Answer

It is unclear why you need to associate the menu item with the variable i. I think what you need instead is to handle the messages when the dynamic menu item is clicked. For a static menu item you would use ON_COMMAND and ON_UPDATE_COMMAND_UI macros in your message map.

What you can do in your case is to use the ON_COMMAND_RANGE in your message map to have a single handler for the range of menu items:

BEGIN_MESSAGE_MAP(CYourView, CFormView)
  ON_COMMAND_RANGE(ID_SWAP_CHAIRMAN_ITEM, ID_SWAP_CHAIRMAN_ITEM + 100, OnChairmanClick)
END_MESSAGE_MAP()

Your OnChairmanClick function will have this syntax:

void CYourView::OnChairmanClick(UINT nID)

You will need to remember the UID of the menu item you associated with a chairman, e.g. in your CChristianLifeMinistryEntry you can add an UID member for it. You can also create a CMap<UID, CChristianLifeMinistryEntry, UID, CChristianLifeMinistryEntry> where you would store the UIDs for a quicker access.

Leave a Reply

Your email address will not be published. Required fields are marked *