ObjectARX右击菜单

转自:https://blog.csdn.net/u014285287/article/details/40183493

  右键菜单,也叫快捷菜单,在Windows编程中叫上下文(context)菜单。ObjectARX本身提供了一套处理上下文菜单的机制。在ObjectARX类库中有一个名为AcEdUIContext的类,此类负责在ObjectARX应用中的上下文菜单中添加自己的菜单项,而原菜单项不会被破坏,这也是此种方法的优点之一。用AcEdUIContext类添加菜单时,菜单项的数目没有限制,但必须是文本菜单。菜单可以层叠,但不允许使用键盘加速键,不能够在状态行显示快捷菜单命令状态提示。此类可以处理三种情况下的上下文菜单:一个默认上下文菜单,二是实体对象上下文菜单,三是命令执行时上下文菜单。虽然菜单出现的时机不同,但方法基本相同,它们之间主要的不同是所用的加载和卸载函数不同。下面加以详细介绍。

 在AcEdUIContext为中包含了三个重要的成员函数,他们分别是:

(1) AutoCAD系统获取快捷菜单句柄函数

  virtual void * getMenuContext(const AcRxClass * unnamed, const AcDbObjectIdArray& unnamed) = 0;

  其中,第一个参数unnamed 是当前所选择的实体的对象句柄,第二个参数unnamed是所选实体的实体ID数组。这两个参数只有在实体对象上下文菜单中有效。

 

(2) 菜单项命令事件响应函数

  virtual void onCommand(Adesk::UInt32 unnamed) = 0;

  其中,unnamed是相应菜单项的菜单ID。此函数在用户选择执行快捷菜单中的某个菜单项时被调用。

 

(3) 菜单更新函数

  virtual void OnUpdateMenu();

  AutoCAD在快捷菜单弹出之前调用此函数。相当于MFC中的菜单更新事件,我们可以在这个函数中改变菜单项的检查状态或使能菜单项等。

 

  其实,我们利用ObjectARX实现上下文菜单要做的工作主要是重载并填写这几个AcEdUIContext成员函数,其操作方法如下:

  首先,我们从AcEdUIContext类派生一个自己的类,名字就叫CDefaultContextMenu吧,当然,你可以按自己的喜好起名字了:-)。然后,在派生的类中重载以上三个函数。

class CDefaultContextMenu : public AcEdUIContext

{

public:

       CDefaultContextMenu();

       ~CDefaultContextMenu();

       // 如下重载以下三个函数

       virtual void* getMenuContext(const AcRxClass *pClass, const AcDbObjectIdArray& ids);

       virtual void onCommand(Adesk::UInt32 cmdIndex);

       virtual void OnUpdateMenu();

private:

       CMenu *m_pDemoMenu; // 用来增加菜单项的MFC菜单对象,使用它是为了加载我们在VC中增加的菜单资源。

       HMENU m_hDemoMenu; // 菜单项所对应的句柄,这才是我们真正要加载的的菜单项,它是m_pDemoMenu中的一项。

};

 

接下来我们需要做的是:

        (1)在构造函数中加载菜单资源;

        (2)在getMenuContext函数中添加显示我们自己菜单项的代码;

        (3)在onCommand函数中处理命令执行代码;

        (4)在OnUpdateMenu中修改菜单项的显示状态(此步可选可不选);

        (5)在析构函数中卸载资源。

 

  --在构造函数中加载菜单资源

acDocManager->pushResourceHandle(_hdllInstance); // 切换当前使用的资源,千万不要忘记加上吆!_hdllInstance是模块

                                //实例指针,通过extern引用到使用的位置就可以了。

m_pDemoMenu= new CMenu; // 创建一个菜单对象

m_pDemoMenu->LoadMenu(IDR_DEMO_DEFAULT_MENU); // 使用创建的菜单对象加载在资源编辑器中编辑好的资源

acDocManager->popResourceHandle(); // 再把资源切换回来吧!

 

--在getMenuContext函数中添加显示我们自己菜单项的代码

m_hDemoMenu = m_pDemoMenu->GetSubMenu(0)->GetSafeHmenu(); // 这里我们就显示已经加载的菜单(m_pDemoMenu)中的第一个子菜单吧!

return &m_hDemoMenu; // 返回子菜单对象的句柄

 

--在onCommand函数中处理命令执行代码

