copyright © 2002 esri. all rights reserved. advanced arcobjects component development ii (c++)...

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

Upload: ian-hutchison

Post on 26-Mar-2015

225 views

Category:

Documents


1 download

TRANSCRIPT

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

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

Advanced geodatabase customization

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

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

Lesson 5 overview

Accessing features with COM

Geodatabase customization directions

Class extensions

Custom features

Exercise 5: MudBank custom feature

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

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

Accessing features

COM

GeoDatabase API

Application

DatabaseCOM

Geodatabase API

Application

Database

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

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

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

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

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

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

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

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

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

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

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

Relationship between a class and an extension

NameID

1 Laterals

CLSID{3070721…

EXTCLSID{0368CF51…Feature classes

ClassExtension

2 Mains {3070721…

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

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

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

ClassExtensionIClassExtension

0..1

IC lassE xtension : IUnknown

In it (in pC lassHelper: IC lassHelper, inpE xtens ionP roperties : IP ropertyS et)

S hutdow n

TableIClass IC lass : IUnknown

CLSID : IU IDE X TCLS ID : IU IDE xtension: IUnknownE xtens ionP roperties : IP ropertyS etFie lds : IF ie ldsHasOID : B ooleanIndexes: IIndexesOID Fie ldNam e: S tring

A ddFie ld (in Fie ld: IF ie ld)A ddIndex (in Index: IIndex)Dele teFie ld (in Fie ld: IF ie ld)Dele teIndex (in Index: IIndex)FindFie ld (in Nam e: S tring): Long

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;}

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

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

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 classIClassSchemaEdit::AlterClassExtensionProperties

STDMETHODIMP CMBClassExtension::Init(IClassHelper *pClassHelper,IPropertySet *pPropSet){

// Read stored symbol from property setCComVariant 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 setCComVariant vSymbol;

pPropSet->GetProperty(CComBstr("symbol"), &vSymbol);

IUnknownPtr ipUnk(vSymbol.ppUnkVal);m_ipSymbolForFeatures = ipUnk;

}

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

5-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// IClassExtensionSTDMETHODIMP TrackLifecycleExt::Init (IClassHelper * pClassHelper, IPropertySet * pExtensionProperties){… IClassPtr ipClass; ipFeatureClass->FindField (CComBSTR( L"CreationDate"),&m_creationDate)))…}// IObjectClassEventsSTDMETHODIMP 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// IClassExtensionSTDMETHODIMP TrackLifecycleExt::Init (IClassHelper * pClassHelper, IPropertySet * pExtensionProperties){… IClassPtr ipClass; ipFeatureClass->FindField (CComBSTR( L"CreationDate"),&m_creationDate)))…}// IObjectClassEventsSTDMETHODIMP 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.hclass ATL_NO_VTABLE CTrackLifecycleExt : public ITrackLifecycleExt, public IClassExtension, public IObjectClassEvents{…

// TrackLifecycleExt.hclass ATL_NO_VTABLE CTrackLifecycleExt : public ITrackLifecycleExt, public IClassExtension, public IObjectClassEvents{…

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

5-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 membersHasCustomRenderer – You have written your own renderer

CustomRenderer – Reference render to use always

ExclusiveCustomRenderer – User can change renderers via GUI

CustomRendererPropPageCLSID – Your custom property page

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

5-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 defaultif (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 defaultif (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)

}…}

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

5-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 missingIFeatureWorkspaceSchemaEdit::AlterClassExtensionCLSID

When modeling and designing in Visio Create class extension and make association via UML

Set the CLSID tagged value to the component

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

5-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

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

5-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

IUnknownMyAddDataCmd

ICommand

IUnknown (inner)

ICommand

IMyAddDataCmd

Instructor DemoInstructor Demo

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

5-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

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

5-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 CMBFeaturepublic:

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 categoryIMPLEMENTED_CATEGORY(CATID_GeoObjects)

END_CATEGORY_MAP()};

// MBFeature.h : Declaration of the CMBFeaturepublic:

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 categoryIMPLEMENTED_CATEGORY(CATID_GeoObjects)

END_CATEGORY_MAP()};

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

5-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.cppHRESULT 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.cppHRESULT 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;}

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

5-19

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

Custom drawing behavior

// MBFeature.cpp…// IFeatureDrawSTDMETHODIMP 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 IFeatureDrawSTDMETHODIMP 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…// IFeatureDrawSTDMETHODIMP 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 IFeatureDrawSTDMETHODIMP 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

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

5-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

1 Laterals

CLSID{3070721…

EXTCLSID{0368CF51…Feature classes

CustomFeature

2 Mains {8881110…

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

5-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-11D4-9601-

0080C7E61A96}" //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-11D4-9601-

0080C7E61A96}" //pClassSchemaEdit.AlterClassExtensionCLSID pUid, Nothing

pClassSchemaEdit.AlterInstanceCLSID pUid End If

End Sub

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

5-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

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

5-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

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

5-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

IClassExtensionIFeatureClassExtension

IFeatureClassDraw

IPropertyPage

IPropertyPageContext

IUnknown

IFeatureDraw CMBFeature

IFeatureesriCore::Feature

IFeatureRenderer

CMBRendererILegendInfoIPersistStream

IMBClassExtension

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

5-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?

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

5-26

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