Тема: Просмотр свойств пользовательских объектов

Приветствую всех посетителей форума. Может кто-нибудь подскажет: как реализовать просмотр и редактирование свойств объекта пользовательского класса, унаследованного от AcDbEntity, именно через окно свойств AutoCad-а. Я просмотрел форум-этот вопрос уже поднимался, но четкого механизма(ов) реализации никто так и не предложил. И вообще можно ли это реализовать!?

Re: Просмотр свойств пользовательских объектов

Алексей Журавков пишет:

Я просмотрел форум-этот вопрос уже поднимался, но четкого механизма(ов) реализации никто так и не предложил.

Плохо искал. Посмотри в ObjectARX SDK примеры: samples\entity\polysamp и samples\entity\Smiley

Алексей Журавков пишет:

И вообще можно ли это реализовать!?

Можно.

Re: Просмотр свойств пользовательских объектов

Спасибо за помощь.
Просмотрел пример Smiley, со многим разобрался, но есть вопросы: если поменять в программе название категорий свойств (Face, Eyes и т.д.) и  перекомпилировать проект, то изменения не отображаются и в окне свойств все остается без изменения. В чем может быть дело?

(изменено: Александр Ривилис, 20 апреля 2010г. 23:54:32)

Re: Просмотр свойств пользовательских объектов

Алексей Журавков пишет:

В чем может быть дело?

Где менял (имена файлов и номера строк)? Еще были нюансы связанные с регистрацией приложения в реестре как COM-сервера. Тот ли arx/dbx/dll грузится в AutoCAD или находит другую версию по старому пути?

Re: Просмотр свойств пользовательских объектов

В файле "SmileyEntity.cpp" в методе "STDMETHODIMP CSmileyEntity::GetCategoryName(PROPCAT propcat, LCID lcid, BSTR* pbstrName)" изменил строку *pbstrName = ::SysAllocString(L"Face"); например на *pbstrName = ::SysAllocString(L"Face111");
В файле "Smiley - COM.reg" изменил пути к файлам на текущие. Зарегистрировал это в реестре.
Но в окне свойств эти изменения не видны. Значит скорее всего подгружается старая откомпилированная версия dll. Изменения в "SmileyDbCom.idl" файле после перекомпиляции также не видны в AutoCad-е Как это можно исправить?

Re: Просмотр свойств пользовательских объектов

Алексей Журавков пишет:

В файле "Smiley - COM.reg" изменил пути к файлам на текущие.

Вот в этом то собака и порылась. Как минимум удали старые файлы. И еще желательно вручную загрузить все новые arx/dbx/dll в AutoCAD - они сами перерегистрируются с новыми путями (во всяком случае должны).

Re: Просмотр свойств пользовательских объектов

Изменения,сделанные в dbx видны. Как вручную загрузить dll в AutoCad? Ведь в ней скорее всего и проблема?!

Re: Просмотр свойств пользовательских объектов

Теоретически исправление и запуск файла Smiley - COM.reg должны привести к нужному результату. Если это не происходит, то можно используя функцию (например из arx) ::LoadLibrary загрузить оба dll-файла, найти их точки входа DllRegisterServer и вызвать их - это должно привести к их перерегистрации.

Re: Просмотр свойств пользовательских объектов

А можно небольшой листинг для этого подхода, пожалуйста?
Я представляю реализацию примерно так - в ф-ции InitApplication()вызвать метод
::LoadLibrary:
HMODULE hModule1, hModule2;
    hModule1 = ::LoadLibrary(_T("D:\\ObjectARX 2008\\Samples\\entity\\Smiley\\debug\\AsdkSmileyUiCom.dll"));
    hModule2 = ::LoadLibrary(_T("D:\\ObjectARX 2008\\Samples\\entity\\Smiley\\debug\\AsdkSmileyDbCom.dll"));
А дальше?

(изменено: Александр Ривилис, 21 апреля 2010г. 11:35:46)

Re: Просмотр свойств пользовательских объектов

Где-то так:

typedef STDAPI (*PtrDllRegisterServer)();
PtrDllRegisterServer ptr1 = 
   (PtrDllRegisterServer)GetProcAddress(hModule1,"DllRegisterServer");
if (ptr1) (*ptr1)();
PtrDllRegisterServer ptr2 = 
   (PtrDllRegisterServer)GetProcAddress(hModule2,"DllRegisterServer");
if (ptr2) (*ptr2)();

Думаю что мысль должна быть понятна.
P.S.: Писал "на коленке" без проверки в Visual Studio.

Re: Просмотр свойств пользовательских объектов

