Display Custom Properties of DWG in Navisworks – 2

By Xiaodong Liang

(continued with Display Custom Properties of DWG in Navisworks – 1)

  1. To Create a COM Wrapper for the custom entity, you can either place the COM implementation in an ARX project or in the same ObjectDBX project where your custom entity exists. Here we are going to see how to place the COM wrapper along with the custom entity itself. If you are interested to create a separate ARX, you can follow the same step explained to create a custom entity where instead of selecting a Project type as “ObjecDBX” , select the Application Type as “ObjectARX” (as mentioned in Step1 – Application Type Dialog) and the continue with the following steps.

image

  1. Input the wrapper name as “NW_DBX_Curve_Wrapper”. In the COM wrapper tab, put the name of your DBX without the .dbx extension as "AdskDemoCurve" in the “DBX Classname” textbox . Select Ok to finish, and build to test for errors. Take a look NW_DBX_Curve_Wrapper.cpp and .h to see what the wizard has added for us.

image

 

  1. Add necessary code for the custom entity

   9.1 AsdkDemoCurve.h

public: 
    // assign the CLSID of the wrapper to 
    //be returned by the subGetClassID 
     // method of our custom entity 
    virtual Acad::ErrorStatus subGetClassID(CLSID * pClsid) const; 
    //set the member variable - long 
    Acad::ErrorStatus setPropertyLong(long val) ; 
    //get the member variable - long 
    long getPropertyLong()const; 
    //set the member variable - double 
    Acad::ErrorStatus setPropertyDouble(double val) ; 
    //get the member variable - double 
    long getPropertyDouble()const; 
    private: 
    // member variable - long 
    long m_propertylong; 
    //member variable - double 
    double m_propertydouble;

9.2 AsdkDemoCurve.cpp

// include the COM wrapper 
#include "NW_AutoCAD_OE_Sample_i.c" 
//initialize the member variables 
AsdkDemoCurve::AsdkDemoCurve () : AcDbCurve () 
{ 
    m_propertylong = 2; 
    m_propertydouble = 10; 
} 
//draw some custom geometires. 
//To similfy the sample, the code draws a 
 
//fixed circle and text. 
Adesk::Boolean AsdkDemoCurve::
    subWorldDraw (AcGiWorldDraw *mode) 
{ 
    assertReadEnabled () ; 
    mode->geometry().circle(
        AcGePoint3d(m_propertydouble,0,0),
        10,
        AcGeVector3d(0,0,1)); 
    mode->geometry().text(
        AcGePoint3d(m_propertydouble,0,0),
        AcGeVector3d(0,0,1),
        AcGeVector3d(1,0,0),
        m_propertylong,1,
        0,
        _T("MyCurve")); 
    return (AcDbCurve::subWorldDraw (mode)) ; 
} 
// return the COM wrapper ID 
Acad::ErrorStatus AsdkDemoCurve::subGetClassID(CLSID * pClsid) const 
{ 
    //locate the file ' NW_AutoCAD_OE_Sample_i.c ', 
    // and open it in VS (this //file may not already be
    // included in the VC project).
    // Look for and copy 
 
    //the CLSID definition name (eg CLSID_NW_DBX_Curve_Wraper) 
    assertReadEnabled(); 
    *pClsid=CLSID_NW_DBX_Curve_Wraper; 
    return Acad::eOk; 
} 
//set the member variable - long 
Acad::ErrorStatus AsdkDemoCurve::setPropertyLong(long val) 
{ 
    assertWriteEnabled(); 
    m_propertylong = val; 
    return Acad::eOk ; 
} 
//get the member variable - long 
long AsdkDemoCurve::getPropertyLong()const 
{ 
    assertReadEnabled(); 
    return m_propertylong; 
} 
//set the member variable - double 
Acad::ErrorStatus AsdkDemoCurve::setPropertyDouble (double val) 
{ 
    assertWriteEnabled(); 
    m_propertydouble = val; 
    return Acad::eOk ; 
} 
//get the member variable - double 
long AsdkDemoCurve::getPropertyDouble()const 
{ 
    assertReadEnabled(); 
    return m_propertydouble; 
}
  1. Now we provide the interface methods to communicate with those two custom properties of this entity, a long and a double. Switch to Class View, select INW_DBX_Curve_Wrapper and Add Property. Select the property type Long and provide the name “PropertyLong”. Then finish. Repeat the operation to provide a double property.

image

image

 

image

 

10.1 NW_DBX_Curve_Wraper.h

//configure in which category 
//(of AutoCAD) the properties would be displayed. 
//    In this sample, we put them in Data category. 
 
//IOPMPropertyExtension 
BEGIN_OPMPROP_MAP() 
    //----- Use the OPMPROP_ENTRY/OPMPROP_CAT_ENTRY macros for each of your properties 
    OPMPROP_ENTRY(0, 0x00000001, 
        PROPCAT_Data, 0, 0, 0,
        _T(""), 0, 1, 
        IID_NULL, 
        IID_NULL, "") 
    OPMPROP_ENTRY(0, 0x00000002, 
        PROPCAT_Data, 0, 0, 0,
        _T(""), 0, 1, 
        IID_NULL, 
        IID_NULL, "") 
