17/01/2014
Выгрузка и удаление внешней ссылки при помощи .NET
В приложении ObjectARX чтобы получить уведомление после того, как внешняя ссылка выгружена или удалена необходимо переопределить методы "AcEditorReactor::xrefSubcommandUnloadItem" и "AcEditorReactor::xrefSubcommandDetachItem" класса реактора редактора. К сожалению, в AutoCAD .Net API нет соответствующих методов.В качестве «обходного метода» можно использовать следующий проект, который можно использовать в .NET.
Полный код можете посмотреть в конце. Шаги, относящиеся к этому коду, следующие:
1) Экспортируем метод из .arx, который принимает указатель на функцию для уведомления.
Код - C++: [Выделить]
- // Указатель на функцию, который буде хранится в реакторе редактора
- typedef void (__stdcall *PTRFN_Notify)(int xrefUnloadType);
- // Экспортируем метод, который будет вызываться из .Net
- extern "C" DLLIMPEXP
- void SetXrefEventNotifyCB(PTRFN_Notify callBack);
2) Реализуем реактор редактора в ObjectARX-модуле.
Код - C++: [Выделить]
- // asdkMyEdReactor.h
- class asdkMyEdReactor : public AcEditorReactor
- {
- protected:
- // Переопределяем функции уведомления о выгрузке/удалении Xref
- virtual void xrefSubcommandUnloadItem(
- AcDbDatabase* pHost,
- int activity,
- AcDbObjectId blockId
- );
- virtual void xrefSubcommandDetachItem(
- AcDbDatabase* pHost,
- int activity,
- AcDbObjectId blockId
- );
- public:
- static PTRFN_Notify mXrefCB;
- //...
- } ;
- // asdkMyEdReactor.cpp
- PTRFN_Notify asdkMyEdReactor::mXrefCB = NULL;
- void asdkMyEdReactor::xrefSubcommandUnloadItem(
- AcDbDatabase* pHost,
- int activity,
- AcDbObjectId blockId)
- {
- acutPrintf(ACRX_T("\nC++ : XRef выгружен."));
- // Проверяем не нулевой ли указатель на функцию уведомления
- if(mXrefCB != NULL)
- {
- // Уведомляем наш C#-модуль о выгрузке
- (mXrefCB)(1);
- }
- AcEditorReactor::xrefSubcommandUnloadItem(pHost, activity, blockId);
- }
- void asdkMyEdReactor::xrefSubcommandDetachItem(
- AcDbDatabase* pHost,
- int activity,
- AcDbObjectId blockId)
- {
- acutPrintf(ACRX_T("\nC++ : XRef удалён."));
- // Проверяем не нулевой ли указатель на функцию уведомления
- if(mXrefCB != NULL)
- {
- // Уведомляем наш C#-модуль об удалении
- (mXrefCB)(2);
- }
- AcEditorReactor::xrefSubcommandDetachItem(pHost, activity, blockId);
- }
- // Сохраняем указатель для последующего использования
- // Он будет использоваться для уведомления о выгрузке/удалении Xref.
- void SetXrefEventNotifyCB(PTRFN_Notify callBack)
- {
- asdkMyEdReactor::mXrefCB = callBack;
- }
3) Реализуем функцию обратного вызова в .NET-плагине и вызовем экспортированный метод при помощи делегата, инициализированного методом обратного вызова.
Код - C#: [Выделить]
- // Нужно для dllimport
- using System.Runtime.InteropServices;
- public delegate void XrefUnloadDelegate(int xrefUnloadType);
- // Делегат, который передается в .arx-модуль
- static XrefUnloadDelegate _xrefUnloadCB = null;
- // Получаем метод, экспортированный из .arx-модуля
- [DllImport("AdskXrefUnloadTest.arx", CharSet = CharSet.Auto)]
- public static extern void
- SetXrefEventNotifyCB(MulticastDelegate callback);
- // Функция обратного вызова, вызываемая из .arx-модуля, когда
- // Xref выгружается / удаляется
- // xrefUnloadType = 1 означает выгрузку
- // xrefUnloadType = 2 означает удаление
- public void xrefCB(int xrefUnloadType)
- {
- Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
- if (xrefUnloadType == 1)
- ed.WriteMessage("\nC# : XRef выгружен.");
- else if (xrefUnloadType == 2)
- ed.WriteMessage("\nC# : XRef удален.");
- else
- ed.WriteMessage("\nC# : XRef CB. Неизвестный тип выгрузки.");
- }
- void IExtensionApplication.Initialize()
- {
- if (_xrefUnloadCB == null)
- _xrefUnloadCB = new XrefUnloadDelegate(xrefCB);
- // Передаем функцию обратного вызова .arx-модулю
- SetXrefEventNotifyCB(_xrefUnloadCB);
- }
А вот и проект: Загрузить XrefUnloadDetach
Источник: http://adndevblog.typepad.com/autocad/2013/07/xref-unload-detach-event-in-net.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=466
Опубликовано 17.01.2014