> 文章列表 > ObjectARX中反应器的使用

ObjectARX中反应器的使用

ObjectARX中反应器的使用

ObjectARX中反应器的使用

  • 反应器机制是观察者模式(设计模式)的一种实现,在该机制下,有事件通知者和事件接收者,负责接收事件的称为反应器
  • 反应器列表:在反应器可以从通知者处接收消息之前,必须显式地将反应器添加到通知者的反应器列表中。
  • 反应器部分类继承关系

种类:

编辑反应器:AcEditorReactor

实体反应器:AcDbEntityReactor

对象反应器:AcDbObjectReactor

图形数据库反应器:AcDbDatabaseReactor

文档管理反应器:AcApDocManagerReactor

根据反应器的基本性质,反应器被分为临时反应器和永久反应器。

临时反应器本身不是数据库对象,由开发者负责临时反应器的注册和卸载,用来监控数据库事件、用户操作以及其他的程序运行时的系统事件。

永久反应器是一个数据库的对象,由开发者创建并由AutoCAD负责删除,永久反应器可以接收及发送消息,可以被保存到DWG和DXF文件中,当图纸被加载的时候会重建永久反应器。用来实现对象之间的关联反应。

下面是一个永久反应器的例子:联动删除

  1. 自定义实体基类CthEntity继承ObjectArx里底层基类AcDbEntity。

  2. 重写自定义基类CthEntity的subErase()函数。

  3. 在subErase()函数里添加要联动删除的实体,一般以持久反应器实现联动。

  4. 删除实体触发Erase命令的subErase()函数

//zhaoanan subErase命令
Acad::ErrorStatus CthEntity::subErase(Adesk::Boolean erasing)
{try{// 调试if (id() != AcDbObjectId::kNull){ACHAR s[30];id().handle().getIntoAsciiBuffer(s);wcscat_s(s, 30, _T(" subErase"));CthLog::WriteLog(s);}//删除实体的公里标对象this->removeDimension();Acad::ErrorStatus es = AcDbEntity::subErase(erasing);if (es != Acad::eOk)return es;}catch (...){return Acad::eOk;}return Acad::eOk;
}
  1. 删除实体的公里标对象,使用永久反应器实现联动功能
//删除实体的公里标对象
void CthEntity::removeDimension()
{//激活支持撤销恢复,该函数主要为“退回”操作及“保存”的操作;如不加则会在上述操作中出现异常。assertWriteEnabled() ;/*- 1.获取到公里标反应器数组*/const AcDbVoidPtrArray* rs = reactors();if (rs != NULL) {/*- 2.根据公里标反应器数组,循环查找公里标依赖*/acutPrintf(_T("rs->length()=%d\\n"), rs->length());for (int i = 0; i < rs->length(); i++) {void* p = rs->at(i);if (!acdbIsPersistentReactor(p))continue;/*- 2.1根据公里标反应器,查找公里标依赖objecid*/AcDbObjectId oi = acdbPersistentReactorObjectId(p);acutPrintf(_T("CthDependency's AcDbObjectId=%p\\n"), &oi);CthDimension *pDimension =NULL;CthDependency *pDedp =NULL;//智能指针打开对象//AcDbObjectPointer<AcDbObject> obj(oi,AcDb::kForRead);/*- 2.1根据公里标依赖objecid,打开实体公里标依赖*/Acad::ErrorStatus es = acdbOpenObject(pDedp, oi, AcDb::kForWrite, Adesk::kTrue);if (es != Acad::eOk)continue;/*- 获取到公里标反应器*//*- 2.2根据公里标依赖,打开实体公里标对象*/acutPrintf(_T("&pDedp=%p\\n"), pDedp);if(pDedp!=NULL){AcDbObjectId id = pDedp->dependencyId();AcDbEntity *ppEnt=NULL;/*- 2.3打开实体公里标对象*/if(Acad::eOk==acdbOpenAcDbEntity(ppEnt,id,AcDb::kForRead)){if(ppEnt->isKindOf(CthDimension::desc())){pDimension = CthDimension::cast(ppEnt);}}}/*- 3删除公里标对象*/pDimension->upgradeOpen();pDimension->erase();pDimension->downgradeOpen();pDimension->close();/*- 4关闭公里标依赖对象*/pDedp->close();/*- 5删除公里标对象依赖反应器*/this->removePersistentReactor(oi);}/*- 5释放删除公里标对象依赖反应器的空字典*/this->releaseExtensionDictionary();}
}

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器