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前都关闭释放了。故后面给智能指针加个作用域,出作用域后析构释放就好了