acDocManager->pushResourceHandle(_hdllInstance); // 切换当前使用的资源

CString strMenuTitle, strPrompt;

m_pMenu->GetMenuString(cmdIndex, strMenuTitle, MF_BYCOMMAND); // 获取一所选菜单项的文本标题

strPrompt.Format("\n您已经选取了菜单:%s\n", strMenuTitle);

acutPrintf(strPrompt); // 我们的例子显示哪一个菜单项被选择

acedPostCommandPrompt(); // 显示命令提示

acDocManager->popResourceHandle(); // 将资源切换回来

 

--在OnUpdateMenu中修改菜单项的显示状态

m_pDemoMenu->EnableMenuItem(IDR_DEMO_DEFAULT_MENU_ITEM1, MF_GRAYED); // 使菜单变灰

m_pDemoMenu->EnableMenuItem(IDR_DEMO_DEFAULT_MENU_ITEM2, MF_ENABLED); // 使能菜单项

m_pDemoMenu->CheckMenuItem(IDR_DEMO_DEFAULT_MENU_ITEM3, MF_BYCOMMAND | MF_CHECKED); // 复选菜单项

 

--在析构函数中卸载资源

if (m_pMenu) delete m_pMenu; // 不释放的话麻烦可大呀!!!

  以上用默认上下文菜单为例对AcEdUIContext类的使用方法作了阐述,至于其他两种基本是与默认上下文菜单相同。只不过在实体对象上下文菜单中的getMenuContext函数中可以对所选的实体进行响应,因为我们可以通过getMenuContext函数的参数获取实体对象。

 

 有了以上的准备工作,我们就可以按照菜单显示时机加载不同种类的菜单了。

 --(1)首先,要行声明一个全局的上下文菜单对象,如下:

CDefaultContextMenu *gpDefDemoCM; // 默认上下文菜单

CEntityContextMenu *gpEntDemoCM; // 实体对象上下文菜单

CCmdContextMenu *gpCmdDemoCM; // 命令时上下文菜单

--(2)然后,在初始化ARX应用时创建并加载上下文菜单对象。

gpDefDemoCM= new CDefaultContextMenu; // 创建默认上下文菜单

gpEntDemoCM= new CEntityContextMenu; // 创建实体对象上下文菜单

gpCmdDemoCM= new CCmdContextMenu; // 创建命令时上下文菜单

acDocManager->pushResourceHandle(_hdllInstance); // 切换当前使用的资源

acedAddDefaultContextMenu(gpDefDemoCM, pAppID); // 向AutoCAD应用中添加默认上下文菜单

acedAddObjectContextMenu(AcDbEntity::desc(), gpEntDemoCM, pAppID); // 向AutoCAD应用中添加实体对象上下文菜单

 // 向AutoCAD应用中添加命令时上下文菜单

 // myCmd是一个命令函数。第一个参数是命令组名,第二个参数是全局命令名,

 // 第三个参数是本地命令名,第四个参数是命令模式,第5和6个参数就不用说了,大家应该明白了。:-0

acedRegCmds->addCommand("MyGrp", "MyDemo", "MyDemo", ACRX_CMD_MODAL, &myCmd, gpCmdDemoCM);

acDocManager->popResourceHandle(); // 切换回资源

  说明:pAppID是acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)中是第二个参数。acedAddObjectContextMenu中的第一个参数根据实体的不同而不同,如对于线实体则为AcDbLine::desc()等。

 

--(3)最后,在卸载ARX应用时,将加载的上下文菜单对象移除,并释放内存空间。

HINSTANCE hInst = AfxGetResourceHandle(); // 保证资源正确

AfxSetResourceHandle(_hdllInstance);

acedRemoveDefaultContextMenu(gpDefDemoCM); // 移除默认上下文菜单

acedRemoveObjectContextMenu(AcDbEntity::desc(), gpEntDemoCM); // 移除实体对象上下文菜单

acedRegCmds->removeGroup("MyGrp"); // 移除命令组"MyGrp"

delete gpDefDemoCM;

delete gpEntDemoCM;

delete gpCmdDemoCM;

AfxSetResourceHandle(hInst);

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

附上ArxDbg中的ArxDbgEdUiContextApp

//

//

//

//  Copyright 2017 Autodesk, Inc.  All rights reserved.

//

//  Use of this software is subject to the terms of the Autodesk license

