ADN Open CIS
Сообщество программистов Autodesk в СНГ

16/10/2013

В каких случаях следует блокировать документ

Если ваш код выполняется в так называемом контексте документа, то нет необходимости блокировать документ. Если ваша команда зарегистрирована при помощи функции 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:

Код - C++: [Выделить]
  1. // определим команду с флагом ACRX_CMD_SESSION
  2. acedRegCmds->addCommand(L"ADSK",L"MyTest",L"MyTest",ACRX_CMD_MODAL | ACRX_CMD_SESSION , MyTestARX);
  3. // добавим окружность в неактивый документ
  4. static void MyTestARX()
  5. {
  6.   AcApDocument* pActiveDoc = acDocManager-
  7.                       >mdiActiveDocument(); 
  8.    AcApDocumentIterator *pIter =
  9.         acDocManager->newAcApDocumentIterator();
  10.  
  11.    // сначала выберем неактивный документ
  12.   AcApDocument *pDocToDo = NULL;
  13.    for (;!pIter->done() ;
  14.        pIter->step() )          
  15.    {             
  16.       if(pIter->document() != pActiveDoc)
  17.       {
  18.           pDocToDo = pIter->document() ;
  19.           break;
  20.       }
  21.    }
  22.  
  23.    delete pIter;
  24.  
  25.   // блокируем документ
  26.   // по-умолчанию, the DocLockMode
  27.   // разрешает запись.
  28.   Acad::ErrorStatus es =
  29.       acDocManager->lockDocument(
  30.       pDocToDo
  31.       /* AcAp::DocLockMode = AcAp::kWrite */ );
  32.  
  33.       if (es != Acad::eOk)        
  34.       {    
  35.          // не получилось заблокировать     
  36.           return;
  37.       }
  38.  
  39.       // коды возврата:
  40.       //  1. Acad::eOk если удалось
  41.       //     заблокировать.
  42.       //  2. Acad::eLockChangeInProgress
  43.       //    Если блокировка документа была предпринята
  44.       //    из функции обратного вызова реактора изменения
  45.       //    блокировки.
  46.       //    Вы не можете "вкладывать" запросы блокировки.
  47.       // 3. Acad::eVetoed
  48.       //    Если была запрещена попытка блокировки из
  49.       //    другого приложения
  50.       // 4. Acad::eNoDocument
  51.       //      Если pDoc равен NULL.  
  52.  
  53.        AcDbDatabase* pDb = pDocToDo->database();
  54.  
  55.        // получаем таблицу блоков
  56.       AcDbBlockTable *pBlockTable;
  57.       es = pDb->getBlockTable(pBlockTable,
  58.                              AcDb::kForRead);
  59.  
  60.       if (es != Acad::eOk)
  61.       {
  62.            return;
  63.       }
  64.  
  65.       // получаем пространство модели
  66.       AcDbBlockTableRecord *pBlockTableRec;
  67.       es = pBlockTable->
  68.           getAt(ACDB_MODEL_SPACE, pBlockTableRec,
  69.           AcDb::kForWrite);
  70.  
  71.       if (es != Acad::eOk)
  72.       {
  73.           pBlockTable->close();
  74.            return;
  75.       }
  76.  
  77.      pBlockTable->close();
  78.  
  79.      // создаём новый примитив
  80.      AcDbCircle *pCircle =
  81.          new AcDbCircle(AcGePoint3d(0,0,0),
  82.          AcGeVector3d(0,0,1),100);
  83.  
  84.      // добавляем примитив к пространству модели
  85.      AcDbObjectId objId;
  86.      pBlockTableRec->appendAcDbEntity(objId, pCircle);
  87.  
  88.      // закрываем примитив
  89.      pCircle->close();
  90.  
  91.      // закрываем пространство модели
  92.      pBlockTableRec->close();
  93.  
  94.      // разблокируем документ
  95.      es = acDocManager->unlockDocument(pDocToDo);
  96.  
  97.      if(es == Acad::eOk)
  98.      {    
  99.          // успешно обработали один документ
  100.      }    
  101. }

 

.NET

Код - C#: [Выделить]
  1. using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
  2. // изменим значение 'TILEMODE' для всех открытых документов, кроме
  3. // активного в момент запуска команды
  4. [CommandMethod("MyTest", CommandFlags.Session)]
  5. public void MyTestNet()
  6. {
  7.     foreach (Document doc in
  8.         AcadApp.DocumentManager)
  9.     {
  10.         if (doc != AcadApp.DocumentManager.MdiActiveDocument)
  11.         {
  12.             // переключаем активный документ
  13.             AcadApp.DocumentManager.MdiActiveDocument = doc;
  14.  
  15.             // Если мы не заблокируем этот документ
  16.             // тогда следующий код не сделает ничего
  17.             // хотя "doc.Database.TileMode =
  18.             // !doc.Database.TileMode;" 
  19.             // может даже прервать работу AutoCAD      
  20.  
  21.             // Если вы заблокируете документ всё должно сработать хорошо
  22.             using (doc.LockDocument())
  23.             {
  24.                 short tm =
  25.                 (short)AcadApp.GetSystemVariable("TILEMODE");
  26.                 AcadApp.SetSystemVariable("TILEMODE",
  27.                                        (tm + 1) % 2);
  28.             }
  29.             break;
  30.         }
  31.     }
  32. }

Источник: 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