[整理]
默认状态下AutoCAD2004是多文档应用程序,系统变量SDI=0,
acdbHostApplicationServices()->workingDatabase();
不是指一个文档,而是多个文档.当使用模态对话框时,这个对话框资源属于唯一的一个文档,所以不会产生错误;
而使用非模态对话框时,对话框资源不属于任何一个文档,如果修改往数据库(写操作),就会导致AutoCAD异常.
解决的方法是:
使用非模态对话框时要显式地管理文档的状态,当然,如果不需要多文档,则将系统变量SDI设为1也能解决非模态对话框的问题,
一般以写的方式操作实体时,要将当前文档锁定,操作结束后,解锁文档,而以读的方式打开对象,不需要锁定文档:
acDocManager->lockDocument(acDocManager->curDocument(), AcAp::kWrite, NULL, NULL, true);
这个函数的使用是锁定文档以便访问它们的资源,这些资源包括与文档相关联的的数据库对象(AcDbDatabases objects associated with a document),以及这些数据库中的实体对象(AcDbObject objects),还有数据库常驻系统变量(all AcDbDatabase resident system variables).
它还包括了基于系统变量的所有文档(all document based system variables),及与文档关联的事务管理器(the Transaction Manager associated with a document).文档在以AcDb::kForRead打开一个AcDbObject对象时不需要锁定,读取系统变量时也不需要锁定文档.
...
acDocManager->unlockDocument(acDocManager->curDocument());
示例:
void lockDocument_Test()
{
AcGePoint3d start(0.0,0.0,0.0), end(10.0,10.0,0.0);
AcDbLine *line = new AcDbLine(start, end);
AcDbBlockTable *pBlockTable;
// 锁定当前文档
acDocManager->lockDocument(acDocManager->curDocument(), AcAp::kWrite, NULL, NULL, true);
acDocManager->curDocument()->database()->getBlockTable(pBlockTable, AcDb::kForRead);
//acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRec;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRec, AcDb::kForWrite);
pBlockTable->close();
AcDbObjectId objId;
pBlockTableRec->appendAcDbEntity(objId, line);
line->close();
pBlockTableRec->close();
// 运行完解锁文档
acDocManager->unlockDocument(acDocManager->curDocument());
}