派生自 IAcadBaseObject2Impl
AsdkSquareWrapper_DG SDK 示例不会创建或操作非驻留在数据库中的对象。如果检查其源代码,可能会注意到包装类似乎不是从 或 派生的。但是,它被设置为支持非数据库驻留的对象。这是可能的,因为包装类派生自包装类,而包装类又派生自 。该类继承实现。如果对象派生自 或 ,则不需要显式派生自 。CAsdkSquareWrapperIAcadBaseObjectImplIAcadBaseObject2ImplIAcadEntityDispatchImplIAcadObjectDispatchImplIAcadObjectDispatchImplIAcadBaseObject2ImplIAcadEntityDispatchImplIAcadObjectDispatchImplIAcadBaseObject2Impl IAcadBaseObject主要区别在于它们识别物体的方式。驻留在数据库中的对象可以通过其对象 ID 进行唯一标识。此 ID 是用于引用它包装的对象的键。未为不驻留在数据库中的对象分配对象 ID,因此替换指向实例的指针。IAcadBaseObject2IAcadBaseObjectIAcadBaseObject2AcDbObject 为了支持此抽象,属性选项板 API 提供了类和模板类。对象封装对实例的引用。此类支持驻留对象和非驻留对象。 是一个“智能指针”类,它使应用程序可以轻松处理这两种类型的对象。模板类的代码用法可以替换为需要支持非数据库驻留对象的应用程序中的引用。AcAxObjectRefAcAxObjectRefPtrAcAxObjectRefAcDbObjectAcAxObjectRefPtrAcDbObjectPointerAcAxObjectRefPtr AsdkSquareWrapper_DG SDK 示例(实现非驻留数据库支持)提供了以下过程的代码示例。 实现对非数据库驻留对象的支持在 COM 包装器的头文件中,将 COM 接口条目添加到接口的 COM 映射中:IAcadBaseObject2 BEGIN_COM_MAP(CAsdkSquareWrapper) ... COM_INTERFACE_ENTRY(IAcadBaseObject) COM_INTERFACE_ENTRY(IAcadBaseObject2) ... END_COM_MAP() 请注意,COM 映射同时公开了 和 。IAcadBaseObjectIAcadBaseObject2 在 COM 包装器的头文件中,声明实现方法的所需替代:IAcadBaseObject2 STDMETHOD(ForceDbResident)(VARIANT_BOOL *forceDbResident); STDMETHOD(AddToDb)(AcDbObjectId& objId, AcDbObjectId ownerId = AcDbObjectId::kNull, TCHAR* keyName = NULL); STDMETHOD(CreateObject)(AcDbObjectId ownerId = AcDbObjectId::kNull, TCHAR *keyName = NULL); 将任何实例替换为 。例如:AcDbObjectPointerAcAxObjectRefPtr AcDbObjectPointer<AsdkSquare> pSq(m_objId, AcDb::kForRead); 替换为 AcAxObjectRefPtr<AsdkSquare> pSq(&m_objRef, AcDb::kForRead); 在 COM 包装的 CPP 文件中,实现所需的方法。如果支持非驻留数据库的对象,则必须实现 、 和 函数。AsdkSquareWrapper_DG SDK 示例定义了这些方法,如下所示:IAcadBaseObject2Impl ForceDbResident()AddToDb()CreateObject() HRESULT CAsdkSquareWrapper::ForceDbResident(VARIANT_BOOL *forceDbResident) { if (NULL == forceDbResident) return E_POINTER; *forceDbResident = ACAX_VARIANT_FALSE; return S_OK; } HRESULT CAsdkSquareWrapper::AddToDb(AcDbObjectId& objId, AcDbObjectId ownerId, TCHAR* keyName) { try { AcAxDocLock docLock(ownerId); Acad::ErrorStatus es; AcAxObjectRefPtr<AsdkSquare> pSq(&m_objRef, AcDb::kForRead); AcDbBlockTableRecordPointer pBlockTableRecord(ownerId, AcDb::kForWrite); if((es = pBlockTableRecord.openStatus()) != Acad::eOk) throw es; if((es = pBlockTableRecord->appendAcDbEntity(objId, pSq.object())) != Acad::eOk) throw es; } catch(const Acad::ErrorStatus) { return Error(L"Failed to add square to database", IID_IAsdkSquareWrapper ,E_FAIL); } return SetObjectId(objId); } HRESULT CAsdkSquareWrapper::CreateObject(AcDbObjectId ownerId, TCHAR *keyName) { try { Acad::ErrorStatus es; AcDbObjectPointer<AsdkSquare> pSq; if((es = pSq.create()) != Acad::eOk) throw es; pSq->setDatabaseDefaults(ownerId.database()); AsdkSquare *pTmp = NULL; pSq.release(pTmp); SetObject((AcDbObject*&)pTmp); } catch(const Acad::ErrorStatus) { return Error(L"Failed to create square", IID_IAsdkSquareWrapper, E_FAIL); } return S_OK; } 修改包装对象时调用该函数。例如,每个属性访问或方法都应显式调用此函数,如下所示:IAcadBaseObject2Impl::Fire_Notification()put_* STDMETHODIMP CAsdkSquareWrapper::put_Number(short newVal) { AcAxDocLock docLock(m_objRef.objectId(), AcAxDocLock::kNormal); if(docLock.lockStatus() != Acad::eOk && docLock.lockStatus() != Acad::eNoDatabase) return E_ACCESSDENIED; AcAxObjectRefPtr<AsdkSquare> pSq(&m_objRef, AcDb::kForWrite); if (pSq.openStatus() != Acad::eOk) return E_ACCESSDENIED; pSq->setSquareId(newVal);Fire_Notification(DISPID_NUMBER);return S_OK; } 该函数将更改通知连接的侦听器。侦听器是实现和接口的对象。此机制对于将“属性”选项板编辑与命令行输入同步非常重要,如“属性选项板与命令交互”中所述。Fire_Notification()IAcadObjectEventsIPropertyNotifySink 驻留在数据库中的对象不需要调用该函数。他们的通知由 AutoCAD Reactor 处理。Fire_Notification() 父主题: |
|Archiver|CAD开发者社区
( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-3-14 06:29
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.