C++ GRX SDK · OPM Properties Palette

Exposing Custom Entity & XDATA Properties in the GstarCAD Ctrl+1 Palette via OPM COM Interfaces (dev-cookbook-20)

Implement IDynamicProperty2 and ICategorizeProperties in C++ GRX to display custom categorized dropdowns and live engineering properties in GstarCAD 2027's Properties Palette.

1. How the Object Property Manager (`OPM`) Populates the `Ctrl+1` Palette

When an engineer selects an entity in GstarCAD 2027 and opens the Properties Palette (`Ctrl+1`), the Object Property Manager (`OPM`) inspects both the entity's static COM Automation wrapper (`IAcadEntity`) and any runtime **Dynamic Properties (`IDynamicProperty2`)** registered with the `IPropertyManager2` collection for that `AcRxClass`. Unlike static COM wrappers—which require compiling and registering a full `.tlb` IDL type library—`IDynamicProperty2` allows a C++ GRX plugin to inject custom categorized rows, unit-formatted numeric fields, and enumerated dropdown lists onto *any* native entity (such as `AcDbBlockReference` or `AcDbPolyline`) without subclassing `AcDbEntity`.

2. C++ ATL COM Implementation of `IDynamicProperty2` & `IDynamicEnumProperty`

The following C++ ATL class exposes a custom **"Fire Resistance Rating"** enumerated dropdown (`REI 60`, `REI 120`, `REI 180`, `REI 240`) under an **"ISO Structural BIM"** category in the Properties Palette whenever a user selects a wall or structural column in GstarCAD 2027, reading and writing the value directly to the entity's Extension Dictionary:

#include "grxHeaders.h"
#include "dynprops.h"

class ATL_NO_VTABLE GcFireRatingDynProp :
    public CComObjectRootEx<CComSingleThreadModel>,
    public IDynamicProperty2,
    public IDynamicEnumProperty,
    public ICategorizeProperties
{
public:
    BEGIN_COM_MAP(GcFireRatingDynProp)
        COM_INTERFACE_ENTRY(IDynamicProperty2)
        COM_INTERFACE_ENTRY(IDynamicEnumProperty)
        COM_INTERFACE_ENTRY(ICategorizeProperties)
    END_COM_MAP()

    STDMETHOD(GetDisplayName)(BSTR* pBstrName) override {
        *pBstrName = ::SysAllocString(L"Fire Resistance Class");
        return S_OK;
    }

    STDMETHOD(IsPropertyEnabled)(IUnknown* pUnk, BOOL* pbEnabled) override {
        *pbEnabled = TRUE;
        return S_OK;
    }

    // Group under custom collapsible category in Ctrl+1 Properties Palette
    STDMETHOD(MapPropertyToCategory)(DISPID dispid, PROPCAT* ppropcat) override {
        *ppropcat = 101;
        return S_OK;
    }
    STDMETHOD(GetCategoryName)(PROPCAT propcat, LCID lcid, BSTR* pbstrName) override {
        *pbstrName = ::SysAllocString(L"ISO 19650 Structural BIM");
        return S_OK;
    }

    // Enumerated Dropdown Options (0 = REI 60, 1 = REI 120, 2 = REI 180, 3 = REI 240)
    STDMETHOD(GetNumPropertyValues)(LONG* numValues) override {
        *numValues = 4;
        return S_OK;
    }
    STDMETHOD(GetPropValueName)(LONG index, BSTR* valueName) override {
        static const wchar_t* kRatings[] = { L"REI 60", L"REI 120", L"REI 180", L"REI 240" };
        if (index >= 0 && index < 4) *valueName = ::SysAllocString(kRatings[index]);
        return S_OK;
    }
};

3. Binding `IDynamicProperty2` to Native `AcRxClass` Descriptors

To attach `GcFireRatingDynProp` to all `AcDbPolyline` or `AcDbBlockReference` objects upon plugin initialization (`On_kInitAppMsg`), retrieve the class property manager via the macro GET_OPMPROPERTY_MANAGER(AcDbBlockReference::desc()) and call `AddProperty()`. When your plugin unloads (`On_kUnloadAppMsg`), always invoke `RemoveProperty()` and release the COM interface pointer so the Properties Palette refreshes cleanly without stale COM references.

  • Document Locking Inside `SetCurrentValueData()`: Because the Properties Palette is a modeless UI window running in the main application context, always instantiate AcAxDocLock docLock(objId.database(), AcAxDocLock::kNormal); inside `SetCurrentValueData()` before opening the target `AcDbObjectId` for write.
  • Real-Time Viewport Graphics Refresh: Call `m_pNotifySink->OnChanged(this)` after updating the Xrecord or XDATA so the Properties Palette and any associated viewport Overrules redraw immediately.

4. Implementing Per-Pickset Batch Editing & Unit Formatting in OPM

When a drafter selects 50 structural columns at once and changes your custom **"Fire Resistance Class"** dropdown in the `Ctrl+1` Properties Palette from `REI 60` to `REI 120`, GstarCAD's OPM host automatically loops through all 50 selected `LONG_PTR objectID` handles and invokes `IDynamicProperty2::SetCurrentValueData(LONG_PTR objectID, const VARIANT varData)` once per entity.

If two selected columns currently hold different fire ratings (`REI 60` vs. `REI 180`), OPM compares the `VARIANT` values returned by `GetCurrentValueData()` across the pickset and automatically displays the blank **`*VARIES*`** state in the combo box—matching native GstarCAD property behavior with zero extra UI code.

Validate This Workflow in GstarCAD 2027

Engineered by Suzhou Gstarsoft Co., Ltd. (SSE: 688657), GstarCAD 2027 delivers 100% native AC1032 DWG binary fidelity, perpetual licensing sovereignty, and zero-day AutoCAD command parity.

Download Free 30-Day Evaluation → Explore AutoCAD Migration Hub Take Skill Certification Quiz