Отлично!!Спасибо, все отлично работает. Только изменил первую строку на "typedef HRESULT (*PtrDllRegisterServer)(void);", т.к. #define STDAPI   EXTERN_C HRESULT STDAPICALLTYPE, а #define STDAPIVCALLTYPE      __cdecl. Если можно хочу уточнить: при вызове метода DllRegisterServer()-он проверяет зарегистирована ли уже библиотека или будет постоянно ее перерегистрировать. Либо существует метод проверки регистрации dll?

(изменено: Александр Ривилис, 22 апреля 2010г. 09:32:33)

Re: Просмотр свойств пользовательских объектов

Алексей Журавков пишет:

при вызове метода DllRegisterServer()-он проверяет зарегистирована ли уже библиотека или будет постоянно ее перерегистрировать.

Будет перерегистрировать (если ты внимательно проследишь всю цепочку вызовов - она есть в исходных кодах ATL - то убедишься в этом сам). Фактически регистрация - это запись в реестр информации, аналогичной то, что прописана в файле "Smiley - COM.reg". Готовой функции проверки регистрации как таковой нет. Да и смысл в ней какой если она должна была бы проверять эту же информацию в реестре?
Есть функция DllUnregisterServer(), которая удаляет информацию о регистрации.
Обычно COM-сервера регистрируются при помощи regsvr32.exe (входит в состав Windows), которая и выполняет функцию аналогичную вызову DllRegisterServer(). Но в данном случае наши dll-файлы зависят от acad.exe и acdbXX.dll (они указаны в таблице импорта наших dll-файлов), которые regsvr32.exe найти и загрузить не может. Поэтому приходится выполнять регистрацию изнутри AutoCAD.

Re: Просмотр свойств пользовательских объектов

Большое спасибо, Александр, за информацию! Пожалуйта, разъясните еще пару вопросов:
1) возвращаясь к примеру "Smiley" - я хочу уточнить, правильно ли я понимаю механизм взаимодействия сгенерированных модулей: сначала загружаются в AutoCad AsdkSmileyDb.dbx,AsdkSmileyUi.arx. Далее не совсем понятно-как подгружаются файлы AsdkSmileyDbCom.dll, AsdkSmileyUiCom.dll. Насколько я понимаю, чтобы отрисовать "Smiley" из внешнего модуля необходимо, чтобы AutoCad и  AsdkSmileyUi.arx были уже загружены. После этого необходимо загрузить AsdkSmileyUiCom.dll и вызвать функцию  createSmile() из AsdkSmileyUi.arx . Как происходит этот процесс? И как AutoCad загружает AsdkSmileyDbCom.dll для получения свойств пользовательских объектов? Можно ли вызвать createSmile() непосредственно из AsdkSmileyUi.arx, в обход AsdkSmileyUiCom.dll
2) Каково назначение GS маркеров( "wd->subEntityTraits().setSelectionMarker( 1 );")?

Re: Просмотр свойств пользовательских объектов

Алексей Журавков пишет:

Далее не совсем понятно-как подгружаются файлы AsdkSmileyDbCom.dll, AsdkSmileyUiCom.dll.

AsdkSmileyDbCom.dll загружается самим AutoCAD'ом по имени COM-сервера "SmileyDb.Entity", если загружен AsdkSmileyDb.dbx и открыт OPM (панель свойств). Имя севера определяется методом AsdkSmiley::getClassID(CLSID* pClsid). Если не поленишься и посмотришь все исходные коды, то заметишь, что при загрузке AsdkSmileyUi.arx загружается (из AsdkSmileyUi.arx) и AsdkSmileyDb.dbx
AsdkSmileyUiCom.dll загружается как COM-сервер по имени "SmileyUi.Application"

Алексей Журавков пишет:

Можно ли вызвать createSmile() непосредственно из AsdkSmileyUi.arx, в обход AsdkSmileyUiCom.dll

Из внешнего по отношению к AutoCAD процесса нельзя.

Алексей Журавков пишет:

2) Каково назначение GS маркеров( "wd->subEntityTraits().setSelectionMarker( 1 );")?

Позволяет при выборе примитива узнать какая его часть была выбрана.

Re: Просмотр свойств пользовательских объектов

А в каком виде представляется информация о части примитива, после его выбора, т.е. как мне идентифицировать часть примитива по маркеру.

Re: Просмотр свойств пользовательских объектов

Она представлена в том виде, в котором ты ее задашь в своем Custom entity.
Есть пара методов, которые можно переопределить в классе своего примитива:

AcDbEntity::getSubentPathsAtGsMarker
AcDbMLeader::getGsMarkersAtSubentPath 

Чтобы я не занимался переписыванием главы документации, посмотри раздел GS Markers в ObjectARX SDK Docs.

Re: Просмотр свойств пользовательских объектов

Теперь все понятно, большое спасибо!!! :D