Преобразование AcDbObjectIdArray в IAcadSelectionSet
Недавно я получил запрос от партнера ADN как передать массив ObjectID в Export COM API. Проблема заключается в том, что необходимо преобразование из C++ в COM
Прототип функции Export в COM описывается так :
Ей передаётся имя файла, расширение файла и IAcadSelectionSet – набор примитивов, тогда как у нас есть массив ObjectId.
Поставим перед собой цель выполнить экспорт набора примитивов в BMP-файл.
Для этого мы:
- Получим массив ObjectId, получим для каждого из элементов IAcadEntity исползуя глобальную функцию AcAxGetIUnknownOfObject.
- Добавляем IAcadEntity к AcadSelectionSet при помощи метода AddItems
- Используем AcadSelectionSet в Export API
Пример кода:
- void TestExport()
- {
- ads_name ss;
- AcDbObjectIdArray* pIdArray = new AcDbObjectIdArray();
- // Получаем набор примитивов
- int res = acedSSGet (NULL, NULL, NULL, NULL, ss);
- if (res == RTNORM)
- {
- // Получаем количество элементов в наборе
- long length = 0l;
- acedSSLength (ss, &length);
- // Цикл по всем элементам
- for (long i= 0l; i < length; ++i)
- {
- ads_name ename;
- // Получаем имя примитива (ename)
- if (acedSSName (ss, i, ename) != RTNORM)
- continue;
- AcDbObjectId objId;
- // Преобразуем ename в ObjectId
- acdbGetObjectId (objId, ename);
- pIdArray->append(objId);
- }
- }
- /* Экспортируем выбранные примитивы в BMP-файл */
- ExportToFile(pIdArray);
- // освобождаем набор после его использования
- acedSSFree (ss);
- delete pIdArray;
- }
- //////////////////////////////////////////////////////////////////////////
- // Вспомогательные функции
- //////////////////////////////////////////////////////////////////////////
- /* Помещаем AcadEntity в заданный IAcadSelectionSet */
- HRESULT addToSelSet(AutoCAD::IAcadSelectionSet* pSelSet, AutoCAD::IAcadEntity* pEntity)
- {
- HRESULT hr;
- SAFEARRAYBOUND rgsabound[1];
- rgsabound[0].lLbound = 0;
- rgsabound[0].cElements = 1;
- SAFEARRAY* psa = SafeArrayCreateVector(VT_DISPATCH, rgsabound->lLbound, rgsabound->cElements);
- if(!psa) return E_OUTOFMEMORY;
- long i = 0;
- LPDISPATCH pDisp = pEntity;
- pEntity->Release();
- /*
- Эта функция назначает единичный элемент массива.
- */
- /*
- Типы вариантов VT_DISPATCH, VT_UNKNOWN, и VT_BSTR являются
- указателями и не требуют разименования.
- */
- hr = SafeArrayPutElement(psa, &i,pDisp);
- if( FAILED(hr) )
- {
- SafeArrayDestroy(psa);
- return hr;
- }
- VARIANT v;
- VariantInit(&v);
- v.vt = VT_DISPATCH|VT_ARRAY;
- v.parray = psa;
- return pSelSet->AddItems(v);
- }
- /* Получаем набор или создаём его, если его еще нет */
- AutoCAD::IAcadSelectionSet *GiveMeSelectionSet(AutoCAD::IAcadSelectionSets *pSelSets, BSTR Name)
- {
- try {
- AutoCAD::IAcadSelectionSet *pSet = NULL;
- if (pSelSets->Add(Name,&pSet) == S_OK) {
- return pSet;
- } else if (pSelSets->Item(_variant_t(Name),&pSet) == S_OK) {
- return pSet;
- } else return NULL;
- } catch(...) {
- return NULL;
- }
- return NULL;
- }
- void ExportToFile(AcDbObjectIdArray*& pIdArray)
- {
- HRESULT hr;
- try
- {
- AutoCAD::IAcadApplication *pAcad =NULL;
- AutoCAD::IAcadDocument *pDoc =NULL;
- AutoCAD::IAcadModelSpace *pMSpace = NULL;
- AutoCAD::IAcadSelectionSets *pSelSets = NULL;
- AutoCAD::IAcadSelectionSet *pSet= NULL;
- hr = NOERROR;
- LPUNKNOWN pUnk = NULL;
- LPDISPATCH pAcadDisp = acedGetIDispatch(TRUE);
- if(pAcadDisp == NULL)
- return ;
- hr = pAcadDisp->QueryInterface(AutoCAD::IID_IAcadApplication,(void**)&pAcad);
- pAcadDisp->Release();
- if (FAILED(hr))
- return;
- if (pAcad)
- {
- if (pAcad->get_ActiveDocument(&pDoc) == S_OK)
- {
- if (pDoc->get_SelectionSets(&pSelSets) == S_OK) {
- /* Получаем или создаём набор */
- if ((pSet = GiveMeSelectionSet(pSelSets,_bstr_t("TestSet"))) != NULL)
- {
- pSet->Clear();
- for (int i = 0; i < pIdArray->length(); i++)
- {
- AcDbObjectId id = pIdArray->at(i);
- // Получаем COM-обертку для примитива
- if(FAILED(hr = AcAxGetIUnknownOfObject(&pUnk, id, pAcadDisp)))
- throw (_com_error(hr));
- // Получаем AutoCAD::IAcadEntity
- AutoCAD::IAcadEntity *pEnt = NULL;
- if(FAILED(hr= pUnk->QueryInterface(AutoCAD::IID_IAcadEntity, (void **)&pEnt)))
- throw (_com_error(hr));
- /* Добавляем примитив к набору */
- if (FAILED(hr = addToSelSet(pSet,pEnt)))
- throw(_com_error(hr)) ;
- }
- if (FAILED(hr = pDoc->Export(_bstr_t("c:\\temp\\test"),_bstr_t("BMP"),pSet)))
- throw(_com_error(hr)) ;
- pSet->Release();
- }
- else
- return ;
- pSelSets->Release();
- }
- pDoc->Release();
- }
- pAcad->Release();
- }
- pUnk->Release();
- }
- catch (...)
- {
- return ;
- }
- return ;
- }
Источник: http://adndevblog.typepad.com/autocad/2015/05/converting-acdbobjectidarray-to-iacadselectionset.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=2728
Опубликовано 21.05.2015