【cad二次开发笔记】长事务测试案例(使用智能指针)

1.长事务测试方法


void longTransactionTest()
{
		Acad::ErrorStatus es;
	AcDbObjectId transId;
	AcDbDatabase * pDb=NULL;
	struct resbuf *rb=NULL;
	rb=acutNewRb(RTSTR);
	//提示让用户选择一个图形文件
	int stat=acedGetFileD(_T("Pick a drawing "),NULL,_T("dwg"),0,rb);
	//如果用户输入错误,则提示用户退出命令
	if((stat!=RTNORM)||(rb==NULL))
	{
		acutPrintf(_T("\n You must pick a drawing file."));
		return;
	}
	//获取文件名转换成字符串
	CString fname;
	{
		//使用字符串只能指针,省去后面管理删除释放字符指针
		TCHAR *lptszFileName=new TCHAR[_tcslen(rb->resval.rstring)+1];
		_tcscpy(lptszFileName,rb->resval.rstring);
		fname=lptszFileName;
		delete[] lptszFileName;
	}
	acutRelRb(rb);rb=NULL;


	// id数组,用于判断是否存在圆
	AcDbObjectIdArray objIdArray;
	//作用域,目的是为了获取读取的图形数据库中的圆的id数组后,析构智能指针对象
	{
		//打开前面选中的图形文件
		pDb=new AcDbDatabase(Adesk::kFalse);
		//如果打开失败,或者用户已经打开,返回
		es=pDb->readDwgFile(fname);
		if(es!=Acad::eOk)
		{
			acutPrintf(_T("\nSorry ,that draing is probably already open.error code:%"),acadErrorStatusText(es));
			//返回前要把前面分配的内存都清理
			delete pDb;pDb=NULL;
			return;
		}
		//获取这个图形文件的块表记录
		AcDbBlockTableRecordPointer pOtherBtRecPtr(ACDB_MODEL_SPACE,pDb,AcDb::kForRead);
		if (pOtherBtRecPtr.openStatus()!=Acad::eOk)
		{
			acutPrintf(_T("\nSorry ,get AcDbBlockTableRecord fail.error code:%s"),acadErrorStatusText(pOtherBtRecPtr.openStatus()));
			delete pDb;pDb=NULL;
			return;
		}
		//获取块表记录迭代器
		AcDbBlockTableRecordIterator * pIter=NULL;
		es=pOtherBtRecPtr->newIterator(pIter);
		if(es!=Acad::eOk)
		{
			acutPrintf(_T("\nSorry ,get AcDbBlockTableRecordIterator fail.error code:%s"),acadErrorStatusText(es));
			delete pDb;pDb=NULL;
			return;
		}

		for (pIter->start();!pIter->done();pIter->step())
		{
			//读方式获取实体
			AcDbObjectId entId;
			pIter->getEntityId(entId);
			AcDbEntityPointer pentPtr;
			es=pentPtr.open(entId,AcDb::kForRead);
			if (es!=Acad::eOk)
			{
				acutPrintf(_T("\nSorry ,open entity fail.error code:%s"),acadErrorStatusText(es));
				delete pDb;pDb=NULL;
				return;
			}
			//判断是否圆
			if (pentPtr->isKindOf(AcDbCircle::desc()))
			{
				objIdArray.append(pentPtr->objectId());
			}
		}
		delete pIter;pIter=NULL;
		if (objIdArray.isEmpty())
		{
			acutPrintf(_T("\nYou must pick a drawing file that contains circles."));
			delete pDb;pDb=NULL;
			return;
		}
	}
	//获取当前数据库块表id
	AcDbObjectId id;
	{
		//获取当前数据库和当前数据库的块表
		AcDbDatabase *pCurDb=NULL;
		pCurDb=curDoc()->database();
		if (pCurDb==NULL)
		{
			acutPrintf(_T("\nget current database fail."));
			delete pDb;pDb=NULL;
			return;
		}

		//获取当前图形数据库块表记录
		AcDbBlockTableRecordPointer pThisMsPtr(ACDB_MODEL_SPACE,pCurDb,AcDb::kForWrite);
		id =pThisMsPtr->objectId();
	}
	


	AcDbIdMapping errorMap;
	//创建长事务,这将从外部数据库中获得外部对象,传入了圆对象id数组objIdArray,仅获取圆对象。
	es=acapLongTransactionManagerPtr()->checkOut(transId,objIdArray,id,errorMap);
	ASSERT(es==Acad::eOk);

	//获取用户输入的颜色和半径
	int colorIndex;
	double radius;
	acedGetInt(_T("\n Enter color number to change entiLies to:"),&colorIndex);
	acedGetReal(_T("\nEnter circle radius :"),&radius);

	if (radius<=0)
	{
		acutPrintf(_T("\nEnter :radius can't less than 0!"));
		delete pDb;pDb=NULL;
		return;
	}
	//获取事务智能指针对象,遍历修改圆的颜色和半径,出作用域析构智能指针,否则在结束事务后 才关闭事务指针会出现错误
	{
		//获取长事务智能指针
		AcDbObjectPointer<AcDbLongTransaction> pLongTransPtr;
		es=pLongTransPtr.open(transId,AcDb::kForRead);
		if (es!=Acad::eOk)
		{
			acutPrintf(_T("\nEnter :open AcDbLongTransaction fail!error code:%s"),acadErrorStatusText(es));
			delete pDb;pDb=NULL;
			return;
		}

		//创建长事务迭代器
		AcDbLongTransWorkSetIterator *pWorkSetlter=NULL;
		pLongTransPtr->newWorkSetIterator(pWorkSetlter);
		
		//遍历修改圆
		for (pWorkSetlter->start();!pWorkSetlter->done();pWorkSetlter->step())
		{	
			//获取实体,修改圆的颜色和半径
			AcDbEntityPointer pEntPtr;
			pEntPtr.open(pWorkSetlter->objectId(),AcDb::kForWrite);
			pEntPtr->setColorIndex(colorIndex);
			((AcDbCircle*)pEntPtr.object())->setRadius(radius);
		}
		delete pWorkSetlter;pWorkSetlter=NULL;
	}

	//暂停,使用户能看得到圆的颜色和半径改变的变化
	TCHAR str[132];
	acedGetString(0,_T("\nSee the new colors and radius.Press return to back"),str);
	//将实体放回原图形数据库中
	acapLongTransactionManagerPtr()->checkIn(transId,errorMap);

	pDb->saveAs(fname);

	delete pDb;pDb=NULL;
}

