XRef Unload / Detach event in .Net

By Balaji Ramamoorthy

In an ObjectARX application, to get a notification after an XRef has been unloaded or detached, it is needed to override the “AcEditorReactor::xrefSubcommandUnloadItem” and “AcEditorReactor::xrefSubcommandDetachItem” in the editor reactor class. Unfortunately, there is no equivalent of these methods in the AutoCAD .Net API. 

A workaround for getting this notification in a .Net plugin is implemented in the attached project.

For the complete code, please refer to the attachment. The steps with only the relevant code are : 

1) Export a method from the .arx which accepts a function pointer to use for notification.

// Function pointer that we will store in our editor reactor
typedef void (__stdcall *PTRFN_Notify)(int xrefUnloadType);
 
// Exported method that will be called from .Net
extern "C" DLLIMPEXP 
            void SetXrefEventNotifyCB(PTRFN_Notify callBack);

2) Implement an editor reactor in the ObjectARX module.

// asdkMyEdReactor.h
 
class asdkMyEdReactor : public AcEditorReactor 
{
protected:
    // Override virtual functions to get notified about Xref
    // unload / detach.
    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 unloaded."));
 
    // Check if we have a function pointer that we can use to notify
    if(mXrefCB != NULL)
    {
        // Notify our C# module about unload
        (mXrefCB)(1);
    }
    AcEditorReactor::xrefSubcommandUnloadItem(pHost, activity, blockId);
}
 
void asdkMyEdReactor::xrefSubcommandDetachItem(
                                        AcDbDatabase* pHost, 
                                        int activity, 
                                        AcDbObjectId blockId)
{
    acutPrintf(ACRX_T("nC++ : XRef detached."));
 
    // Check if we have a function pointer that we can use to nofity.
    if(mXrefCB != NULL)
    {
        // Notify our C# module about detach
        (mXrefCB)(2);
    }
    AcEditorReactor::xrefSubcommandDetachItem(pHost, activity, blockId);
}
 
// Store the function pointer for future use.
// This will used to notify when Xref unload/detach happens.
void SetXrefEventNotifyCB(PTRFN_Notify callBack)
{
    asdkMyEdReactor::mXrefCB = callBack;
}

3) Implement a callback method in .Net plugin and invoke the exported method with a delegate initialized to the callback method.

// Needed for dllimport
using System.Runtime.InteropServices;
 
public delegate void XrefUnloadDelegate(int xrefUnloadType);
 
// Delegate that will be passed to the .arx module
static XrefUnloadDelegate _xrefUnloadCB = null;
 
// Get the method exposed in the .arx module 
[DllImport("AdskXrefUnloadTest.arx", CharSet = CharSet.Auto)]
public static extern void 
            SetXrefEventNotifyCB(MulticastDelegate callback);
 
// Callback that will be invoked from .arx module when 
// an Xref unload / detach happens
// xrefUnloadType = 1 indicates a unload
// xrefUnloadType = 2 indicates a detach
public void xrefCB(int xrefUnloadType)
{
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    if (xrefUnloadType == 1)
        ed.WriteMessage("nC# : XRef unloaded.");
    else if (xrefUnloadType == 2)
        ed.WriteMessage("nC# : XRef detached.");
    else
        ed.WriteMessage("nC# : XRef CB. Unload type unknown.");
}
 
void IExtensionApplication.Initialize()
{
    if (_xrefUnloadCB == null)
        _xrefUnloadCB = new XrefUnloadDelegate(xrefCB);
 
    // Provide the callback to the .arx module 
    SetXrefEventNotifyCB(_xrefUnloadCB);
}

Here is the sample project :

Download XrefUnloadDetach


Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading