LoveArx 发表于 2013-5-20 01:27:22

AutoCAD ObjectARX 二次开发实例(1)——上下文菜单


本文原创,如需转载,请注明出处!
用ObjectARX进行CAD的二次开发,程序员特别关心用户界面的问题,像对话框,菜单等,下面的以ARX开发包的实例为例,说明ARX的CAD二次开发中的界面问题。
上下文菜单(Context Menu)
环境说明:后面所有的“开发实例”系列的帖子都使用VC++.net2002+AutoCAD2005+ARX2005
以SDK中ContextMenu例子为例。
ARX中的上下文菜单(快捷菜单)的实现主要与AcEdUIContext类有关。需注意的是,虽然对菜单项的数目没有限制,但菜单项中只能包含文本。可以有层叠菜单。你的ARX
程序提供的快捷菜单项不包含键盘加速键,并且对于新添加的菜单项,状态栏中没有帮助提示(这点有点怀疑,因为我并没有在资源中加菜单项的提示字符串,但在程序
运行过程中有一些不知哪来的字符串显示于状态栏中)。
ARX的上下文菜单有三种模式:
1、默认模式:当没有命令运行,并且没有pick
first选择集时,用户右击出现的快捷菜单中包含的标准项从.MNU文件中的CMDDEFAULT
POP菜单读出的。你的ARX程序可以
加入菜单项到此时的快捷菜单中,但此菜单项是以一个子菜单的形式加入的,具体的项目可加到这个子菜单的层叠菜单中。你的ARX程序必须为这个子菜单项提供菜单资
源,并通过一个CMenu指针和HMENU变量对菜单进行控制,同时要提供必要的回调函数,以响应菜单命令。若在程序中没有指定子菜单名字,那最高层项目(就是子菜单名
,与标准项目位列在一起)就是ARX程序的名字。
创建默认模式的上下文菜单的步骤:
a.从AcEdUIContext派生一个类,并用资源编辑器编辑好菜单。
b.在此类的构造函数中载入指定的菜单,并在析构函数中作好清理工作,如下。
//构造函数
cmCommandContext::cmCommandContext()
{
//把当前的资源句柄标识的资源压入当前文档的资源句柄栈,并把_hdllInstance指定的资源作为当前资源,这里相当于是保存资源现场

acDocManager->pushResourceHandle(_hdllInstance);
//载入菜单

m_pMenu = new CMenu();
   
m_pMenu->LoadMenu(IDR_MENU6);
//恢复资源现场
   
acDocManager->popResourceHandle();
}
//析构函数,很明显,不用解释
cmCommandContext::~cmCommandContext()
{

if(m_pMenu)
      delete
m_pMenu;
}


c.改写AcEdUIContext的三个虚函数,这三个函数都是在不同情况下被CAD所调用以实现一系列功能。
getMenuContext函数用于给CAD调用,以得到快捷菜单的HMENU句柄,这样CAD可通过此句柄操纵菜单,用m_pMenu->GetSubMenu(0)->GetSafeHmenu();便可完成;

OnUpdateMenu函数相当于MFC中的UPDATE_COMMAND_UI消息对应的处理函数,便于在显示菜单前,被CAD调用设置菜单项的状态,如变灰,不可用等。
onCommand函数则是当用户选择一个菜单项时,CAD调用的。若用户点击ARX程序添加的菜单项时CAD就会使用与此项相关的Id(由HMENU提供)作为参数调用AcEdUIContext对
象的成员函数onCommand()。

d.声明一个你的默认菜单类的对象,并用acedAddDefaultContextMenu函数添加到标准的默认菜单中。在SDK的例子中,使用了三次来调用此函数,以测试不同的情况,第一次添加了菜单的名字,第二次没有添加,说明使用程序的名字作为菜单的名字,第三次是如第二次般使用函数,说明再次添加相同的菜单(对象不同,但实际指向的菜单相同)时,CAD会忽略后面添加的相同菜单的。

e.在程序结束时,用acedRemoveDefaultContextMenu移除此默认的上下文菜单。

如下图:


2、命令模式:当ARX命令在运行时,并且用户右击出现快捷菜单时,菜单中的标准项从.MNU文件中的CMCOMMAND
POP菜单中读取。另外,若ARX发出的命令提示有命令选项
,并且命令提示使用了标准的语法的话,这些选项会在快捷菜单中以独立的选项显示。当用户点击从快捷菜单中点击一个命令选项时,选项的关键字会被发送到当前的命
令窗口。
这些命令选项常被添加到快捷菜单中,ARX程序员只需以标准的形式提供一个命令提示就可得到这种功能。
创建命令模式的上下文菜单的步骤与创建默认模式的相似,只是添加时用acedRegCmds->addCommand添加,在其最后一个参数中加和菜单对应的对象;在程序结束时,不
用移除。
对于本例中命令模式的菜单,好像没有成功,例子中无法显示,不知怎么原因,知道原因的大家说说。
3、编辑模式:当存在pick
first选择集,也就是说在用户选中了实体在进行编辑时,用户右击就可出现快捷菜单,菜单中的标准项从.MNU文件中的CMEDIT
POP菜单中读
取。另外,被选择的对象对应的菜单项也可添加项目到菜单中。每个对象层次结构中的AcRxClass对象都可包含一个AcEdUIContext对象。快捷菜单代码决定了选择集中所
有对象的共同父类。从这个父类开始,依类层次结构向上,询问每个类是否有AcEdUIContext对象,然后从提供的HMENU中添加项目到快捷菜单中。用这种方法,在类层次
结构中的每个类都能向快捷菜单贡献项目。ARX程序必须在AutoCAD调用从类层次结构中得到的AcEdUIContext对象的getMenuContext()时返回一个HMENU*若用户点击这些
添加的项目,AutoCAD就会使用与此项相关的Id(由HMENU提供)作为参数调用AcEdUIContext对象的成员函数onCommand()
创建编辑模式的上下文菜单的步骤:
a.菜单类的定义及实现与默认模式的类似。
b.添加菜单用acedAddObjectContextMenu。
c.移除菜单用acedRemoveObjectContextMenu。
如下图:



例子中其它要说明的地方:
在初始化中用acDocManager->pushResourceHandle和acDocManager->popResourceHandle在保存和恢复资源,但在程序结束中用HINSTANCE
hInst =

AfxGetResourceHandle();AfxSetResourceHandle(_hdllInstance);和AfxSetResourceHandle来保存和恢复资源。为什么不一样呢?我想可以是在初始化时,CAD文档已经
初始化,所以可用文档的资源操作函数,在结束程序时,可能文档已经析构了,所以只能用全局函数来操作资源。



cre8o 发表于 2013-6-20 11:50:29

有两个问题我想知道 首先能暂时覆盖mnu提供的菜单吗? 在某些程序运行中是用不到那么多默认命令的 然后有办法在点选物体后自动弹出上下文菜单么? 有些命令 右键就意味着取消 那就没法运行了

Gdlprfcu 发表于 2013-5-20 22:29:48

谢谢分享。

黑叶子 发表于 2013-5-21 08:30:44

希望更多人出来交流下经验

wuyanfan 发表于 2023-12-20 17:42:14

留名收藏学习
页: [1]
查看完整版本: AutoCAD ObjectARX 二次开发实例(1)——上下文菜单