2.定义注册命令

acedRegCmds->addCommand(_T("LONGTRANSTEST"),_T("LONGTRANS"),_T("LONGTRANS"),ACRX_CMD_MODAL,longTransactionTest);

3.测试步骤

(1)启动运行打开cad后,随意绘制几个圆,保存dwg文件,关闭当前dwg

(2)点击文件=》新建=》确定

(3)在命令输入:LONGTRANS,在弹出窗中选择第1步中保存的dwg文件

 

(4)关闭不保存当前临时文档,打开原文档,发现图形圆已修改为刚刚操作后的圆

4.总结:试验过程中出现的问题

(1)通过checkOut(transId,objIdArray,id,errorMap);获取事务id    transId时,无法获取。不使用智能指针时,正常获取transId。

个人理解,原因是读取原dwg文件时,获取块表的智能指针,迭代获取圆实体对象id(objIdArray)后,块表指针没析构。然后又获取当前数据库的块表记录id(id),两者之间相互影响了(忘了匹配两个块表记录的内存是否一样了)。

(2)调用checkIn(transId,errorMap)结束后,删除pDb数据库指针后,就报错了中断了。与不使用智能指针对比发现,块表记录等指针是在checkIn前都关闭释放了。故后面给智能指针加个作用域,出作用域后析构释放就好了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值