16/07/2015
Преобразование из .NET в COM с использованием управляемого (Managed) C++
После выбора объекта при помощи .NET (управляемый C++), как его преобразовать в COM-объект? Сначала нужно получить IUnknow-указатель из свойства AcadObject объекта, а затем преобразовать его в COM-объект. Эта процедура позволяет вам сохранить счетчик ссылок COM объекта.Следующий код показывает как это сделать и как получить его имя типа. Напоминаю, что нужно установить для проекта свойство Mixed mode. Это легко сделать создав проект при помощи ObjectARX Wizard и указав ему использовать .NET.
Код - C++: [Выделить]
- static void MgdFunction()
- {
- // Получаем коллекцию документов (MDI-интерфейс)
- Autodesk::AutoCAD::ApplicationServices::DocumentCollection ^docMgr =
- Autodesk::AutoCAD::ApplicationServices::Application::DocumentManager;
- // Получаем активный документ
- Autodesk::AutoCAD::ApplicationServices::Document ^acadDoc =
- docMgr->MdiActiveDocument;
- // Получаем редактор (Editor)
- Autodesk::AutoCAD::EditorInput::Editor ^ed = acadDoc->Editor;
- // Объект транзакции
- Autodesk::AutoCAD::DatabaseServices::Transaction ^trans = nullptr;
- try
- {
- // Стартуем транзакцию
- trans = acadDoc->Database->TransactionManager->StartTransaction();
- // Выбираем примитив при помощи .NET API
- Autodesk::AutoCAD::EditorInput::PromptEntityResult ^promptEntRes =
- ed->GetEntity(_T("\nВыберите примитив: "));
- if (promptEntRes->Status != Autodesk::AutoCAD::EditorInput::PromptStatus::OK)
- return;
- // Открываем примитив для чтения
- Autodesk::AutoCAD::DatabaseServices::Entity ^mgdEntity =
- (Autodesk::AutoCAD::DatabaseServices::Entity^)
- trans->GetObject(promptEntRes->ObjectId,
- Autodesk::AutoCAD::DatabaseServices::OpenMode::ForRead);
- // Получаем COM-объект из .NET-объекта
- System::Object ^acadObj = mgdEntity->AcadObject;
- System::IntPtr ptr = System::Runtime::InteropServices::Marshal::GetIUnknownForObject(acadObj);
- IUnknown* iunk = static_cast<IUnknown *>(ptr.ToPointer());
- CComQIPtr<IAcadEntity> acadEntity = iunk;
- iunk->Release();
- // Получаем имя примитива из COM-объекта
- // Это будет имя класса типа AcDbLine для отрезка
- // или AcDbCircle для окружности, и т.д.
- CComBSTR entityName;
- acadEntity->get_EntityName(&entityName);
- // Если мы сделаем правильное преобразование, например в IAcadLine для отрезка,
- // тогда мы можем вызвать любой другой метод этого COM-объекта
- // Сейчас получим имя COM-интерфейса объекта
- // Это будет что-то типа IAcadLine, IAcadCircle, и т.д.
- CComPtr<ITypeInfo> typeInfo;
- acadEntity->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT,&typeInfo);
- CComBSTR interfaceName;
- typeInfo->GetDocumentation(-1,&interfaceName, 0,0,0);
- // и печатаем при помощи .NET
- ed->WriteMessage(_T("\nВыбран примитив: {0} ({1})"),
- gcnew System::String(entityName),
- gcnew System::String(interfaceName));
- trans->Commit();
- }
- catch(System::Exception^ e)
- {
- // Что-то пошло не так
- ed->WriteMessage(e->Message);
- }
- __finally
- {
- // Освобождаем транзакцию
- trans->~Transaction();
- }
- }
Источник: http://adndevblog.typepad.com/autocad/2013/01/cast-from-net-to-com-using-managed-c.html
Автор перевода: Александр Ривилис
Обсуждение: http://adn-cis.org/forum/index.php?topic=2863
Опубликовано 16.07.2015