Presentation is loading. Please wait.

Presentation is loading. Please wait.

Copyright © 2002 ESRI. All rights reserved. Advanced ArcObjects Component Development II (C++) Advanced geodatabase customization.

Similar presentations


Presentation on theme: "Copyright © 2002 ESRI. All rights reserved. Advanced ArcObjects Component Development II (C++) Advanced geodatabase customization."— Presentation transcript:

1 Copyright © 2002 ESRI. All rights reserved. Advanced ArcObjects Component Development II (C++) Advanced geodatabase customization

2 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-2 Lesson 5 overview Accessing features with COM Geodatabase customization directions Class extensions Custom features Exercise 5: MudBank custom feature

3 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-3 Accessing features COM GeoDatabase API Application Database COM Geodatabase API Application Database

4 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-4 Application ArcMap Editor Database Class extensions Custom features Some application customizations can be accomplished at the database level Example: Event handling for feature creation Levels of geodatabase customization Application COM GDB API Clients Database

5 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-5 Database-level customizations Change the default behavior of a feature class (e.g., new validation rules, custom database updates) Two ways to implement behavior Class extensions: Only loaded once when class is created Custom features/objects: Applies to feature when created Only applies to feature classes in a Personal or ArcSDE geodatabase

6 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-6 Class extensions Adds class-level behavior to object classes Higher-level customization than custom features Object is created when data is accessed Common uses Custom editing behavior Custom rules and validation Custom drawing: Renderers Custom property inspector Related object notification Custom split policies

