REMOVEALLPROXY

Автор Тема: REMOVEALLPROXY  (Прочитано 94101 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Оффлайн T72Автор темы

  • ADN Club
  • Сообщений: 23
  • Карма: 4
REMOVEALLPROXY
« : 31-10-2014, 10:02:07 »
Добрый день. Скорее всего вопрос к Александру.
Хочу вызвать данную команду через acedCmdLookup но она требует параметр (Очистить список масштабов? [Да/Нет] <Да>: Д)
Как можно это обойти или только пересобирать библиотеку?
Спасибо.

Код - C# [Выбрать]
  1.         public delegate void AcRxFunctionPtr();
  2.  
  3.         [StructLayoutAttribute(LayoutKind.Sequential)]
  4.         public struct AcEdCommandStruc
  5.         {
  6.             public AcRxFunctionPtr fcnAddr;
  7.             public int flags;
  8.             public System.IntPtr app;
  9.             public System.IntPtr hResHandle;
  10.             public System.IntPtr cmd;
  11.         }
  12.  
  13.         [StructLayoutAttribute(LayoutKind.Sequential)]
  14.         public struct HINSTANCE__
  15.         {
  16.             public int unused;
  17.         }
  18.  
  19.         [DllImportAttribute("acad.exe", EntryPoint = "acedCmdLookup")]
  20.         public static extern int acedCmdLookup([InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string cmdStr,
  21.             int globalLookup,
  22.             ref AcEdCommandStruc retStruc,
  23.             int skipUndef);
  24.  
  25.         public  static bool LookupCommand(string command)
  26.         {
  27.             AcEdCommandStruc cs = new AcEdCommandStruc();
  28.             int res = acedCmdLookup(command, 1, ref cs, 1);
  29.  
  30.             if (res != 0)
  31.                 cs.fcnAddr.Invoke();
  32.             else
  33.                 return false;
  34.  
  35.             return true;
  36.         }
  37.  
« Последнее редактирование: 31-10-2014, 14:48:27 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #1 : 31-10-2014, 15:02:42 »
Приветствую на форуме!
Хочу вызвать данную команду через acedCmdLookup
Зачем? Есть куча других способов для этого. Кстати, команда _REMOVEALLPROXY - модальная, работающая только с текущим/активным чертежом, по этой причине не блокирует его и соответственно прямым вызовом может вызываться только из определенных контекстов.
Почему не вызвать её через Editor.RunCommand (или P/Invoke acedCmd) в версиях до 2014 и Editor.Command в версиях начиная с 2015?
Самый же радикальный способ переписать её с чистого ObjectARX на AutoCAD .NET API, что вполне возможно. Если хочешь, я выложу исходник на C++ и дам комментарии как его переделать на C#. Там со всеми обработками ошибок около сотни строк. Ну и если ты обязуешься выложить соответствующий исходник на C#. :) 
« Последнее редактирование: 31-10-2014, 16:05:39 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн T72Автор темы

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #2 : 31-10-2014, 15:59:02 »
Цитировать
Есть куча других способов для этого?
Возможно :)

Ее конкретно возможно и можно но есть другие команды которые я не могу использовать через RunCommand так как он не ждет окончания, acedCmd не работает с CommandFlags.Session
Если переводить на .Net тогда и EXPLODEALLPROXY нужно.
А перевести можно и исходники выложить. Буду ждать. Спасибо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #3 : 31-10-2014, 18:33:40 »
но есть другие команды которые я не могу использовать через RunCommand так как он не ждет окончания
Ждет. Ты путаешь RunCommand с SendCommand. RunCommand - это непубличный метод класса Editor, который нужно вызвать хитрым способом.
Код - C# [Выбрать]
  1. // (c) 2013  Tony Tanzillo
  2. public static class EditorInputExtensionMethods
  3. {
  4.    public static PromptStatus Command( this Editor editor, params object[] args )
  5.    {
  6.       if( editor == null )
  7.          throw new ArgumentNullException( "editor" );
  8.       return runCommand( editor, args );
  9.    }
  10.  
  11.    static Func<Editor, object[], PromptStatus> runCommand = GenerateRunCommand();
  12.  
  13.    static Func<Editor, object[], PromptStatus> GenerateRunCommand()
  14.    {
  15.       MethodInfo method = typeof( Editor ).GetMethod( "RunCommand",
  16.          BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public );
  17.       var instance = Expression.Parameter( typeof( Editor ), "instance" );
  18.       var args = Expression.Parameter( typeof( object[] ), "args" );
  19.       return Expression.Lambda<Func<Editor, object[], PromptStatus>>(
  20.          Expression.Call( instance, method, args ), instance, args )
  21.             .Compile();
  22.    }
  23. }
  24. // Пример использования:
  25. //  var doc = Application.DocumentManager.MdiActiveDocument;
  26. //  var ed = doc.Editor;
  27. //  ed.Command("_REMOVEALLPROXY","_Y");

acedCmd не работает с CommandFlags.Session
Мне не очень понятно зачем тебе запускать команду из контекста приложения. Но если даже это и нужно, то делается это просто: делаешь фиктивную команду с флагом Modal, которую запускаешь из контекста приложения через AcadDocument.SendCommand или Document.SendStringToExecute. А все остальные действия выполняешь именно в этой команде.


« Последнее редактирование: 05-11-2014, 12:55:04 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #4 : 31-10-2014, 18:41:49 »
А перевести можно и исходники выложить. Буду ждать. Спасибо.
Код - C++ [Выбрать]
  1. typedef void __cdecl ACEDRESETSCALELIST(bool,bool,class AcDbDatabase *);
  2. static void RemoveAllProxy(void)
  3. {
  4.   Acad::ErrorStatus es;
  5.   AcDbDatabase *pDb = acdbCurDwg(); // Текущая база
  6.   AcDbHandle firstHandle = pDb->blockTableId().handle(); // Первая метка объекта - метка таблицы блоков
  7.   AcDbHandle lastHandle = pDb->handseed(); // Следующая после последней метки
  8.   int nObjects = pDb->approxNumObjects(); // Приблизительное количество объектов в базе
  9.   ACHAR buf[256],buf1[256]; lastHandle.getIntoAsciiBuffer(buf);
  10.   __int64 iLast = 0; swscanf(buf,_T("%I64x"),&iLast);
  11.   firstHandle.getIntoAsciiBuffer(buf1);
  12.   __int64 iFirst = 0; swscanf(buf1,_T("%I64x"),&iFirst);
  13.   __int64 nProxyTotal = 0, nProxyEntityTotal = 0;
  14.   acutPrintf(_T("\nПервая метка объекта: <%s>, последняя метка объекта: <%s>"),buf1,buf);
  15.   AcDbObjectIdArray ids;
  16.   // Массив меток заблокированных слоёв - их придётся временно разблокировать
  17.   AcDbObjectIdArray idsLockedLayers;
  18.  
  19.  for (__int64 i = iFirst; i < iLast && nObjects > 0; i++) {
  20.     AcDbHandle h(i);
  21.     AcDbObjectId id = AcDbObjectId::kNull;
  22.     if ((es = pDb->getAcDbObjectId(id,false,h)) == Acad::eOk) { // Получаем ObjectId по Handle
  23.       AcDbObjectPointer<AcDbObject> pObj(id,AcDb::kForRead);
  24.       if (pObj.openStatus() == Acad::eOk && pObj->isAProxy()) {
  25.         nProxyTotal++;
  26.         ids.append(id);
  27.         AcDbEntity *pEnt = AcDbEntity::cast(pObj.object());
  28.         if (pEnt) {
  29.           nProxyEntityTotal++;
  30.           AcDbObjectId idLayer = pEnt->layerId();
  31.           if (!idsLockedLayers.contains(idLayer)) {
  32.             AcDbLayerTableRecordPointer pLayer(idLayer,AcDb::kForWrite);
  33.             if (pLayer.openStatus() == Acad::eOk) {
  34.               if (pLayer->isLocked()) {
  35.                 pLayer->setIsLocked(false);
  36.                 idsLockedLayers.append(idLayer);
  37.               }
  38.             }
  39.           }
  40.         }
  41.       }
  42.       nObjects--;
  43.     }
  44.   }
  45.  
  46.  wsprintf(buf,_T("\nВсего найдено proxy-объектов: %I64d. Из них proxy-примитивов: %I64d."),nProxyTotal,nProxyEntityTotal); acutPrintf(_T("%s"),buf);
  47.  
  48.  ACEDRESETSCALELIST *acedResetScaleList = NULL;
  49.  HMODULE hAcad = LoadLibraryA("accore.dll");
  50.  if (!hAcad) hAcad = LoadLibraryA("acad.exe");
  51.  
  52.  if (hAcad != NULL) {
  53.  #ifdef _WIN64
  54.    acedResetScaleList = (ACEDRESETSCALELIST *)GetProcAddress(hAcad,"?acedResetScaleList@@YAX_N0PEAVAcDbDatabase@@@Z");
  55.  #else // _WIN64
  56.    acedResetScaleList = (ACEDRESETSCALELIST *)GetProcAddress(hAcad,"?acedResetScaleList@@YAX_N0PAVAcDbDatabase@@@Z");
  57.  #endif
  58.    if (acedResetScaleList) {
  59.      ACHAR res[256];
  60.      acedInitGet(0,_T("Да Нет Yes No _ Yes No Yes No"));
  61.      int rc = acedGetKword(_T("\nОчистить список масштабов? [Да/Нет] <Да>: "),res);
  62.      if (rc == RTNONE || (rc == RTNORM && !wcsicmp(res,_T("Yes")))) {
  63.        acedResetScaleList(true,false,acdbCurDwg());
  64.      }
  65.    }
  66.    FreeLibrary(hAcad);
  67.  }
  68.  
  69.   int nProxyDeleted = 0;
  70.   int nProxyEntityDeleted = 0;
  71.   for (int j=0; j < ids.length(); j++) {
  72.     AcDbObjectPointer<AcDbObject> pObj(ids[j],AcDb::kForWrite);
  73.     if (pObj.openStatus() == Acad::eOk) {
  74.       if (pObj->erase(true) == Acad::eOk) {
  75.         nProxyDeleted++;
  76.         if (AcDbEntity::cast(pObj.object())) {
  77.           nProxyEntityDeleted++;
  78.         }
  79.       } else {
  80.         AcDbObject *ppObj; pObj.release(ppObj);
  81.         if (AcDbEntity::cast(ppObj)) {
  82.           AcDbLine *pRep = new AcDbLine();
  83.           if (ppObj->handOverTo(pRep,false,false) == Acad::eObjectToBeDeleted) {
  84.             pRep->erase(); pRep->close();
  85.             delete ppObj;
  86.             nProxyDeleted++;
  87.             nProxyEntityDeleted++;
  88.           } else {
  89.             delete pRep;
  90.           }
  91.         } else {
  92.           AcDbDictionary *pRep = new AcDbDictionary();
  93.           if (ppObj->handOverTo(pRep,false,false) == Acad::eObjectToBeDeleted) {
  94.             pRep->erase(); pRep->close();
  95.             delete ppObj;
  96.             nProxyDeleted++;
  97.           } else {
  98.             delete pRep;
  99.           }
  100.         }
  101.       }
  102.     }
  103.   }
  104.  
  105.   for (int i = 0; i < idsLockedLayers.length(); i++)  {
  106.     AcDbLayerTableRecordPointer pLayer(idsLockedLayers[i],AcDb::kForWrite);
  107.     if (pLayer.openStatus() == Acad::eOk) {
  108.       pLayer->setIsLocked(true);
  109.     }
  110.   }
  111.   acutPrintf(_T("\nВсего удалено proxy-объектов: %d. Из них proxy-примитивов: %d."),nProxyDeleted,nProxyEntityDeleted);
  112.   acutPrintf(_T("\nДля проверки ошибок выполните команду _AUDIT"));
  113. }
« Последнее редактирование: 06-11-2014, 01:23:11 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #5 : 31-10-2014, 18:55:52 »
Код - C++ [Выбрать]
  1. enum ExplodeStatus {
  2.   success   =  0,
  3.   parmerr   = -1,
  4.   openerr   = -2,
  5.   explerr   = -3,
  6.   appenderr = -4,
  7.   eraseerr  = -5
  8. };
  9. static int ExplodeProxyInBTR(AcDbObjectId blkId, long &proxy, long &exploded);
  10. static void ExplodeAllProxy(void)
  11. {
  12.   AcDbObjectIdArray idsLockedLayers;
  13.   {
  14.     AcDbLayerTablePointer pTblBlk(acdbCurDwg()->layerTableId(),AcDb::kForRead);
  15.     AcDbLayerTableIterator *pIter = NULL;
  16.     if (pTblBlk->newIterator(pIter) == Acad::eOk && pIter) {
  17.       for (pIter->start(); !pIter->done(); pIter->step()) {
  18.         AcDbObjectId layId;
  19.         if (pIter->getRecordId(layId) == Acad::eOk) {
  20.           AcDbLayerTableRecordPointer pLayer(layId,AcDb::kForWrite);
  21.           if (pLayer.openStatus() == Acad::eOk) {
  22.             if (pLayer->isLocked()) {
  23.               pLayer->setIsLocked(false);
  24.               idsLockedLayers.append(layId);
  25.             }
  26.           }
  27.         }
  28.       }
  29.       delete pIter;
  30.     }
  31.   }
  32.  
  33.   AcDbBlockTablePointer pTblBlk(acdbCurDwg()->blockTableId(),AcDb::kForRead);
  34.   if (pTblBlk.openStatus() == Acad::eOk) {
  35.     AcDbBlockTableIterator *pIter = NULL;
  36.     if (pTblBlk->newIterator(pIter) == Acad::eOk && pIter) {
  37.       AcDbObjectIdArray blkIds;
  38.       for (pIter->start(); !pIter->done(); pIter->step()) {
  39.         AcDbObjectId blkId;
  40.         if (pIter->getRecordId(blkId) == Acad::eOk) {
  41.           blkIds.append(blkId);
  42.         }
  43.       }
  44.       delete pIter;
  45.       pTblBlk->close();
  46.       long exploded = 0, proxy = 0;
  47.       for (int i=0; i < blkIds.length(); i++) {
  48.         if (ExplodeProxyInBTR(blkIds[i],proxy,exploded) != success) {
  49.           acutPrintf(_T("\nОшибка расчленения ACAD_PROXY_ENTITY!"));
  50.         }
  51.       }
  52.       acutPrintf(_T("\nУдалено Proxy: %d Новых объектов: %d"), proxy, exploded);
  53.     } else {
  54.       acutPrintf(_T("\nНе могу создать итератор для таблицы блоков!"));
  55.     }
  56.   } else {
  57.     acutPrintf(_T("\nНе могу открыть таблицу блоков!"));
  58.   }
  59.   {
  60.     for (int i = 0; i < idsLockedLayers.length(); i++) {
  61.       AcDbLayerTableRecordPointer pLayer(idsLockedLayers[i],AcDb::kForWrite);
  62.       if (pLayer.openStatus() == Acad::eOk) {
  63.         pLayer->setIsLocked(true);
  64.       }
  65.     }
  66.   }
  67. }
  68. static int ExplodeProxyInBTR(AcDbObjectId blkId, long &proxy, long &exploded)
  69. {
  70.   Acad::ErrorStatus es = Acad::eOk;
  71.   AcDbBlockTableRecordIterator *pBlkIter = NULL;
  72.  
  73.   // Массив в который добавляются расчлененные proxy
  74.   AcDbVoidPtrArray aExplProxy;
  75.  
  76.   if (!blkId.isNull()) {
  77.     AcDbBlockTableRecordPointer pBtr(blkId,AcDb::kForRead);
  78.     if (pBtr.openStatus() != Acad::eOk) {
  79.       return openerr;
  80.     }
  81.     if (pBtr->newIterator(pBlkIter) != Acad::eOk || !pBlkIter) {
  82.       return openerr;
  83.     }
  84.  
  85.     for (pBlkIter->start(); !pBlkIter->done(); pBlkIter->step()) {
  86.       AcDbEntity *pEnt = NULL;
  87.       if (pBlkIter->getEntity(pEnt,AcDb::kForWrite) == Acad::eOk && pEnt) {
  88.         AcDbProxyEntity *pProxy = AcDbProxyEntity::cast(pEnt);
  89.         if (pProxy && (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics ||
  90.                        pProxy->graphicsMetafileType() == AcDbProxyEntity::kBoundingBox)) {
  91.           if (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics) {
  92.             pProxy->explode(aExplProxy);
  93.             proxy++;
  94.             if (pProxy->erase() != Acad::eOk) {
  95.               AcDbLine *pLine = new AcDbLine();
  96.               if (pProxy->handOverTo(pLine,false,false) == Acad::eObjectToBeDeleted) {
  97.                 pLine->erase(); pLine->close();
  98.                 delete pProxy;
  99.                 continue;
  100.               }
  101.             }
  102.           } else {
  103.             AcDbExtents ext;
  104.             if (pProxy->getGeomExtents(ext) == Acad::eOk) {
  105.               AcGePoint3dArray arr;
  106.               arr.append(ext.minPoint());
  107.               arr.append(AcGePoint3d(ext.minPoint().x,ext.maxPoint().y,ext.minPoint().z));
  108.               arr.append(AcGePoint3d(ext.maxPoint().x,ext.maxPoint().y,ext.minPoint().z));
  109.               arr.append(AcGePoint3d(ext.maxPoint().x,ext.minPoint().y,ext.minPoint().z));
  110.               AcDb3dPolyline *pPline = new AcDb3dPolyline(AcDb::k3dSimplePoly,arr,Adesk::kTrue);
  111.               aExplProxy.append(pPline);
  112.               pPline->setLayer(pProxy->layerId());
  113.               pPline->setLinetype(pProxy->linetypeId());
  114.               pPline->setColor(pProxy->color());
  115.             }
  116.             proxy++;
  117.             if (pProxy->erase() != Acad::eOk) {
  118.               AcDbLine *pLine = new AcDbLine();
  119.               if (pProxy->handOverTo(pLine,false,false) == Acad::eObjectToBeDeleted) {
  120.                 pLine->erase(); pLine->close();
  121.                 delete pProxy;
  122.                 continue;
  123.               }
  124.             }
  125.           }
  126.         }
  127.         pEnt->close();
  128.       }
  129.     }
  130.     exploded += aExplProxy.length();
  131.     delete pBlkIter;
  132.     AcDbObjectIdArray idsRef;
  133.     pBtr->getBlockReferenceIds(idsRef);
  134.  
  135.     if (aExplProxy.length() > 0) {
  136.       es = pBtr->upgradeOpen();
  137.       if (es == Acad::eOk || es == Acad::eWasOpenForWrite) {
  138.         for (int i=0; i < aExplProxy.length(); i++) {
  139.           AcDbEntity *pEnt = static_cast<AcDbEntity *>(aExplProxy[i]);
  140.           if (pEnt) {
  141.             Acad::ErrorStatus es_curr;
  142.             es_curr = pBtr->appendAcDbEntity(pEnt);
  143.             if (es_curr != Acad::eOk) {
  144.               delete (AcDbEntity *)aExplProxy[i];
  145.             } else {
  146.               pEnt->close();
  147.             }
  148.           }
  149.         }
  150.       }
  151.  
  152.       pBtr->close();
  153.  
  154.       for (int i=0; i < idsRef.length(); i++) {
  155.         AcDbObjectPointer<AcDbBlockReference> pRef(idsRef[i],AcDb::kForWrite);
  156.         if (pRef.openStatus() == Acad::eOk) {
  157.           pRef->recordGraphicsModified();
  158.         }
  159.       }
  160.     }
  161.     return success;
  162.   } else {
  163.     return openerr;
  164.   }
  165. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн T72Автор темы

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #6 : 05-11-2014, 14:45:08 »
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. #if CORE
  7. using AcAp = Autodesk.AutoCAD.ApplicationServices.Core;
  8. #else
  9. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  10. #endif
  11. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  12. using AcEd = Autodesk.AutoCAD.EditorInput;
  13. using AcGe = Autodesk.AutoCAD.Geometry;
  14. using Autodesk.AutoCAD.DatabaseServices;
  15. using Autodesk.AutoCAD.Geometry;
  16.  
  17. namespace ImplementLink
  18. {
  19.     public static class Acad
  20.     {
  21.         #region Static Properties
  22.  
  23.         public static Autodesk.AutoCAD.ApplicationServices.Document Document
  24.         {
  25.             get { return AcAp.Application.DocumentManager.MdiActiveDocument; }
  26.         }
  27.  
  28.         public static AcDb.Database Database
  29.         {
  30.             get { return AcAp.Application.DocumentManager.MdiActiveDocument.Database; }
  31.         }
  32.  
  33.         public static AcEd.Editor Editor
  34.         {
  35.             get { return AcAp.Application.DocumentManager.MdiActiveDocument.Editor; }
  36.         }
  37.  
  38.         public static AcDb.TransactionManager TransactionManager
  39.         {
  40.             get { return AcAp.Application.DocumentManager.MdiActiveDocument.TransactionManager; }
  41.         }
  42.  
  43.         #endregion
  44.  
  45.         #region Transactional Methods
  46.  
  47.         public static T Read<T>(this AcDb.ObjectId objectId, bool openErased = false, bool forceOpenOnLockedLayer = true)
  48.             where T : AcDb.DBObject
  49.         {
  50.             return objectId.GetObject(AcDb.OpenMode.ForRead, openErased, forceOpenOnLockedLayer) as T;
  51.         }
  52.  
  53.         public static T Write<T>(this AcDb.ObjectId objectId, bool openErased = false, bool forceOpenOnLockedLayer = true)
  54.             where T : AcDb.DBObject
  55.         {
  56.             return objectId.GetObject(AcDb.OpenMode.ForWrite, openErased, forceOpenOnLockedLayer) as T;
  57.         }
  58.  
  59.         #endregion
  60.     }
  61. }
  62.  

Код - C# [Выбрать]
  1. #if CORE
  2.         public const string ACAD = "accore.dll";
  3.         public const string ACDB = "acdb19.dll";
  4. #else
  5.         public const string ACAD = "acad.exe";
  6.         public const string ACDB = "acdb18.dll";
  7. #endif
  8.  
  9. #if WIN32
  10.         [DllImport(ACAD, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedResetScaleList@@YAX_N0PAVAcDbDatabase@@@Z")]
  11.         public static extern void acedResetScaleList(bool b1, bool b2, IntPtr db);
  12. #else
  13.         [DllImport(ACAD, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedResetScaleList@@YAX_N0PEAVAcDbDatabase@@@Z")]
  14.         public static extern void acedResetScaleList(bool b1, bool b2, IntPtr db);
  15. #endif
  16.  
  17.         private static int PurgeDatabase(Database db)
  18.         {
  19.             int idCount = 0;
  20.             using (Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
  21.             using (var tr = Acad.Database.TransactionManager.StartTransaction())
  22.             {
  23.                 ObjectIdCollection idsToPurge = new ObjectIdCollection();
  24.                 RegAppTable rat = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
  25.  
  26.                 foreach (ObjectId raId in rat)
  27.                 {
  28.                     if (raId.IsValid)
  29.                     {
  30.                         idsToPurge.Add(raId);
  31.                     }
  32.                 }
  33.  
  34.                 db.Purge(idsToPurge);
  35.  
  36.                 foreach (ObjectId id in idsToPurge)
  37.                 {
  38.                     DBObject obj = tr.GetObject(id, OpenMode.ForWrite);
  39.                     obj.Erase();
  40.                 }
  41.  
  42.                 idCount = idsToPurge.Count;
  43.                 tr.Commit();
  44.             }
  45.             return idCount;
  46.         }
  47.  

Код - C# [Выбрать]
  1.         [CommandMethod("REMOVEALLPROXY", CommandFlags.Modal)]
  2.         public static void RemoveAllProxy()
  3.         {
  4.             Database db = Acad.Database;                  // Текущая база
  5.             Handle firstHandle = db.BlockTableId.Handle;  // Первая метка объекта - метка таблицы блоков
  6.             Handle lastHandle = db.Handseed;              // Следующая после последней метки
  7.             int nObjects = db.ApproxNumObjects;           // Приблизительное количество объектов в базе
  8.  
  9.             string bufferLast = lastHandle.ToString();
  10.             string bufferFirst = firstHandle.ToString();
  11.             Int64 iLast = Int64.Parse(bufferLast, System.Globalization.NumberStyles.HexNumber);
  12.             Int64 iFirst = Int64.Parse(bufferFirst, System.Globalization.NumberStyles.HexNumber); ;
  13.  
  14.             Acad.Editor.WriteMessage(
  15.                 string.Format("\nПервая метка объекта: <{0}>, последняя метка объекта: <{1}>",
  16.                 bufferFirst,
  17.                 bufferLast));
  18.  
  19.             Int64 nProxyTotal = 0;
  20.             Int64 nProxyEntityTotal = 0;
  21.             ObjectIdCollection ids = new ObjectIdCollection();
  22.             // Массив меток заблокированных слоёв - их придётся временно разблокировать
  23.             ObjectIdCollection idsLockedLayers = new ObjectIdCollection();
  24.  
  25.             using (AcAp.Application.DocumentManager.MdiActiveDocument.LockDocument())
  26.             using (var tr = Acad.TransactionManager.StartTransaction())
  27.             {
  28.                 LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  29.  
  30.                 for (Int64 i = iFirst; i < iLast && nObjects > 0; i++)
  31.                 {
  32.                     Handle h = new Handle(i);
  33.                     ObjectId id = ObjectId.Null;
  34.                     if (db.TryGetObjectId(h, out id))
  35.                     {
  36.                         try
  37.                         {
  38.                             DBObject dbObj = tr.GetObject(id, OpenMode.ForRead, true, true);
  39.                             if (dbObj != null && !dbObj.IsErased && dbObj.IsAProxy)
  40.                             {
  41.                                 nProxyTotal++;
  42.                                 ids.Add(id);
  43.                                 Entity entity = dbObj as Entity;
  44.                                 if (entity != null && entity.IsAProxy)
  45.                                 {
  46.                                     nProxyEntityTotal++;
  47.                                     ObjectId idLayer = entity.LayerId;
  48.                                     if (!idsLockedLayers.Contains(idLayer))
  49.                                     {
  50.                                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(idLayer, OpenMode.ForRead);
  51.                                         if (ltr.IsLocked)
  52.                                         {
  53.                                             ltr.IsLocked = false;
  54.                                             idsLockedLayers.Add(idLayer);
  55.                                         }
  56.                                     }
  57.                                 }
  58.                             }
  59.                             nObjects--;
  60.                         }
  61.                         catch { }
  62.                     }
  63.                 }
  64.  
  65.                 tr.Commit();
  66.  
  67.             }
  68.  
  69.             Acad.Editor.WriteMessage(string.Format("\nВсего найдено proxy-объектов: {0}. Из них proxy-примитивов: {1}.",
  70.                 nProxyTotal,
  71.                 nProxyEntityTotal));
  72.  
  73.             PromptKeywordOptions pko = new PromptKeywordOptions("\nОчистить список масштабов? ");
  74.             pko.Keywords.Add("Yes", "Д", "Да", true, true);
  75.             pko.Keywords.Add("No", "Н", "Нет", true, true);
  76.             pko.Keywords.Default = "Yes";
  77.             PromptResult pr = Acad.Editor.GetKeywords(pko);
  78.             if (pr.Status == PromptStatus.OK && pr.StringResult == "Yes")
  79.             {
  80.                 acedResetScaleList(false, true, db.UnmanagedObject);
  81.             }
  82.  
  83.             int nProxyDeleted = 0;
  84.             int nProxyEntityDeleted = 0;
  85.  
  86.             using (AcAp.Application.DocumentManager.MdiActiveDocument.LockDocument())
  87.             {
  88.                 for (int j = 0; j < ids.Count; j++)
  89.                 {
  90.  
  91.                     using (DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false))
  92.                     {
  93.                         try
  94.                         {
  95.                             dbObj.Erase(true);
  96.                             if (dbObj.IsErased)
  97.                             {
  98.                                 nProxyDeleted++;
  99.                                 Entity entity = dbObj as Entity;
  100.                                 if (entity != null)
  101.                                 {
  102.                                     nProxyEntityDeleted++;
  103.                                 }
  104.                             }
  105.                         }
  106.                         catch
  107.                         {
  108.                             Entity entity = dbObj as Entity;
  109.                             DBObject tmpObj = null;
  110.                             if (entity != null)
  111.                             {
  112.                                 tmpObj = new Line();
  113.                             }
  114.                             else
  115.                             {
  116.                                 tmpObj = new DBDictionary();
  117.                             }
  118.                             dbObj.HandOverTo(tmpObj, false, false);
  119.                             nProxyDeleted++;
  120.                             tmpObj.Erase(true);
  121.                             tmpObj.Close();
  122.                             tmpObj.Dispose();
  123.                         }
  124.                     }
  125.                 }
  126.  
  127.                 using (var tr = Acad.TransactionManager.StartTransaction())
  128.                 {
  129.                     LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  130.                     for (int i = 0; i < idsLockedLayers.Count; i++)
  131.                     {
  132.                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(idsLockedLayers[i], OpenMode.ForWrite);
  133.                         ltr.IsLocked = true;
  134.                     }
  135.  
  136.                     tr.Commit();
  137.                 }
  138.  
  139.                 idsLockedLayers.Dispose();
  140.  
  141.                 Acad.Editor.WriteMessage(
  142.                     string.Format("\nВсего удалено proxy-объектов: {0}. Из них proxy-примитивов: {1}.",
  143.                     nProxyDeleted,
  144.                     nProxyEntityDeleted));
  145.             }
  146.  
  147.             Autodesk.AutoCAD.Interop.AcadApplication app = (Autodesk.AutoCAD.Interop.AcadApplication)AcAp.Application.AcadApplication;
  148.             app.ActiveDocument.AuditInfo(true);
  149.             PurgeDatabase(db);
  150.         }
  151.  

Код - C# [Выбрать]
  1.         [CommandMethod("EXPLODEALLPROXY", CommandFlags.Modal)]
  2.         public static void ExplodeAllProxy()
  3.         {
  4.             Database db = Acad.Database;
  5.             ObjectIdCollection idsLockedLayers = new ObjectIdCollection();
  6.  
  7.             using (AcAp.Application.DocumentManager.MdiActiveDocument.LockDocument())
  8.             {
  9.                 using (var tr = Acad.TransactionManager.StartTransaction())
  10.                 {
  11.                     LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  12.  
  13.                     foreach (var layerId in lt)
  14.                     {
  15.                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite);
  16.                         if (ltr.IsLocked)
  17.                         {
  18.                             ltr.IsLocked = false;
  19.                             idsLockedLayers.Add(layerId);
  20.                         }
  21.                     }
  22.  
  23.                     tr.Commit();
  24.                 }
  25.  
  26.                 long exploded = 0;
  27.                 long proxy = 0;
  28.                 ObjectIdCollection ids = new ObjectIdCollection();
  29.                 using (var tr = Acad.TransactionManager.StartTransaction())
  30.                 {
  31.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  32.                     ids = new ObjectIdCollection(bt.OfType<ObjectId>().ToArray());
  33.  
  34.                     bt.Close();
  35.                 }
  36.  
  37.                 foreach (ObjectId currentId in ids)
  38.                 {
  39.                     if (!ExplodeProxyInBTR(currentId, ref proxy, ref exploded))
  40.                     {
  41.                         Acad.Editor.WriteMessage(
  42.                             string.Format("\nОшибка расчленения ACAD_PROXY_ENTITY!",
  43.                             currentId));
  44.                     }
  45.                 }
  46.  
  47.                 Acad.Editor.WriteMessage(string.Format("\nУдалено Proxy: {0} Новых объектов: {1}", proxy, exploded));
  48.  
  49.  
  50.                 using (var tr = Acad.TransactionManager.StartTransaction())
  51.                 {
  52.                     LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  53.                     for (int i = 0; i < idsLockedLayers.Count; i++)
  54.                     {
  55.                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(idsLockedLayers[i], OpenMode.ForWrite);
  56.                         ltr.IsLocked = true;
  57.                     }
  58.  
  59.                     tr.Commit();
  60.                 }
  61.             }
  62.         }
  63.  
  64.         public static bool ExplodeProxyInBTR(ObjectId blkId, ref long proxy, ref long exploded)
  65.         {
  66.             if (blkId == ObjectId.Null)
  67.             {
  68.                 return false;
  69.             }
  70.  
  71.             DBObjectCollection aExplProxy = new DBObjectCollection();
  72.             ObjectIdCollection proxyEntities = new ObjectIdCollection();
  73.  
  74.             using (var tr = Acad.TransactionManager.StartTransaction())
  75.             {
  76.                 using (BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkId, OpenMode.ForRead))
  77.                 {
  78.                     foreach (var item in btr)
  79.                     {
  80.                         ProxyEntity proxyEntity = tr.GetObject(item, OpenMode.ForWrite) as ProxyEntity;
  81.                         if (proxyEntity != null)
  82.                         {
  83.                             proxyEntities.Add(item);
  84.                             proxyEntity.Close();
  85.                             System.Diagnostics.Debug.WriteLine(item.ObjectClass.Name);
  86.                         }
  87.                     }
  88.                 }
  89.             }
  90.  
  91.             for (int i = 0; i < proxyEntities.Count; i++)
  92.             {
  93.                 ProxyEntity proxyEntity = proxyEntities[i].Open(OpenMode.ForWrite, false, false) as ProxyEntity;
  94.                 switch (proxyEntity.GraphicsMetafileType)
  95.                 {
  96.                     case GraphicsMetafileType.BoundingBox:
  97.                         {
  98.                             Extents3d ext = proxyEntity.GeometricExtents;
  99.                             if (ext != null)
  100.                             {
  101.                                 Point3dCollection arr = new Point3dCollection();
  102.                                 arr.Add(ext.MinPoint);
  103.                                 arr.Add(new Point3d(ext.MinPoint.X, ext.MaxPoint.Y, ext.MinPoint.Z));
  104.                                 arr.Add(new Point3d(ext.MaxPoint.X, ext.MaxPoint.Y, ext.MinPoint.Z));
  105.                                 arr.Add(new Point3d(ext.MaxPoint.X, ext.MinPoint.Y, ext.MinPoint.Z));
  106.  
  107.                                 Polyline3d pLine = new Polyline3d(Poly3dType.SimplePoly, arr, true);
  108.                                 pLine.LayerId = proxyEntity.LayerId;
  109.                                 pLine.LinetypeId = proxyEntity.LinetypeId;
  110.                                 pLine.Color = proxyEntity.Color;
  111.  
  112.                                 aExplProxy.Add(pLine);
  113.                             }
  114.  
  115.                             proxy++;
  116.                             proxyEntity.Erase(true);
  117.  
  118.                             Line line = new Line();
  119.                             proxyEntity.HandOverTo(line, false, false);
  120.                             line.Dispose();
  121.                         }
  122.                         break;
  123.                     case GraphicsMetafileType.FullGraphics:
  124.                         {
  125.                             proxyEntity.Explode(aExplProxy);
  126.                             if (aExplProxy.Count > 0)
  127.                             {
  128.                                 try
  129.                                 {
  130.                                     proxy++;
  131.                                     proxyEntity.Erase(true);
  132.  
  133.                                     Line line = new Line();
  134.                                     proxyEntity.HandOverTo(line, false, false);
  135.                                     line.Dispose();
  136.                                 }
  137.                                 catch{}
  138.                             }
  139.                             else
  140.                             {
  141.                                 //System.Diagnostics.Debug.WriteLine(proxyEntity.ObjectId.ToString());
  142.                             }
  143.                         }
  144.                         break;
  145.                     case GraphicsMetafileType.NoMetafile:
  146.                         break;
  147.                     default:
  148.                         break;
  149.                 }
  150.  
  151.                 proxyEntity.Dispose();
  152.             }
  153.             proxyEntities.Dispose();
  154.  
  155.             using (var tr = Acad.TransactionManager.StartTransaction())
  156.             {
  157.                 using (BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkId, OpenMode.ForRead))
  158.                 {
  159.                     exploded += aExplProxy.Count;
  160.                     ObjectIdCollection idsRef = btr.GetBlockReferenceIds(true, true);
  161.  
  162.                     if (aExplProxy.Count > 0)
  163.                     {
  164.                         for (int i = 0; i < aExplProxy.Count; i++)
  165.                         {
  166.                             btr.UpgradeOpen();
  167.                             Entity entity = aExplProxy[i] as Entity;
  168.                             btr.AppendEntity(entity);
  169.                             tr.AddNewlyCreatedDBObject(entity, true);
  170.                             entity.Close();
  171.                         }
  172.                     }
  173.  
  174.                     for (int i = 0; i < idsRef.Count; i++)
  175.                     {
  176.                         BlockReference br = (BlockReference)tr.GetObject(idsRef[i], OpenMode.ForWrite);
  177.                         br.RecordGraphicsModified(true);
  178.                         br.Close();
  179.                     }
  180.  
  181.                     idsRef.Dispose();
  182.                     btr.Close();
  183.                 }
  184.             }
  185.  
  186.             aExplProxy.Dispose();
  187.  
  188.             return true;
  189.         }
  190.  
« Последнее редактирование: 21-11-2014, 12:19:40 от T72 »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #7 : 05-11-2014, 18:54:59 »
Несколько замечаний по коду. Строка 93 третьей части кода:
Код - C# [Выбрать]
  1. DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false);
Ты открываешь это объект, но нигде не закрываешь его. Если dbObj.Erase(true) выполнилось успешно, то нужно вызвать dbObj.Close(). Если возникло исключение и мы пользуемся для удаления
Код - C# [Выбрать]
  1. dbObj.HandOverTo(tmpObj, false, false);
то нужно выполнить dbObj.Dispose() и tmpObj.Close()
Поэтому (я не тестировал код) лучше использовать конструкцию:
Код - C# [Выбрать]
  1. using (DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false))
  2. {
  3. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #8 : 05-11-2014, 22:28:10 »
Еще одно замечание. Можно конечно использовать и условную компиляцию, т.е. в зависимости от версии и в зависимости от разрядности AutoCAD компилировать отдельные dll-файлы. А можно проверить и то и другое динамически и динамически вызвать нужную функцию. Тогда в отличие от arx-файла, который всегда нужно делать для каждой разрядности AutoCAD, можно сделать (в 95% случаев) dll-файл независящий от разрядности AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #9 : 06-11-2014, 01:21:18 »
T72, ну и спасибо тебе за то, что навёл меня на баг в моей версии. В версиях начиная с 2013 список масштабов в команде REMOVEALLPROXY не чистился. Причина банальная - перенос функции acedResetScaleList в accore.dll. Подправил свои исходники и выложил исправленные arx-файлы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн T72Автор темы

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #10 : 06-11-2014, 07:52:59 »
Несколько замечаний по коду. Строка 93 третьей части кода:
Код - C#: [Выделить]

    DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false);

Ты открываешь это объект, но нигде не закрываешь его. Если dbObj.Erase(true) выполнилось успешно, то нужно вызвать dbObj.Close(). Если возникло исключение и мы пользуемся для удаления
Спасибо. Close там был но потом я его при рефакторинге случайно удалил, а вот то, что Dispose нужен не знал, учту.
По поводу 95% в данном случае действительно можно сделать так.


Оффлайн T72Автор темы

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #11 : 06-11-2014, 14:16:00 »
Добавил EXPLODEALLPROXY.
Пришлось немного поменять из-за несовместимости транзакций и HandOverTo.
Еще хочу обратить внимание на момент с расчленением прокси. Если explode возвращает 0 примитивов то выполнять proxy++ не стоит (по моему мнению), т.к. данный ACAD_PROXY_ENTITY исчезает из быстрого выбора, но в чертеже содержится и при следующем открытии будет снова доступен.
Спасибо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #12 : 06-11-2014, 21:21:49 »
Если explode возвращает 0 примитивов то выполнять proxy++ не стоит (по моему мнению), т.к. данный ACAD_PROXY_ENTITY исчезает из быстрого выбора, но в чертеже содержится и при следующем открытии будет снова доступен.
Эту мысль я что-то не понял.  В моём коде вне зависимости от того что возвращает explode сам примитив потом удаляется и поэтому proxy++ справедливо.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #13 : 06-11-2014, 22:30:34 »
Эта конструкция в корне неправильна:
Код - C# [Выбрать]
  1. proxyEntity.Explode(aExplProxy);
  2. if (aExplProxy.Count > 0)
  3. {
  4.     proxy++;
  5.     proxyEntity.Erase(true);
  6.  
  7.     Line line = new Line();
  8.     proxyEntity.HandOverTo(line, false, false);
  9.     line.Close();
  10.     line.Dispose();
  11. }
1. Ты сначала удаляешь  proxyEntity, и не проверив удачно ли это получилось выполняешь повторное удаление при помощи HandOverTo
2. После HandOverTo ты делаешь line.Close() - это правильно, т.к. теперь line - это примитив в базе. А где же line.Erase() ?
3. Нужно делать не line.Dispose(), а proxyEntity.Dispose()
Мы тут уже на форуме это обсуждали, что если объект/примитив AutoCAD содержится в базе (т.е. его ObjectId отличен от 0), то метод Dispose() для него эквивалентен методу Close(), а если примитив не содержится в базе (т.е. его ObjectId равен 0), то метод Dispose эквивалентен освобождению памяти этого примитива.
Таким образом  line.Close(); и  line.Dispose();  -  эквивалентны, зато нет освобождения памяти proxyEntity
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн T72Автор темы

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #14 : 06-11-2014, 22:36:17 »
Цитата: T72 от 06-11-2014, 14:16:00

    Если explode возвращает 0 примитивов то выполнять proxy++ не стоит (по моему мнению), т.к. данный ACAD_PROXY_ENTITY исчезает из быстрого выбора, но в чертеже содержится и при следующем открытии будет снова доступен.

Эту мысль я что-то не понял.  В моём коде вне зависимости от того что возвращает explode сам примитив потом удаляется и поэтому proxy++ справедливо.
Данная функция для разбиения прокси на примитивы - значит если не получилось разбить то не стоит удалять, для этого есть другая функция.