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

29/05/2013

Перебор всех IAcadBlock в IAcadBlocks используя ActiveX в C++

Вопрос:
В C++ я не вижу возможности перебрать IAcadBlocks, чтобы получить доступ к каждому IAcadBlock. Есть пример кода, который это делает?

Ответ:
Следующие два подхода перебирают IAcadBlocks для доступа к каждому IAcadBlock. Первый предполагает, что вы настроили ваш проект с использованием ARX/MFC и импортирована TLB-библиотеки AutoCAD COM.

Код - C++: [Выделить]
  1. void test()
  2. {
  3.     try
  4.     {
  5.         // Получаем приложение
  6.         IAcadApplicationPtr pIAcad =
  7.             acedGetAcadWinApp()->GetIDispatch(TRUE);
  8.         // Получаем коллекцию блоков
  9.         IAcadBlocksPtr pIBlks =
  10.             pIAcad->GetActiveDocument()->GetBlocks();
  11.  
  12.         // Подсчитываем блоки
  13.         long nCnt =pIBlks->GetCount();
  14.         for(long i=0; i<nCnt; i++)
  15.         {
  16.             _variant_t var(i);
  17.             // каждый блок
  18.             IAcadBlockPtr pIBlk =  pIBlks->Item(var);
  19.             BSTR str;
  20.             // Получаем имя блока
  21.             pIBlk->get_Name(&str);
  22.             _bstr_t bstr(str);
  23.             // Выводим окно с именем блока
  24.             AfxMessageBox(bstr);
  25.             ::SysFreeString(str);
  26.         }
  27.     }
  28.     catch(_com_error& err)
  29.     {
  30.         AfxMessageBox(err.ErrorMessage());
  31.     }
  32. }

 

Если вы используете директиву #import для файлов, включенных в ObjectARX, это можно сделать следующим образом.

Код - C++: [Выделить]
  1. static void test()
  2. {
  3.     try
  4.     {
  5.         // Получаем приложение
  6.         IDispatch* pDisp =
  7.             acedGetAcadWinApp()->GetIDispatch(TRUE);
  8.         if(!pDisp) _com_issue_error(E_POINTER);
  9.         CComPtr<IAcadApplication> pIAcad;
  10.         pDisp->QueryInterface(IID_IAcadApplication, (void**)&pIAcad);
  11.  
  12.         // Получаем текущий документ
  13.         CComPtr<IAcadDocument> pIDoc;
  14.         pIAcad->get_ActiveDocument(&pIDoc);
  15.  
  16.         // Получаем коллекцию блоков
  17.         CComPtr<IAcadBlocks> pIBlks;
  18.         pIDoc->get_Blocks(&pIBlks);
  19.  
  20.         long blksCnt;
  21.         pIBlks->get_Count(&blksCnt);
  22.         CComPtr<IAcadBlock> pIBlk;
  23.         // Перебираем все блоки
  24.         for(long i=0; i<blksCnt; i++)
  25.         {
  26.             _variant_t x(i);
  27.             pIBlks->Item(x, &pIBlk);
  28.             BSTR str;
  29.             pIBlk->get_Name(&str);
  30.             char buf[256];
  31.             buf [0] =0 ;
  32.             if(WideCharToMultiByte (CP_ACP,
  33.                 0,
  34.                 str,
  35.                 -1,
  36.                 buf,
  37.                 256,
  38.                 NULL,
  39.                 NULL))
  40.        acutPrintf(_T("\nИмя %d-го блока: %s"), i, buf);
  41.             ::SysFreeString(str);
  42.         }
  43.     }
  44.     catch(_com_error& err)
  45.     {
  46.         AfxMessageBox(err.ErrorMessage());
  47.     }
  48. }

 

Примечание переводчика: В коде присутствует вызов WideCharToMultiByte, который был нужен только в AutoCAD до 2006 включительно. Для AutoCAD 2007+ функция acutPrintf для формата %s требует wchar_t *, а не char *.

 

Источник: http://adndevblog.typepad.com/autocad/2013/03/iterate-each-iacadblock-in-iacadblocks-using-activex-in-c.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=55.0

Опубликовано 29.05.2013
Отредактировано 06.06.2013 в 12:53:13