本例是AutoCAD ObjectARX2000 开发技术指南中的例子,但稍加改变。
用向导建立工程。
AsdkObjectReactor.h文件:
#include "dbmain.h"
/*
使一个数据库对象对另一个数据库对象起反应的步骤为:
1. 从AcDbObject类或其任何子类派生一个类。
2. 实现其通知函数。
3. 建立该类的对象实例。
4. 将该对象加入到数据库中,并制定一个所有者。
5. 用AcDbObject::addPersistentReactor()函数将它加到通知者对象中。
*/
/*
本例演示如何使用反应器建立数据库对象之间的依存关系。
在本例中,如果改变一条线,则另一条线也跟着起变化。
*/
class CAsdkObjectReactor : public AcDbObject
{
public:
ACRX_DECLARE_MEMBERS(CAsdkObjectReactor);
CAsdkObjectReactor(void) {};
public:
void eLinkage(AcDbObjectId i, double f = 1.0) {m_EntId = i; m_Factor = f;};
public:
// 重载函数
void modified(const AcDbObject* dbObj);
// 必须重载的函数
Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);
Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler);
Acad::ErrorStatus dxfInFields(AcDbDxfFiler* pFiler);
Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* pFiler);
private:
AcDbObjectId m_EntId; // 关联的对象的对象ID
double m_Factor; // 比例因子
};
ACDB_REGISTER_OBJECT_ENTRY_AUTO(CAsdkObjectReactor)
Acad::ErrorStatus addToModelSpace(AcDbObjectId& objId, AcDbEntity* pEntity);
Acad::ErrorStatus assocLines();
AsdkObjectReactor.cpp文件:
#include "StdAfx.h"
#include "AsdkObjectReactor.h"
ACRX_DXF_DEFINE_MEMBERS(CAsdkObjectReactor, AcDbObject, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0, ASDKOBJECTTONNOTIFY, persreac);
/*
这个函数在每次对直线中的一条进行改动时调用。当它被调用时,
它打开另一条直线,并将其长度变为前面改动后的直线的长度。
*/
void CAsdkObjectReactor::modified(const AcDbObject* dbObj)
{
AcDbLine* pLine = AcDbLine::cast(dbObj);
if (!pLine)
{
const ACHAR* cstr = dbObj->isA()->name();
acutPrintf(_T("这是一个%s.\n而本程序只对直线起作用。\n"), cstr);
return;
}
acutPrintf(_T("\nReactor attached to %lx calling %lx.\n"), pLine->objectId(), m_EntId);
/*
当一个反应器正在被加到实体上的通知过程中,或者该通知正在对
由于另外一条直线改动而进行这条直线的改动工作反应时,就会引起失败。
这就有效防止了两条直线和其反应器之间可能产生的通知死循环。
*/
AcDbLine* pLine2;
if (acdbOpenObject((AcDbObject*&)pLine2, m_EntId, AcDb::kForWrite) == Acad::eOk)
{
// 获取改动后的直线的长度
AcGePoint3d startPt = pLine->startPoint();
AcGePoint3d endPt = pLine->endPoint();
AcGeVector3d vec = endPt - startPt;
double length = vec.length();
// 更新另一条直线
startPt = pLine2->startPoint();
endPt = pLine2->endPoint();
vec = endPt - startPt;
vec = length * m_Factor * vec.normal();
pLine2->setEndPoint(startPt + vec);
pLine2->close();
}
}
/*
编入一个对象的信息
*/
Acad::ErrorStatus CAsdkObjectReactor::dwgInFields(AcDbDwgFiler* pFiler)
{
assertWriteEnabled();
AcDbObject::dwgInFields(pFiler);
pFiler->readItem(&m_Factor);
pFiler->readItem((AcDbSoftPointerId*)&m_EntId);
return pFiler->filerStatus();
}
/*
编出一个对象的信息
*/
Acad::ErrorStatus CAsdkObjectReactor::dwgOutFields(AcDbDwgFiler* pFiler)
{
assertReadEnabled();
AcDbObject::dwgOutFields(pFiler);
pFiler->writeItem(m_Factor);
pFiler->writeItem((AcDbSoftPointerId&)m_EntId);
return pFiler->filerStatus();
}
/*
从DXF和AutoLisp编入一个对象的信息
*/
Acad::ErrorStatus CAsdkObjectReactor::dxfInFields(AcDbDxfFiler* pFiler)
{
assertWriteEnabled();
Acad::ErrorStatus es;
if ((es = AcDbObject::dxfInFields(pFiler)) != Acad::eOk)
{
return es;
}
// 检查是否在正确的子类数据标记上
if (pFiler->atSubclassData(_T("AsdkObjectToNotify")))
{
return Acad::eBadDxfSequence;
}
struct resbuf rbIn;
while (es == Acad::eOk)
{
if ((es = pFiler->readItem(&rbIn)) == Acad::eOk)
{
if (rbIn.restype == AcDb::kDxfReal)
{
m_Factor = rbIn.resval.rreal;
}
else if (rbIn.restype == AcDb::kDxfSoftPointerId)
{
acdbGetObjectId(m_EntId, rbIn.resval.rlname);
}
else
{
return pFiler->pushBackItem();
}
}
}
return pFiler->filerStatus();
}
/*
编出一个对象的信息到DXF和AutoLisp
*/
Acad::ErrorStatus CAsdkObjectReactor::dxfOutFields(AcDbDxfFiler* pFiler)
{
assertReadEnabled();
AcDbObject::dxfOutFields(pFiler);
pFiler->writeItem(AcDb::kDxfSubclass, _T("AsdkObjectToNotify"));
pFiler->writeItem(AcDb::kDxfReal, m_Factor);
pFiler->writeItem(AcDb::kDxfSoftPointerId, m_EntId);
return pFiler->filerStatus();
}
// 添加一个实体到模型空间,但不关闭实体
Acad::ErrorStatus addToModelSpace(AcDbObjectId& objId, AcDbEntity* pEntity)
{
AcDbBlockTable* pBlockTable;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
pBlockTable->close();
Acad::ErrorStatus er = pBlockTableRecord->appendAcDbEntity(objId, pEntity);
if (er != Acad::eOk)
{
acutPrintf(_T("addToModelSpace Field.\n"));
pBlockTableRecord->close();
return er;
}
pBlockTableRecord->close();
return Acad::eOk;
}
// 创建两条直线和两个AsdkObjectToNotify对象,并把他们联系到一起
Acad::ErrorStatus assocLines()
{
Acad::ErrorStatus er;
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
AcDbObjectId aId, bId;
AcDbLine* pLineA = new AcDbLine;
pLineA->setDatabaseDefaults(pDb);
er = pLineA->setStartPoint(AcGePoint3d(1, 1, 0));
if (er != Acad::eOk)
{
acutPrintf(_T("pLineA->setStartPoint Field.\n"));
return er;
}
pLineA->setEndPoint(AcGePoint3d(2, 1, 0));
er = addToModelSpace(aId, pLineA);
if (er != Acad::eOk)
{
acutPrintf(_T("addToModelSpace Field.\n"));
return er;
}
acutPrintf(_T("直线A为%lx从1,1点到2,1点。\n"),pLineA->objectId());
AcDbLine* pLineB = new AcDbLine;
pLineB->setDatabaseDefaults(pDb);
er = pLineB->setStartPoint(AcGePoint3d(1, 2, 0));
if (er != Acad::eOk)
{
acutPrintf(_T("pLineB->setStartPoint Field.\n"));
return er;
}
pLineB->setEndPoint(AcGePoint3d(2, 2, 0));
er = addToModelSpace(bId, pLineB);
if (er != Acad::eOk)
{
acutPrintf(_T("addToModelSpace Field.\n"));
return er;
}
acutPrintf(_T("直线B为%lx从1,2点到2,2点。\n"),pLineB->objectId());
/*
打开命名对象词典,检查是否有一个关键字为"ASDK_DICT"的实体。
如果没有,创建一个词典并加上它。
*/
AcDbDictionary* pNamedObj;
AcDbDictionary* pNameList;
er = pDb->getNamedObjectsDictionary(pNamedObj, AcDb::kForWrite);
if (er != Acad::eOk)
{
acutPrintf(_T("pDb->getNamedObjectsDictionary Field.\n"));
return er;
}
if (pNamedObj->getAt(_T("ASDK_DICT"), (AcDbObject*&)pNameList, AcDb::kForWrite) == Acad::eKeyNotFound)
{
pNameList = new AcDbDictionary;
AcDbObjectId dictId;
pNamedObj->setAt(_T("ASDK_DICT"), pNameList, dictId);
}
pNamedObj->close();
// 为直线A创建AsdkObjectToNotify
CAsdkObjectReactor* pObj = new CAsdkObjectReactor; // 创建CObjectReactor类的实例
pObj->eLinkage(bId);
AcDbObjectId objId;
if ((pNameList->getAt(_T("object_to_notify_A"), objId)) == Acad::eKeyNotFound)
{
pNameList->setAt(_T("object_to_notify_A"), pObj, objId); // 将CObjectReactor的实例添加到数据库
pObj->close();
}
else
{
delete pObj;
acutPrintf(_T("object_to_notify_A已存在.\n"));
}
// 在直线A和AsdkObjectToNotify之间设置永久反应器链接
pLineA->addPersistentReactor(objId);
pLineA->close();
// 为直线B创建AsdkObjectToNotify
pObj = new CAsdkObjectReactor;
pObj->eLinkage(aId);
if ((pNameList->getAt(_T("object_to_notify_B"), objId)) == Acad::eKeyNotFound)
{
pNameList->setAt(_T("object_to_notify_B"), pObj, objId);
pObj->close();
}
else
{
delete pObj;
acutPrintf(_T("object_to_notify_B已存在.\n"));
}
// 在直线B和AsdkObjectToNotify之间设置永久反应器链接
pLineB->addPersistentReactor(objId);
pLineB->close();
return Acad::eOk;
}
ARX工具栏建立新命令,调用函数assoclines()即可。