对象反应器的使用

本例是AutoCAD ObjectARX2000 开发技术指南中的例子,但稍加改变。

用向导建立工程。

AsdkObjectReactor.h文件:

#pragma once
#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()即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值