乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 120|回复: 6

AutoCAD中实现双击编辑总结及源代码

[复制链接]

9

主题

21

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
57
发表于 2015-3-23 14:34:00 | 显示全部楼层 |阅读模式
将自己在中实现鼠标双击编辑编程总结如下。根据网上收集资料消化所得,源码根据网上收集的代码修改增加,用vs10.0可编译为cad2002-2012程序,采用VC版本宏_MSC_VER 来进行条件编译,源代码实现了文章中的两种双击方式,注意看源码中的代码注释来选择哪一种方式。
AutoCAD中实现双击编辑
AutoCAD中arx编程实现双击编辑有两种方法,其一是基于类AcDbDoubleClickEdit的双击事件,另一方法是使用反应器机制实现。(一) 基于类AcDbDoubleClickEdit的双击事件实现双击编辑(1)AutoCAD2002-AutoCAD2009版本AutoCAD2002-AutoCAD2009中有ObjectARX API专门用来处理实体的双击事件,此API基于AcDbDoubleClickEdit类。在AutoCAD中双击实体时,默认的行为是调用相应的实体定义编辑器或对象属性管理器。如果多个实体同时被选中,在选择集中双击实体会弹出对象属性管理器。对于自定义实体,可以重载AcDbDoubleClickEdit类的双击事件,改变默认行为,为此需要从AcDbDoubleClickEdit为每个要处理双击事件的实体派生类。为了接受通告消息,在这个类中必需声明两个方法:一个是startEdit(),另一个是finishEdit()。当应用程序被​加载的时候,AcDbDoubleClickEdit类要对要处理的数据库对象增加协议扩展,例如在InitApplication()初始化过程中增加如下的代码:pPlineEdit = new AcDbDoubleClickEditPline;AcDbPline::desc()->addX(AcDbDoubleClickEdit::desc(),pPlineEdit);同样地,在卸载应用程序的时候去除数据库对象的协议扩展,方法如下:AcDbPline::desc()->delX(AcDbDoubleClickEdit::desc());要使程序能够被编译,还必需连接AcDblClkEditPE.lib库,可使用#pragma comment (lib ,"AcDblClkEditPE.lib")。并且在InitApplication()中增加如下的代码:acrxDynamicLinker->loadModule(/*MSG0*/"ACDBLCLKEDITPE.ARX",Adesk::kFalse);(AutoCAD启动时自行装载了AcDblClkEdit.arx及ACDBLCLKEDITPE.ARX,可以不要该行语句) 例子:双击实体弹出对话框(重载AcDbDoubleClickEdit)ARX // DoubleClickEdit.h: interface for the CDoubleClickEdit class.//By freejsutin 2005-08-17 #include "AcDblClkEdit.h" //for dinfine AcDbDoubleClickEdit#pragma comment (lib ,"AcDblClkEditPE.lib")#include "actrans.h" //for dinfine actrTransactionManagerclass CDoubleClickEdit : public AcDbDoubleClickEdit {public:CDoubleClickEdit();virtual ~CDoubleClickEdit(); void finishEdit(void);void CDoubleClickEdit::startEdit(AcDbEntity *pEnt, AcGePoint3d clickpt);private:bool upgradeOpen(AcDbObject *pEnt);};// DoubleClickEdit.cpp: implementation of the CDoubleClickE//dit class.///////////////////////////////////////////////////////////#include "stdafx.h"#include "autodrawing.h"#include "DoubleClickEdit.h"#include "DeviceAttribute.h"void CDoubleClickEdit::finishEdit(){ }// 主要是这个函数在起作用,在这个函数里实现你想要的功能void CDoubleClickEdit::startEdit(AcDbEntity *pEnt, AcGePoint3d clickpt){// 由于要对实体进行编辑,先锁定文档AcApDocument *pDoc = acDocManager->curDocument();acDocManager->lockDocument(pDoc, AcAp::kWrite); // 判断如果传进来的实体是我的自定义实体,便进行修改操作if (pEnt->isKindOf(cascoCDeviceDrawing::desc()))
{
   cascoCDeviceDrawing* pMyClass = cascoCDeviceDrawing::cast(pEnt);
   // 将打开级别升级到可写方式,防止对象以只读模式打开
   if( !upgradeOpen(pMyClass) )
   {
            acDocManager->unlockDocument(pDoc);
    return;
   }
   // 创建这个对象,以便切换CAD资源
   CAcModuleResourceOverride thisResource;
   CDeviceAttribute Diatest(CWnd::FromHandle(adsw_acadMainWnd()));
   Diatest.DoModal();
   pMyClass->close();
}
// 所有修改完成,解锁文档
acDocManager->unlockDocument(pDoc);
// 刷新显示
actrTransactionManager->flushGraphics();
}
bool CDoubleClickEdit::upgradeOpen(AcDbObject *pEnt)
{
if(pEnt->upgradeOpen()!=Acad::eOk)
{
   acutPrintf("错误:不能打开%s实体!", pEnt->isA()->name());
   return FALSE;
}
return TRUE;
}(2)AutoCAD2010及以上版本AutoCAD2010及以上版本没有AcDbDoubleClickEdit类,在AcDblClkEditPE.arx中的 AcDbDoubleClickEdit 功能已在  AcApp.arx 和 acad.lib中了。(AutoCAD2010及以上版本自定义实体的时worldDraw(AcGiWorldDraw *mode)等也改为subWorldDraw(AcGiWorldDraw *mode))    为使 AutoCAD 2010及以上版本的双击扩展协议能起作用,必需:    1、删除调用AcDblClkEditPE.arx 的 loadModule() 。    2、删除 AcDbDoubleClickEdit::rxinit() ,这项工作已能自动完成。    3、Include the AcDblClkEdit.h     4、在你的.cpp模块之一中增加 ACRX_DEFINE_MEMBERS(AcDbDoubleClickEdit)(二) 使用反应器机制实现双击编辑Autodesk为开发者提供了反应器机制,它类似于MFC的消息处理,利用它我们可以响应输入事件、实体添加/编辑/删除等事件。常见的AutoCAD反应器有:编辑反应器(AcEditorReactor)、实体反应器(AcDbEntityReactor)、对象反应器(AcDbObjectReactor)、图形数据库反应器(AcDbDatabaseReactor)、文档管理反应器(AcApDocManagerReactor)等。我们在这里是利用编辑反应器来实现鼠标双击事件的响应的,下面是实现步骤。第一步 派生一个编辑反应器类CMyEditReactor。并重载编辑反应器的如下方法:      virtual void beginDoubleClick(const AcGePoint3d& clickPoint);  这里只返回了双击时鼠标所在的一点,并不像上面方法(一)双击事件还返回了该点所在的实体对象。在本方法中怎样由该点获得要编辑的实体是本方法的关键。   第二步 声明一个全局CMyEditReactor对象,如下:      static CMyEditReactor *gpDblClkTest;   第三步 在应用程序初始化时创建反应器对象,将反应器对象增加到编辑反应器列表。// Init this application. Register your// commands, reactors...void InitApplication(){// NOTE: DO NOT edit the following lines.//{{AFX_ARX_INIT............................................//}}AFX_ARX_INIT// TODO: add your initialization functionsgpDblClkTest = new CMyEditReactor(); // 创建编辑反应器对象acedEditor->addReactor(gpDblClkTest );}第四步 在应用程序卸载时从内存中清除反应器对象,将反应器对象从编辑反应器列表中删除。// Unload this application. Unregister all objects// registered in InitApplication.void UnloadApplication(){// NOTE: DO NOT edit the following lines.//{{AFX_ARX_EXIT.........................................................//}}AFX_ARX_EXIT// TODO: clean up your applicationif(gpDblClkTest){ acedEditor->removeReactor(gpDblClkTest);delete gpDblClkTest; // 清除编辑反应器对象gpDblClkTest = NULL;}}第五步 响应鼠标事件,编写响应代码。void CMyEditReactor::beginDoubleClick(const AcGePoint3d & clickPoint){    ads_name ssName;     ads_name entName;    ads_point pt;    AcDbObjectId id;    AcDbEntity *pEnt=NULL;    long len;
    struct resbuf rStarDb, rEndDb;
    rStarDb.restype = RTSHORT;
    rStarDb.resval.rint = 1;
    rEndDb.restype = RTSHORT;
    rEndDb.resval.rint = 0;