7 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-7 Relationship between a class and an extension NameID 1Laterals CLSID { … EXTCLSID {0368CF51… Feature classes ClassExtension 2Mains { … Only one extension can be associated with a class Component requires registration On each client system In categories: ESRI GeoObject Class Extension Must associate class with new class extension Insert GUID with UML or ArcObjects code

8 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-8 Accessing the class from the extension IClassExtension::Init() IClassHelper – Reference is passed in IClassHelper::Class – Acquire a reference to the class (e.g., m_ipClass ) IClassExtension::Shutdown() Release m_ipClass reference STDMETHODIMP CMBClassExtension::Init(IClassHelper *pClassHelper,IPropertySet *pPropSet) { if (!pClassHelper) return E_POINTER; HRESULT hr; IClassPtr ipClass; hr = pClassHelper->get_Class(&m_ipClass); return S_OK; } STDMETHODIMP CMBClassExtension::Init(IClassHelper *pClassHelper,IPropertySet *pPropSet) { if (!pClassHelper) return E_POINTER; HRESULT hr; IClassPtr ipClass; hr = pClassHelper->get_Class(&m_ipClass); return S_OK; }

9 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-9 Accessing data with a class extension Data can be stored with a feature class Clients can access data via extension PropertySet is passed in upon initialization Can also write data (property set) to the class IClassSchemaEdit::AlterClassExtensionProperties STDMETHODIMP CMBClassExtension::Init(IClassHelper *pClassHelper,IPropertySet *pPropSet) { // Read stored symbol from property set CComVariant vSymbol; pPropSet->GetProperty(CComBstr("symbol"), &vSymbol); IUnknownPtr ipUnk(vSymbol.ppUnkVal); m_ipSymbolForFeatures = ipUnk; } STDMETHODIMP CMBClassExtension::Init(IClassHelper *pClassHelper,IPropertySet *pPropSet) { // Read stored symbol from property set CComVariant vSymbol; pPropSet->GetProperty(CComBstr("symbol"), &vSymbol); IUnknownPtr ipUnk(vSymbol.ppUnkVal); m_ipSymbolForFeatures = ipUnk; }

10 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ClassExtensions and object events Implement IObjectClassEvents Not an outbound interface Similar to Editor events // TrackLifecycleExt.cpp // IClassExtension STDMETHODIMP TrackLifecycleExt::Init (IClassHelper * pClassHelper, IPropertySet * pExtensionProperties) {… IClassPtr ipClass; ipFeatureClass->FindField (CComBSTR( L"CreationDate"),&m_creationDate)))… } // IObjectClassEvents STDMETHODIMP CTrackLifecycleExt::OnCreate (IObject * obj) {… SYSTEMTIME systemTime; DOUBLE dTime; ::GetLocalTime(&systemTime); ::SystemTimeToVariantTime(&systemTime, &dTime); CComVariant vTime(dTime); if (FAILED(hr = obj->put_Value (m_creationDate, vTime))) } // TrackLifecycleExt.cpp // IClassExtension STDMETHODIMP TrackLifecycleExt::Init (IClassHelper * pClassHelper, IPropertySet * pExtensionProperties) {… IClassPtr ipClass; ipFeatureClass->FindField (CComBSTR( L"CreationDate"),&m_creationDate)))… } // IObjectClassEvents STDMETHODIMP CTrackLifecycleExt::OnCreate (IObject * obj) {… SYSTEMTIME systemTime; DOUBLE dTime; ::GetLocalTime(&systemTime); ::SystemTimeToVariantTime(&systemTime, &dTime); CComVariant vTime(dTime); if (FAILED(hr = obj->put_Value (m_creationDate, vTime))) } // TrackLifecycleExt.h class ATL_NO_VTABLE CTrackLifecycleExt : public ITrackLifecycleExt, public IClassExtension, public IObjectClassEvents {… // TrackLifecycleExt.h class ATL_NO_VTABLE CTrackLifecycleExt : public ITrackLifecycleExt, public IClassExtension, public IObjectClassEvents {…

11 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ClassExtensions and custom drawing Basic requirements 1. Implement IFeatureClassDraw 2. Renderer: esriCore or a custom renderer 3. Property page: esriCore or custom page IFeatureClassDraw members HasCustomRenderer – You have written your own renderer CustomRenderer – Reference render to use always ExclusiveCustomRenderer – User can change renderers via GUI CustomRendererPropPageCLSID – Your custom property page

12 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Custom renderers Implement IFeatureRenderer Draw, PrepareFilter, ExclusionSet ILegendInfo – Create symbols for the TOC IPersistStream – Store LegendGroup and symbols STDMETHODIMP CMBRenderer::Draw(IFeatureCursor *pFeatureCursor,esriDrawPhase drawPhase,IDisplay *pDisplay,ITrackCancel *pTrackCancel) { // Just draw special if Geography, otherwise use default if (drawPhase != esriDPGeography)return E_NOTIMPL; // Loop through all the MudBanks, unioning all the Mudbanks into one polygon IGeometryPtr ipMudBankGeom(CLSID_Polygon); IFeaturePtr ipFeature; IMBClassExtensionPtr ipClassExtension; while (pFeatureCursor->NextFeature(&ipFeature) == S_OK) { // Do specialized drawing here… ipFeature->get_Shape(&ipFeatureGeom); ::Draw(pDisplay, ipSym, ipLandGeom) } … } STDMETHODIMP CMBRenderer::Draw(IFeatureCursor *pFeatureCursor,esriDrawPhase drawPhase,IDisplay *pDisplay,ITrackCancel *pTrackCancel) { // Just draw special if Geography, otherwise use default if (drawPhase != esriDPGeography)return E_NOTIMPL; // Loop through all the MudBanks, unioning all the Mudbanks into one polygon IGeometryPtr ipMudBankGeom(CLSID_Polygon); IFeaturePtr ipFeature; IMBClassExtensionPtr ipClassExtension; while (pFeatureCursor->NextFeature(&ipFeature) == S_OK) { // Do specialized drawing here… ipFeature->get_Shape(&ipFeatureGeom); ::Draw(pDisplay, ipSym, ipLandGeom) } … }

13 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Methods of applying class extensions During creation IFeatureWorkspace::CreateFeatureClass(pExtCLSID…) After creation IClassSchemaEdit::AlterClassExtensionCLSID(pExtCLSID…) After creation and class extension is missing IFeatureWorkspaceSchemaEdit::AlterClassExtensionCLSID When modeling and designing in Visio Create class extension and make association via UML Set the CLSID tagged value to the component

14 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Custom objects Extends row-level behavior for a class Requires aggregation of an esriCore::Feature Why create custom objects? Complex network features: Switch gear Custom features: Drawing, row updating ESRI: Feature-link annotation and dimension The reality… Most customizations can be accomplished with class extensions Do not want to compromise GDB integrity

15 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved COM containment Simplest form of binary reuse Delegate requests to inner object Provide custom behavior for selected members Can wrap any coclass (e.g., esriCore commands) esriCore. AddDataCommand IUnknow n MyAddDataCmd ICommand IUnknown (inner) ICommand IMyAddDataCmd Instructor Demo

16 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved COM aggregation Use to create custom features Exposes interfaces of inner object directly Provide implementation for contained interface/methods ICustomFeature Feature IUnknown (controlling Unknown) CustomFeature IFeature IUnknown (inner) IFeatureDraw IFeatureBuffer IFeatureDraw IFeatureEdit IFeatureEvents

17 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ATL macros for aggregation One macro exposes controlling IUnknown (outer) Another allows the class to be aggregated Implement the interfaces you wish to contain // MBFeature.h : Declaration of the CMBFeature public: CMBFeature() : m_pInnerUnk(NULL) { } DECLARE_GET_CONTROLLING_UNKNOWN() … BEGIN_COM_MAP(CMBFeature) COM_INTERFACE_ENTRY(IMBFeature) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IFeatureDraw) COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pInnerUnk) END_COM_MAP() BEGIN_CATEGORY_MAP(CMBFeature) // Register in this component category IMPLEMENTED_CATEGORY(CATID_GeoObjects) END_CATEGORY_MAP() }; // MBFeature.h : Declaration of the CMBFeature public: CMBFeature() : m_pInnerUnk(NULL) { } DECLARE_GET_CONTROLLING_UNKNOWN() … BEGIN_COM_MAP(CMBFeature) COM_INTERFACE_ENTRY(IMBFeature) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IFeatureDraw) COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pInnerUnk) END_COM_MAP() BEGIN_CATEGORY_MAP(CMBFeature) // Register in this component category IMPLEMENTED_CATEGORY(CATID_GeoObjects) END_CATEGORY_MAP() };

18 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Aggregating an esriCore::Feature in ATL Cocreate esriCore object in FinalConstruct() Hook inner and outer objects together via IUnknown Get a reference to inner interface for containment // MBFeature.cpp HRESULT CMBFeature::FinalConstruct() { // Get outer object since this object may be aggregated in as well. IUnknown * pOuter = GetControllingUnknown(); // Aggregate in ESRI's simple Feature object if (FAILED (CoCreateInstance(CLSID_Feature, pOuter, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &m_pInnerUnk))) return E_FAIL; // Get reference to inner feature IFeatureDraw if (FAILED(m_pInnerUnk->QueryInterface(IID_IFeatureDraw, (void**)&m_pFeatureDraw))) return E_FAIL; return S_OK; } // MBFeature.cpp HRESULT CMBFeature::FinalConstruct() { // Get outer object since this object may be aggregated in as well. IUnknown * pOuter = GetControllingUnknown(); // Aggregate in ESRI's simple Feature object if (FAILED (CoCreateInstance(CLSID_Feature, pOuter, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &m_pInnerUnk))) return E_FAIL; // Get reference to inner feature IFeatureDraw if (FAILED(m_pInnerUnk->QueryInterface(IID_IFeatureDraw, (void**)&m_pFeatureDraw))) return E_FAIL; return S_OK; }

19 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Custom drawing behavior // MBFeature.cpp … // IFeatureDraw STDMETHODIMP CMBFeature::get_InvalidArea(IInvalidArea** ppInvalidArea) { return m_pFeatureDraw->get_InvalidArea(ppInvalidArea); // Use containment } STDMETHODIMP CMBFeature::putref_InvalidArea(IInvalidArea* pInvalidArea) { return m_pFeatureDraw->putref_InvalidArea(pInvalidArea); // Use containment } // Override the Draw method of IFeatureDraw STDMETHODIMP CMBFeature::Draw(esriDrawPhase drawPhase, IDisplay* pDisplay, ISymbol* pSymbol, VARIANT_BOOL SymbolInstalled, IGeometry* pGeometry, esriDrawStyle drawStyle) { … // Get the ClassExtension because it has the symbols and methods ipClassExtension->get_LandSymbol(&ipSym); ipClassExtension->get_IntersectingLandGeometry(ipMudBankGeom,&ipLandGeom); ::Draw(pDisplay, ipSym, ipLandGeom); return S_OK; } // MBFeature.cpp … // IFeatureDraw STDMETHODIMP CMBFeature::get_InvalidArea(IInvalidArea** ppInvalidArea) { return m_pFeatureDraw->get_InvalidArea(ppInvalidArea); // Use containment } STDMETHODIMP CMBFeature::putref_InvalidArea(IInvalidArea* pInvalidArea) { return m_pFeatureDraw->putref_InvalidArea(pInvalidArea); // Use containment } // Override the Draw method of IFeatureDraw STDMETHODIMP CMBFeature::Draw(esriDrawPhase drawPhase, IDisplay* pDisplay, ISymbol* pSymbol, VARIANT_BOOL SymbolInstalled, IGeometry* pGeometry, esriDrawStyle drawStyle) { … // Get the ClassExtension because it has the symbols and methods ipClassExtension->get_LandSymbol(&ipSym); ipClassExtension->get_IntersectingLandGeometry(ipMudBankGeom,&ipLandGeom); ::Draw(pDisplay, ipSym, ipLandGeom); return S_OK; } Call Draw() function in IFeature::Draw

20 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Relationship between a feature and a class One feature object can be associated with a class Component requires registration On each client system In categories: ESRI GeoObjects Must associate feature with class Insert GUID with UML or ArcObjects code NameID 1Laterals CLSID { … EXTCLSID {0368CF51… Feature classes CustomFeature 2Mains { …

21 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Use the selected object in ArcCatalog Access IClassSchemaEdit, just like class extensions Registering a custom feature Public Sub LoadClassExtension() Dim pGxApp As IGxApplication Dim pGxCatalog As IGxCatalog Dim pGxSelection As IGxSelection Set pGxApp = Application Set pGxCatalog = pGxApp.Catalog Set pGxSelection = pGxCatalog.Selection Dim pGxEnum As IEnumGxObject Set pGxEnum = pGxSelection.SelectedObjects pGxEnum.Reset Dim pGxObject As IGxObject Set pGxObject = pGxEnum.Next If (pGxObject Is Nothing) Then Set pGxObject = pGxCatalog.SelectedObject Public Sub LoadClassExtension() Dim pGxApp As IGxApplication Dim pGxCatalog As IGxCatalog Dim pGxSelection As IGxSelection Set pGxApp = Application Set pGxCatalog = pGxApp.Catalog Set pGxSelection = pGxCatalog.Selection Dim pGxEnum As IEnumGxObject Set pGxEnum = pGxSelection.SelectedObjects pGxEnum.Reset Dim pGxObject As IGxObject Set pGxObject = pGxEnum.Next If (pGxObject Is Nothing) Then Set pGxObject = pGxCatalog.SelectedObject If (TypeOf pGxObject Is IGxDataset) Then Dim pGxDataset As IGxDataset Dim pObjectClass As IObjectClass Dim pClassSchemaEdit As IClassSchemaEdit Set pGxDataset = pGxObject ' QI Set pObjectClass = pGxDataset.Dataset Set pClassSchemaEdit = pObjectClass Dim pUid As New UID pUid.Value = "{82F517DC-C600-11D C7E61A96}" //pClassSchemaEdit.AlterClassExtensionCLSID pUid, Nothing pClassSchemaEdit.AlterInstanceCLSID pUid End If End Sub If (TypeOf pGxObject Is IGxDataset) Then Dim pGxDataset As IGxDataset Dim pObjectClass As IObjectClass Dim pClassSchemaEdit As IClassSchemaEdit Set pGxDataset = pGxObject ' QI Set pObjectClass = pGxDataset.Dataset Set pClassSchemaEdit = pObjectClass Dim pUid As New UID pUid.Value = "{82F517DC-C600-11D C7E61A96}" //pClassSchemaEdit.AlterClassExtensionCLSID pUid, Nothing pClassSchemaEdit.AlterInstanceCLSID pUid End If End Sub

22 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Modeling custom features in Visio Inherit from esriCore::Feature Assign custom feature via tagged values (CLSID) Define other public members if necessary Export to repository

23 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Building a Visual Studio workspace Use ESRI Code Generation add-in to import repository Creates an ATL project Aggregates an esriCore::Feature object Choose interface and members to contain Adds public members modeled in Visio Example: IBuilding::Age() and IBuilding::Owner() Create the schema Import repository to a database in ArcCatalog Automatically applies GUIDs modeled See Case Tools tutorial for more details

24 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Exercise 5 overview Aggregate in an esriCore::Feature Implement IFeatureDraw Implement a class extension Add a renderer and property page Challenge: Persistence CMBClassExtension CMBRendererPropertyPage IClassExtension IFeatureClassExtension IFeatureClassDraw IPropertyPage IPropertyPageContext IUnknow n IFeatureDraw CMBFeature IFeature esriCore::Feature IFeatureRenderer CMBRenderer ILegendInfo IPersistStream IMBClassExtension

25 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Review When should you write a custom feature? How do you register a custom feature with a feature class? What other objects are often created with custom features or extensions? When should you use IEditorEvents versus IObjectClassEvents ? What happens when a client application accesses a feature class, but does not have the custom feature DLL registered on their system?

26 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 5-26


Download ppt "Copyright © 2002 ESRI. All rights reserved. Advanced ArcObjects Component Development II (C++) Advanced geodatabase customization."

Similar presentations


Ads by Google