管理上下文菜单 
当用户右键单击工具选项板时,更改上下文菜单相对简单。 来自。但是,其方法定义只是返回以避免链接器错误。因此,必须重写接口的两个方法:和 。AcadToolImplIAcadToolContextMenuE_NOTIMPLIAcadToolContextMenu::Customize()IAcadToolContextMenu::InvokeMenuCommand() 
由于只能在运行时更改上下文菜单,因此必须动态定义菜单命令。该框架调用用户在“工具选项板”窗口中右键单击任何选项板时的实现。它向您传递菜单句柄、当前调色板的 ID、菜单命令 ID 的上限和下限以及上下文标志。您的实现应执行以下操作:IAcadToolContextMenu::Customize() 
- 验证当前工具选项板是否属于您的工具选项板。如果它不是你的,你可能想通过简单地返回来禁止菜单自定义。E_NOTIMPL
 
- 如果不想禁止显示更改,请使用菜单手柄添加新命令或删除标准项。
 
- 确保分配给任何添加项目的 ID 在给定范围内。
 
- 保存在非本地存储中使用的 ID 以供回调引用。
 
- 当所选工具选项板不属于您时,将缓存的 ID 重新初始化为零。
 
 
在每个右键单击事件上,框架都会调用股票工具 COM 对象上的函数。如果应用程序允许用户多次定义库存工具,则可能会无意中重新填充每个定义的上下文菜单。若要防止出现这种情况,请在创建新实例之前验证库存工具的 GUID 是否不在库存工具目录中。Customize() 
如果用户从菜单中选择一个命令,则将在实现 的每个工具对象上调用该方法。调用时,框架会向您传递所选菜单项的命令 ID、工具选项板 ID 和窗口句柄。如果命令 ID 与您的命令 ID 匹配,并且工具选项板 ID 和窗口句柄可接受,则执行相应的操作。InvokeMenuCommand()IAcadToolContextMenuInvokeMenuCommand() 
以下过程使用 MFC 菜单对象将三个菜单项追加到上下文菜单中。 
设置 IAcadToolContextMenu 实现
- 在 simpleTool.h 文件中,添加以下预处理器定义:
#define MAX_MENU_ENTRIES 3
 
 
- 在 simpleTool.cpp 文件中,添加以下静态数组,用于存储您使用的 ID:
static UINT m_nMenuIds[MAX_MENU_ENTRIES] = {0,0,0};
 
- 在类声明中,声明两个方法的原型:CSimpleToolIAcadToolContextMenu
// IAcadToolContextMenu members
STDMETHOD(Customize)(/* [in] */ int nContextFlag,
	/* [in] */ DWORD hMenu,
	/* [in] */ UINT idCmdFirst,
	/* [in] */ UINT idCmdLast,
	/* [in] */ GUID *pPaletteId,
	/* [retval][out] */ DWORD *pFlag);
STDMETHOD(InvokeMenuCommand)(/* [in] */ UINT idCmd,
	/* [in] */ GUID *pPaletteId,
	/* [in] */ DWORD hWnd,
	/* [retval][out] */ DWORD *pFlag);
 
 
- 在 SimpleTool.cpp 文件中,为 and 方法添加空白实现原型。Customize()InvokeMenuCommand()
现在,您可以实现上下文菜单功能了。 
 
 
实现 Customize() 方法 
- 在实现正文中,检查是否未尝试添加超过框架允许的菜单项:Customize()
int maxMenu = (idCmdLast - idCmdFirst) < MAX_MENU_ENTRIES ?     (idCmdLast - idCmdFirst) : MAX_MENU_ENTRIES;
 
 
- 使用参数获取当前工具选项板的名称。您可以使用该对象检索调色板。下面的代码演示了这一点。pPaletteId*AcTcManager
AcTcPalette* pPalette = 
    (AcTcPalette*)(AcTcGetManager()->FindItem(*pPaletteId));