END_OPMPROP_MAP() 
//IOPMPropertyExtensionImpl 
// It is a pity VS does not generate the properties 
//Set/Get methods codes 
//automatically. We need to write as below: 
public: 
//INW_DBX_Curve_Wraper 
STDMETHOD(get_PropertyLong)(/*[out, retval]*/ LONG *pVal); 
STDMETHOD(put_PropertyLong)(/*[in]*/ LONG newVal); 
STDMETHOD(get_PropertyDouble)(/*[out, retval]*/ DOUBLE *pVal); 
STDMETHOD(put_PropertyDouble)(/*[in]*/ DOUBLE newVal);

 

10.2 NW_DBX_Curve_Wraper.cpp

//get property - long 
STDMETHODIMP CNW_DBX_Curve_Wraper::
    get_PropertyLong(LONG *pVal) 
{ 
    try 
    { 
        Acad::ErrorStatus es; 
        AcAxObjectRefPtr 
            pLine(&m_objRef,AcDb::kForRead,
            Adesk::kTrue); 
        if((es=pLine.openStatus()) != Acad::eOk) 
        throw es; 
        *pVal = pLine->getPropertyLong(); 
    } 
    catch(const Acad::ErrorStatus) 
    { 
    return Error(L"Failed to open object.",
        IID_INW_DBX_Curve_Wraper,E_FAIL); 
    } 
    catch(const HRESULT hr) 
    { 
    return Error(L"Invalid argument.",
        IID_INW_DBX_Curve_Wraper,hr); 
    } 
    return S_OK; 
} 
//set property - long 
STDMETHODIMP CNW_DBX_Curve_Wraper::
    put_PropertyLong(LONG newVal) 
{ 
    try 
    { 
        Acad::ErrorStatus es; 
        AcAxObjectRefPtr 
            pLine(&m_objRef,AcDb::kForWrite,Adesk::kTrue); 
        if((es=pLine.openStatus()) != Acad::eOk) 
        throw es; 
        pLine->setPropertyLong(newVal); 
    } 
    catch(const Acad::ErrorStatus) 
    { 
        return Error(L"Failed to set PropertyLong.",
            IID_INW_DBX_Curve_Wraper,E_FAIL); 
    } 
    catch(const HRESULT hr) 
    { 
        return Error(L"Invalid argument.",
            IID_INW_DBX_Curve_Wraper,hr); 
    } 
    return S_OK; 
} 
//get property - double 
STDMETHODIMP CNW_DBX_Curve_Wraper::
    get_PropertyDouble(DOUBLE *pVal) 
{ 
    try 
    { 
        Acad::ErrorStatus es; 
        AcAxObjectRefPtr 
            pLine(&m_objRef,AcDb::kForRead,
            Adesk::kTrue); 
        if((es=pLine.openStatus()) != Acad::eOk) 
        throw es; 
        *pVal = pLine->getPropertyDouble(); 
    } 
    catch(const Acad::ErrorStatus) 
    { 
    return Error(L"Failed to open object.",
        IID_INW_DBX_Curve_Wraper,E_FAIL); 
    } 
    catch(const HRESULT hr) 
    { 
    return Error(L"Invalid argument.",
        IID_INW_DBX_Curve_Wraper,hr); 
    } 
    return S_OK; 
} 
//set property - double 
STDMETHODIMP CNW_DBX_Curve_Wraper::
    put_PropertyDouble(DOUBLE newVal) 
{ 
    try 
    { 
        Acad::ErrorStatus es; 
        AcAxObjectRefPtr pLine(
            &m_objRef,AcDb::kForWrite,
            Adesk::kTrue); 
        if((es=pLine.openStatus()) != Acad::eOk) 
        throw es; 
        pLine->setPropertyDouble(newVal); 
    } 
    catch(const Acad::ErrorStatus) 
    { 
    return Error(L"Failed to set PropertyLong.",
        IID_INW_DBX_Curve_Wraper,E_FAIL); 
    } 
    catch(const HRESULT hr) 
    { 
    return Error(L"Invalid argument.",
        IID_INW_DBX_Curve_Wraper,hr); 
    } 
    return S_OK; 
}
  1. Now build the DBX to see if there is error.
    12. Run AutoCAD, and load our DBX. This will register the COM server automatically.
    13. Optional: We should now verify that the ObjectDBX registry entries have been made properly. Run RegEdit.exe to access the Windows registry, and navigate to HKEY_LOCAL_MACHINE>SOFTWARE>Autodesk>ObjectDBX>R18.1>ActiveXCLSID. Look for a key called AsdkDemoCurve. The CLSID string value within it should be the same as the CLSID found in the IDL file for your custom wrapper, under INW_DBX_Curve_Wraper. Example:
    image
     

We can now create a simple COM client to create and manipulate our custom line.. This will allow us to use objects defined by this TLB, namely, our custom wrapper. Create a VB.NET project, add the tlb and add the following code:

<CommandMethod("addEnt")> _
   Public Sub addEnt()
      Dim oAcadApp As AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication
      Dim myDemo As NW_DBX_Curve_Wraper
      myDemo = oAcadApp.ModelSpace.AddCustomObject("AsdkDemoCurve")
   End Sub

Load the .NET dll and run command addEnt.

 

image

 

image


Comments

Leave a Reply

Discover more from Autodesk Developer Blog

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

Continue reading