В каких случаях следует блокировать документ
Если ваш код выполняется в так называемом контексте документа, то нет необходимости блокировать документ. Если ваша команда зарегистрирована при помощи функции acedDefun() или при помощи метода acedRegCmds->addCommand() без флага ACRX_CMD_SESSION ( CommandFlags.Session в .NET), ваш код будет выполняться в контексте документа. В этом контексте AutoCAD блокирует текущий документ перед выполнением команды и разблокирует по её завершению. Если у вас есть необходимость получать доступ к другим документам в контексте документа, то вам придётся блокировать эти документы самостоятельно. В этом случае вы должны зарегистрировать свою команду в контексте приложения, используя флаг ACRX_CMD_SESSION ( CommandFlags.Session в .NET).
В любом другом контексте вы должны блокировать документ, который собираетесь модифицировать. Это значит, что вы должны блокировать документ если ваша команда зарегистрирована для выполнения в контексте приложения. Это будет и при использовании флага the ACRX_CMD_SESSION в методе addCommand(), и в обработчике сообщений немодального диалога в случае если вы модифицируете объекты базы данных документа. Если ваше приложение создаёт COM-интерфейс или вы обеспечиваете методы/свойства, которые могут модифицировать объекты базы, вы тоже должны заблокировать документ..
Ниже небольшие примеры ARX и .NET приложений, которые требуют блокировки документов.
ObjectARX:
- // определим команду с флагом ACRX_CMD_SESSION
- acedRegCmds->addCommand(L"ADSK",L"MyTest",L"MyTest",ACRX_CMD_MODAL | ACRX_CMD_SESSION , MyTestARX);
- // добавим окружность в неактивый документ
- static void MyTestARX()
- {
- AcApDocument* pActiveDoc = acDocManager-
- >mdiActiveDocument();
- AcApDocumentIterator *pIter =
- acDocManager->newAcApDocumentIterator();
- // сначала выберем неактивный документ
- AcApDocument *pDocToDo = NULL;
- for (;!pIter->done() ;
- pIter->step() )
- {
- if(pIter->document() != pActiveDoc)
- {
- pDocToDo = pIter->document() ;
- break;
- }
- }
- delete pIter;
- // блокируем документ
- // по-умолчанию, the DocLockMode
- // разрешает запись.
- Acad::ErrorStatus es =
- acDocManager->lockDocument(
- pDocToDo
- /* AcAp::DocLockMode = AcAp::kWrite */ );
- if (es != Acad::eOk)
- {
- // не получилось заблокировать
- return;
- }
- // коды возврата:
- // 1. Acad::eOk если удалось
- // заблокировать.
- // 2. Acad::eLockChangeInProgress
- // Если блокировка документа была предпринята
- // из функции обратного вызова реактора изменения
- // блокировки.
- // Вы не можете "вкладывать" запросы блокировки.
- // 3. Acad::eVetoed
- // Если была запрещена попытка блокировки из
- // другого приложения
- // 4. Acad::eNoDocument
- // Если pDoc равен NULL.
- AcDbDatabase* pDb = pDocToDo->database();
- // получаем таблицу блоков
- AcDbBlockTable *pBlockTable;
- es = pDb->getBlockTable(pBlockTable,
- AcDb::kForRead);
- if (es != Acad::eOk)
- {
- return;
- }
- // получаем пространство модели
- AcDbBlockTableRecord *pBlockTableRec;
- es = pBlockTable->
- getAt(ACDB_MODEL_SPACE, pBlockTableRec,
- AcDb::kForWrite);
- if (es != Acad::eOk)
- {
- pBlockTable->close();
- return;
- }
- pBlockTable->close();
- // создаём новый примитив
- AcDbCircle *pCircle =
- new AcDbCircle(AcGePoint3d(0,0,0),
- AcGeVector3d(0,0,1),100);
- // добавляем примитив к пространству модели
- AcDbObjectId objId;
- pBlockTableRec->appendAcDbEntity(objId, pCircle);
- // закрываем примитив
- pCircle->close();
- // закрываем пространство модели
- pBlockTableRec->close();
- // разблокируем документ
- es = acDocManager->unlockDocument(pDocToDo);
- if(es == Acad::eOk)
- {
- // успешно обработали один документ
- }
- }
.NET
- using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
- // изменим значение 'TILEMODE' для всех открытых документов, кроме
- // активного в момент запуска команды
- [CommandMethod("MyTest", CommandFlags.Session)]
- public void MyTestNet()
- {
- foreach (Document doc in
- AcadApp.DocumentManager)
- {
- if (doc != AcadApp.DocumentManager.MdiActiveDocument)
- {
- // переключаем активный документ
- AcadApp.DocumentManager.MdiActiveDocument = doc;
- // Если мы не заблокируем этот документ
- // тогда следующий код не сделает ничего
- // хотя "doc.Database.TileMode =
- // !doc.Database.TileMode;"
- // может даже прервать работу AutoCAD
- // Если вы заблокируете документ всё должно сработать хорошо
- using (doc.LockDocument())
- {
- short tm =
- (short)AcadApp.GetSystemVariable("TILEMODE");
- AcadApp.SetSystemVariable("TILEMODE",
- (tm + 1) % 2);
- }
- break;
- }
- }
- }
Источник: http://adndevblog.typepad.com/autocad/2012/05/when-to-lock-the-document.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=262
Опубликовано 16.10.2013Отредактировано 29.01.2014 в 18:48:37