ASSERT(pPalette != NULL);
TCHAR pszString[1024]; // arbitrary buffer size; not                       // limited by the framework
pPalette->GetName(pszString, 1024);
 
 
- 将调色板的名称与调色板的名称进行比较。如果发现它不匹配,请将菜单 ID 数组条目重新初始化为 0 并返回:
if (_tcscmp(pszString, "SimplePalette")!= 0)
{
    for (i=0; i < maxMenu ; i++)
    {
        m_nMenuIds[i] = 0;
    }
    return E_NOTIMPL;
}
 
- 使用步骤 1 中确定的最大菜单项限制,从给定范围内保存三个命令 ID:
int i;
for (i=0; i < maxMenu ; i++)
{
    m_nMenuIds[i] = idCmdFirst + i;
}
 
- 创建一个新对象:CMenu
CMenu* menu = new CMenu;
 
 
- 使用参数和函数将对象附加到上下文菜单:CMenuhMenuCMenu::Attach()
menu->Attach(HMENU(hMenu);
 
 
- 使用选定的命令 ID 添加三个菜单命令:
menu->InsertMenu(-1, MF_BYPOSITION, m_nMenuIds[0], "Menu&1");
menu->InsertMenu(-1, MF_BYPOSITION, m_nMenuIds[1], "Menu&2");
menu->InsertMenu(-1, MF_BYPOSITION, m_nMenuIds[2], "Menu&3");
 
 
- 分离对象并将其删除:CMenu
menu->Detach();
delete menu;
 
下面是完成的方法覆盖:Customize() 
STDMETHODIMP CSimpleTool::Customize(/* [in] */ int nContextFlag,
					/* [in] */ DWORD hMenu,
					/* [in] */ UINT idCmdFirst,
					/* [in] */ UINT idCmdLast,
					/* [in] */ GUID *pPaletteId,
					/* [retval][out] */ DWORD *pFlag)
{
AcTcPalette* pPalette = 
    (AcTcPalette*)(AcTcGetManager()->FindItem(*pPaletteId));
ASSERT(pPalette != NULL);
TCHAR pszString[128];
pPalette->GetName(pszString, 128);
int i=0;
int maxMenu = (idCmdLast - idCmdFirst) < MAX_MENU_ENTRIES ?
    (idCmdLast - idCmdFirst) : MAX_MENU_ENTRIES;
if (_tcscmp(pszString, "SimplePalette")!= 0)
{
    // Zero-out any existing IDs
    for (i=0; i < maxMenu ; i++)
    {
        m_nMenuIds[i] = 0;
    }
    return E_NOTIMPL;
}
for (i=0; i < maxMenu ; i++)
    m_nMenuIds[i] = idCmdFirst + i;
CMenu* menu = new CMenu;
if (menu->Attach(HMENU(hMenu))) 
{
    menu->InsertMenu(-1, MF_BYPOSITION, m_nMenuIds[0],         "Menu&1");
    menu->InsertMenu(-1, MF_BYPOSITION, m_nMenuIds[1],         "Menu&2");
    menu->InsertMenu(-1, MF_BYPOSITION, m_nMenuIds[2],         "Menu&3");
    menu->Detach();
}
delete menu;
return S_OK;
}
最后一个函数参数 是一个参数,可用于禁止显示上下文菜单。有关使用此参数的更多信息,请参阅 ObjectARX 参考。Customize()pFlag[out,retval] 
实现上下文菜单功能的最后一步是重写该方法。对于此简单情况,只需将参数的值与保存在方法中的菜单 ID 进行比较即可。如果您找到自己的某个 ID,请采取适当的措施。以下代码实现 。InvokeMenuCommand()idCmdCustomize()InvokeMenuCommand() 
STDMETHODIMP CSimpleTool::InvokeMenuCommand(/* [in] */ UINT idCmd,
	    /* [in] */ GUID *pPaletteId,
	    /* [in] */ DWORD hWnd,
	    /* [retval][out] */ DWORD *pFlag)
{
if (idCmd == m_nMenuIds[0])
    ::AfxMessageBox("Menu1 chosen");
else if (idCmd == m_nMenuIds[1])
    ::AfxMessageBox("Menu2 chosen");
else if (idCmd == m_nMenuIds[2])
    ::AfxMessageBox("Menu3 chosen");
return S_OK;
}
 
 
 
    
 |