是否可以在快捷菜单处理程序中使用菜单模板资源?

问题描述 投票:0回答:2

抱歉,这是一个愚蠢的问题,但是我想知道在实现快捷菜单处理程序(IContextMenu)时是否可以使用菜单模板资源。

如果没有,添加大量菜单项是否仍然被接受?也许用LoadMenuIndirect

谢谢您的指导。

c++ winapi contextmenu
2个回答
0
投票

当然,使用LoadMenu API获取HMENU,然后使用InsertMenuItem在具有资源指定菜单的顶级弹出窗口上创建一个新项目。


0
投票

嗯,我想出了一个解决方案,但我愿意接受反馈以改进它。

要做的第一件事就是在Visual Studio中创建菜单模板资源,这是正常方法。但是在Resource.h标头中,更改自动生成的菜单项ID,以使它们从0开始并相应地递增。这些将是菜单偏移。

[接下来,我创建了一个帮助函数,该函数将从模板中加载菜单并(递归地)将项目ID偏移给定的数字(该数字在idCmdFirst中为IContextMenu:QueryContextMenu):

void OffsetMenuIds(HMENU hmenu, UINT idCmdFirst)
{
    MENUITEMINFO mii;
    mii.cbSize = sizeof(MENUITEMINFO);
    mii.fMask = MIIM_FTYPE | MIIM_SUBMENU | MIIM_ID;

    INT cItems = GetMenuItemCount(hmenu);

    for (UINT i = 0; i < cItems; ++i)
    {
        if (!GetMenuItemInfo(hmenu, i, TRUE, &mii))
        {
            continue;
        }

        if (mii.fType & MFT_SEPARATOR)
        {
            continue;
        }

        if (mii.hSubMenu)
        {
            OffsetMenuIds(mii.hSubMenu, idCmdFirst);
            continue;
        }

        mii.wID += idCmdFirst;
        SetMenuItemInfo(hmenu, i, TRUE, &mii);
    }
}

所以现在,当调用QueryContextMenu时,我们从资源中加载菜单,调用OffsetMenuIds函数,然后将模板中的顶级菜单项复制到资源管理器的上下文菜单中:

STDMETHODIMP CFileRightClickHandler::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{   
    HMENU hmenuTemplate = LoadMenu( _AtlBaseModule.GetModuleInstance(),
                                    MAKEINTRESOURCE(IDR_MENU1)  );

    OffsetMenuIds(hmenuTemplate, idCmdFirst);

    INT cItems = GetMenuItemCount(hmenuTemplate);

    for (UINT i = 0; i < cItems; ++i)
    {
        MENUITEMINFO mii;
        mii.cbSize = sizeof(MENUITEMINFO);
        mii.fMask = MIIM_TYPE | MIIM_SUBMENU | MIIM_ID;
        mii.dwTypeData = NULL;

        CHeapPtr<WCHAR> pszCommand;

        if (!GetMenuItemInfo(hmenuTemplate, i, TRUE, &mii))
        {
            continue;
        }

        if (mii.fType == MFT_STRING)
        {
            pszCommand.Allocate(++mii.cch);
            mii.dwTypeData = pszCommand;

            if (!GetMenuItemInfo(hmenuTemplate, i, TRUE, &mii))
            {
                continue;
            }
        }

        if (!InsertMenuItem(hmenu, ++indexMenu, TRUE, &mii))
        {
            continue;
        }
    }

    DestroyMenu(hmenuTemplate);

    return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)ID_LAST);
}

这至少处理简单的菜单项。这可能需要扩展以处理更复杂的菜单项,例如带有位图的菜单项。无论如何,请告诉我您是否有任何建议的改进。

© www.soinside.com 2019 - 2024. All rights reserved.