// 由于要对实体进行编辑,先锁定文档    AcApDocument *pDoc=acDocManager->curDocument();    acDocManager->lockDocument(pDoc,AcAp::kWrite);
    acedSetVar(_T("DBLCLKEDIT"),&rStarDb);       //双击开始恢复cad默认的行为
    if(acedSSGet(NULL,asDblArray(clickPoint),NULL,NULL,ssName)!= RTNORM )  //获得双击的选择集    {        acedSSFree(ssName);          return;        }    Acad::ErrorStatus es;    acedSSLength(ssName,&len);    if (len>1)                    //表示多个实体重叠情况    {        acedSSFree(ssName);        return;    }    if (acedSSName(ssName, 0, entName) == RTNORM) //获得实体名    {        es = acdbGetObjectId(id,entName);  //获得实体id        if(es!=Acad::eOk)        {            AfxMessageBox(_T("打开实体ID失败"));            acedSSFree(ssName);            return;        }        es=acdbOpenObject(pEnt,id,AcDb::kForWrite);  //获得要处理的实体对象        if(es!=Acad::eOk)        {            AfxMessageBox(_T("acdbOpenObject(pEnt,pID,AcDb::kForWrite)失败!"));            acedSSFree(ssName);            return;        }/*   在该位置才锁定文档,MDI文档时出错        // 由于要对实体进行编辑,先锁定文档        AcApDocument *pDoc=acDocManager->curDocument();        acDocManager->lockDocument(pDoc,AcAp::kWrite);*/        // 判断如果传进来的实体是我的自定义实体,便进行修改操作        if(pEnt->isKindOf(AsdkMyClass::desc()) == Adesk::kTrue)        {            AsdkMyClass* pMyClass = AsdkMyClass::cast(pEnt);
                acedSetVar(_T("DBLCLKEDIT"),&rEndDb);       //自定义实体双击编辑屏蔽cad默认双击行为
            // 创建这个对象,以便切换CAD资源            CAcModuleResourceOverride thisResource;                // 创建我的修改实体对话框            CDlgModiEnt Dlg(CWnd::FromHandle(adsw_acadMainWnd()));             // 设定初值            Dlg.setValue(pMyClass->GetFloorNum(), pMyClass->GetBaseHeight());            // 如果“OK”按钮被按下,对自定义实体进行修改            if (Dlg.DoModal() == IDOK) {                pMyClass->SetFloorNum(Dlg.m_num);                pMyClass->SetBaseHeight(Dlg.m_height);                pMyClass->ExtendedBaseIni();            }            pMyClass->close();        }        else            pEnt->close();        // 所有修改完成,解锁文档        acDocManager->unlockDocument(pDoc);        acedSSFree(ssName);    }(三) 基于类AcDbDoubleClickEdit及基于反应器机制的双击事件实现双击编辑的不同   1、基于类AcDbDoubleClickEdit需要从AcDbDoubleClickEdit为每个要处理双击事件的实体派生类。当应用程序被​加载的时候,AcDbDoubleClickEdit类要对要处理的数据库对象增加协议扩展,在卸载应用程序的时候去除数据库对象的协议扩展。(似乎是不必为每一类实体对象从AcDbDoubleClickEdit派生双击事件派生类,改objectarx2006附带的双击编辑例子实现)   2、基于编辑反应器机制的只需派生一个编辑反应器类CMyEditReactor。并重载编辑反应器的如下方法:virtual void beginDoubleClick(const AcGePoint3d& clickPoint),只创建一个全局反应器对象,可对不同的对象选择编辑。  3、使用编辑反应器机制的工作量要小,但编辑完成之后还是会弹出属性编辑对话框,不知怎样解决。  4、基于类AcDbDoubleClickEdit的方式编辑完成之后不会弹出属性编辑对话框,双击时存在多选实体时,只会弹出属性编辑对话框,不会弹出属性编辑对话框,与cad本身的编辑方式相同。(四)存在问题    当基于编辑反应器机制时,选用cad->选项->配置->可用配置的另一配置时,双击编辑会出现问题。   问题已解决:1、当基于编辑反应器机制时,选用cad工具->选项->配置->可用配置的另一配置时,双击编辑会出现打开文件写失败的原因是文档锁定问题,单文档无问题,多文档失败。将源码中锁定文档的语句再向前移动就能解决mdi文档出错的问题。2、使用编辑反应器机制编辑完成之后还是会弹出属性编辑对话框,是对原cad的双击编辑机制未进行屏蔽。解决:进行双击开始(beginDoubleClick函数体内开始位置)还原系统变量、恢复cad默认的双击行为,在确定选择的是自定义实体时改变系统变量DBLCLKEDIT为0,屏蔽cad默认的双击行为。(自定义了双击编辑反应器后,任何cad原有的实体双击编辑,均先调用自定义的双击编辑反应器,之后才执行cad只有的双击编辑行为,因此如采用在beginDoubleClick(const AcGePoint3d & clickPoint)函数体内自定义编辑前改变系统变量DBLCLKEDIT为0,屏蔽cad默认的双击行为,函数体结尾恢复cad默认的双击行为是行不通的)。3、注意系统变量PICKFIRST对双击行为的影响,当系统变量PICKFIRST为0时,双击是不起作用的。
回复

使用道具 举报

1

主题

313

帖子

16

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
317
发表于 2015-3-24 08:18:00 | 显示全部楼层
楼主不是一般的强!
回复

使用道具 举报

1

主题

3

帖子

1

银币

初来乍到

Rank: 1

铜币
7
发表于 2016-1-18 23:30:00 | 显示全部楼层
顶!!赞!!好帖子
回复

使用道具 举报

1

主题

4

帖子

4

银币

初来乍到

Rank: 1

铜币
8
发表于 2019-6-10 19:23:00 | 显示全部楼层
好东西,顶!
回复

使用道具 举报

0

主题

3

帖子

1

银币

初来乍到

Rank: 1

铜币
3
发表于 2019-7-19 08:58:00 | 显示全部楼层

精品贴!
回复

使用道具 举报

29

主题

743

帖子

11

银币

中流砥柱

Rank: 25

铜币
858
发表于 2019-7-26 15:18:00 | 显示全部楼层
总结得很好。。。
回复

使用道具 举报

0

主题

3

帖子

1

银币

初来乍到

Rank: 1

铜币
3
发表于 2020-11-18 08:26:00 | 显示全部楼层
感谢亲的分享
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-2-4 03:41 , Processed in 0.276911 second(s), 66 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表