//  agreement provided at the time of installation or download, or which

//  otherwise accompanies this software in either electronic or hard copy form.  

//

//

//

#ifndef ARXDBGEDUICONTEXT_H

#define ARXDBGEDUICONTEXT_H

/**************************************************************************

**

**  CLASS ArxDbgEdUiContextApp

**

**  **jma

**

*************************************/

class ArxDbgEdUiContextApp : public AcEdUIContext {

public:

                           ArxDbgEdUiContextApp();

       virtual              ~ArxDbgEdUiContextApp();

    //ACRX_DECLARE_MEMBERS(ArxDbgEdUiContextApp);

    virtual void*    getMenuContext(const AcRxClass* classtype, const AcDbObjectIdArray& selectedObjs);

    virtual void     onCommand(Adesk::UInt32 cmdId);

       bool                 isValid() const { return (m_cMenu != NULL); }

private:

              // data members

    CMenu*           m_cMenu;

    HMENU            m_hMenu;

};

#endif // ARXDBGEDUICONTEXT_H

 

//

//

//

//  Copyright 2017 Autodesk, Inc.  All rights reserved.

//

//  Use of this software is subject to the terms of the Autodesk license

//  agreement provided at the time of installation or download, or which

//  otherwise accompanies this software in either electronic or hard copy form.  

//

//

//

#include "stdafx.h"

#if defined(_DEBUG) && !defined(AC_FULL_DEBUG)

#error _DEBUG should not be defined except in internal Adesk debug builds

#endif

#include "ArxDbgEdUiContext.h"

#include "ArxDbgApp.h"

#include "AcExtensionModule.h"

#include "Res_ArxDbg.h"

//ACRX_CONS_DEFINE_MEMBERS(ArxDbgEdUiContextApp, AcEdUiContext, 1)

/**************************************************************************

**

**  ArxDbgEdUiContextApp::ArxDbgEdUiContextApp

**

**  **jma

**

*************************************/

ArxDbgEdUiContextApp

::ArxDbgEdUiContextApp()

{

       CAcModuleResourceOverride(ArxDbgApp::getApp()->dllInstance());

    m_cMenu = new CMenu;

    BOOL res = m_cMenu->LoadMenu(ARXDBG_MNU_APP);

    VERIFY(res);

    if (!res) {

        delete m_cMenu;

        m_cMenu = NULL;

    }

}

/**************************************************************************

**

**  ArxDbgEdUiContextApp::ArxDbgEdUiContextApp

**

**  **jma

**

*************************************/

ArxDbgEdUiContextApp::~ArxDbgEdUiContextApp()

{

    if (m_cMenu)

        delete m_cMenu;

}

/**************************************************************************

**

**  ArxDbgEdUiContextApp::getMenuContext

**

**  **jma

**

*************************************/

void*

ArxDbgEdUiContextApp::getMenuContext(const AcRxClass* classtype, const AcDbObjectIdArray& selectedObjs)

{

    m_hMenu = m_cMenu->GetSubMenu(0)->GetSafeHmenu();

    return &m_hMenu;

}

/**************************************************************************

**

**  ArxDbgEdUiContextApp::onCommand

**

**  **jma

**

*************************************/

void 

ArxDbgEdUiContextApp::onCommand(Adesk::UInt32 cmdId)

