CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

管理上下文菜单

2022-12-31 08:55| 发布者: admin| 查看: 208| 评论: 0|来自: AutoCAD

当用户右键单击工具选项板时更改上下文菜单相对简单。派生自。但是,它的方法定义只是返回以避免链接器错误。因此,您必须覆盖接口的两个方法:and。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 实现

  1. simpleTool.h文件中,添加以下预处理器定义:
    #define MAX_MENU_ENTRIES 3
    
  2. simpleTool.cpp文件中,添加以下静态数组来存储您使用的 ID:
    static UINT m_nMenuIds[MAX_MENU_ENTRIES] = {0,0,0};
    
  3. 在类声明中,声明两个方法的原型: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);
    
  4. SimpleTool.cpp文件中,为 and 方法添加空白的实现原型。Customize()InvokeMenuCommand()

    现在,您已准备好实现上下文菜单功能。

实现 Customize() 方法

  1. 在实现正文中,检查是否尝试添加的菜单项数超过框架允许的数量:Customize()
    int maxMenu = (idCmdLast - idCmdFirst) < MAX_MENU_ENTRIES ?     (idCmdLast - idCmdFirst) : MAX_MENU_ENTRIES;
    
  2. 使用参数获取当前工具选项板的名称。可以使用对象来检索调色板。以下代码对此进行了演示。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);
    
  3. 将调色板的名称与调色板的名称进行比较。如果发现不匹配,请将菜单 ID 数组条目重新初始化为 0 并返回:
    if (_tcscmp(pszString, "SimplePalette")!= 0)
    {
        for (i=0; i < maxMenu ; i++)
        {
            m_nMenuIds[i] = 0;
        }
        return E_NOTIMPL;
    }
    
  4. 使用步骤 1 中确定的最大菜单项限制保存给定范围内的三个命令 ID:
    int i;
    for (i=0; i < maxMenu ; i++)
    {
        m_nMenuIds[i] = idCmdFirst + i;
    }
    
  5. 创建一个新对象:CMenu
    CMenu* menu = new CMenu;
    
  6. Attach the object to the context menu, using the parameter and the function:CMenuhMenuCMenu::Attach()
    menu->Attach(HMENU(hMenu);
    
  7. Add three menu commands, using the selected command IDs:
    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");
    
  8. Detach the object and delete it:CMenu
    menu->Detach();
    delete menu;
    

    Here is the finished method override: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;
    }
    

路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-5-19 16:15

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部