{

       LPCTSTR cmdStr = NULL;

       CString str;

       if (cmdId == ARXDBG_APPCMD_EDITOR_INFO)

              cmdStr = _T("ArxDbgSnoopEd");

       else if (cmdId == ARXDBG_APPCMD_DB_INFO)

              cmdStr = _T("ArxDbgSnoopDb");

       else if (cmdId == ARXDBG_APPCMD_ENT_INFO)

              cmdStr = _T("ArxDbgSnoopEnts");

       else if (cmdId == ARXDBG_APPCMD_NESTEDENT_INFO)

              cmdStr = _T("ArxDbgSnoopNents");

       else if (cmdId == ARXDBG_APPCMD_SERVICES_INFO)

              cmdStr = _T("ArxDbgSnoopServices");

       else if (cmdId == ARXDBG_APPCMD_REGISTRY_INFO)

              cmdStr = _T("ArxDbgSnoopSysRegistry");

       else if (cmdId == ARXDBG_APPCMD_REACTOR_INFO)

              cmdStr = _T("ArxDbgReactors");

       else if (cmdId == ARXDBG_APPCMD_OBJ_STATE)

              cmdStr = _T("ArxDbgTestState");

       else if (cmdId == ARXDBG_APPCMD_DWG_FILER)

              cmdStr = _T("ArxDbgTestDwgFiler");

       else if (cmdId == ARXDBG_APPCMD_TEST_TRANSDB_CLONES)

              cmdStr = _T("ArxDbgTestTransDbClones");

       else if (cmdId == ARXDBG_APPCMD_TEST_WORLD_DRAW)

              cmdStr = _T("ArxDbgTestWorldDraw");

       else if (cmdId == ARXDBG_APPCMD_TEST_CURVES)

              cmdStr = _T("ArxDbgTestCurve");

       else if (cmdId == ARXDBG_APPCMD_TEST_SELSET)

              cmdStr = _T("ArxDbgTestSelSet");

       else if (cmdId == ARXDBG_APPCMD_TEST_XDATA)

              cmdStr = _T("ArxDbgTestXdata");

       else if (cmdId == ARXDBG_APPCMD_TEST_EXTENTS)

              cmdStr = _T("ArxDbgTestExtents");

       else if (cmdId == ARXDBG_APPCMD_TEST_INTERSECT)

              cmdStr = _T("ArxDbgTestIntersect");

       else if (cmdId == ARXDBG_APPCMD_TEST_GRIPPTS)

              cmdStr = _T("ArxDbgTestGetGripPoints");

       else if (cmdId == ARXDBG_APPCMD_TEST_STRETCHPTS)

              cmdStr = _T("ArxDbgTestGetStretchPoints");

       else if (cmdId == ARXDBG_APPCMD_TEST_OSNAP)

              cmdStr = _T("ArxDbgTestGetOsnapPoints");

       else if (cmdId == ARXDBG_APPCMD_TEST_EXTDICTADD)

              cmdStr = _T("ArxDbgTestExtDictAdd");

       else if (cmdId == ARXDBG_APPCMD_TEST_EXTDICT_REMOVE)

              cmdStr = _T("ArxDbgTestExtDictRemove");

       else if (cmdId == ARXDBG_APPCMD_TEST_COLOR)

              cmdStr = _T("ArxDbgTestColor");

       else if (cmdId == ARXDBG_APPCMD_TEST_PURGE)

              cmdStr = _T("ArxDbgTestPruge");

       else if (cmdId == ARXDBG_APPCMD_TEST_COUNTREFS)

              cmdStr = _T("ArxDbgTestCountHardRefs");

       else if (cmdId == ARXDBG_APPCMD_TEST_ENTMAKE)

              cmdStr = _T("ArxDbgTestEntMake");

       else if (cmdId == ARXDBG_APPCMD_TEST_TBLMAKE)

              cmdStr = _T("ArxDbgTestTblMake");

       else if (cmdId == ARXDBG_APPCMD_TEST_XFORM)

              cmdStr = _T("ArxDbgTestXform");

       else if (cmdId == ARXDBG_APPCMD_LOGO_ADD)

              cmdStr = _T("ArxDbgAdeskLogoAdd");

       else if (cmdId == ARXDBG_APPCMD_LOGO_MODIFY)

              cmdStr = _T("ArxDbgAdeskLogoModify");

       else if (cmdId == ARXDBG_APPCMD_LOGO_HARDWIRE1)

              cmdStr = _T("ArxDbgAdeskLogoHardwire1");

       else if (cmdId == ARXDBG_APPCMD_LOGO_HARDWIRE2)

              cmdStr = _T("ArxDbgAdeskLogoHardwire2");

       else if (cmdId == ARXDBG_APPCMD_LOGO_ADD_STYLE)

              cmdStr = _T("ArxDbgAdeskLogoStyleAdd");

       else if (cmdId == ARXDBG_APPCMD_LOGO_MOD_STYLE)

              cmdStr = _T("ArxDbgAdeskLogoStyleModify");

       else if (cmdId == ARXDBG_APPCMD_ABOUT)

              cmdStr = _T("ArxDbgAbout");

       if (cmdStr != NULL) {

              str.Format(_T("%s\n"), cmdStr);

           acDocManager->sendStringToExecute(acDocManager->curDocument(), str, false, false);

       }

}

 

转自:https://blog.csdn.net/u014285287/article/details/40183493

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值