Euan Cameron and allan laframboise will present customizing ArcGIS desktop applications Using COM objects. Esri's VB and c++ developers will Learn how to Move VBA customizations to COM objects Underlying architecture advanced customizations Application extensions and when to use them. The presentation will include: ArcObjects product review ArcInfo, ArcEditor, ArcView, ArcMap, ArcCatalog and ArcToolBox.
Euan Cameron and allan laframboise will present customizing ArcGIS desktop applications Using COM objects. Esri's VB and c++ developers will Learn how to Move VBA customizations to COM objects Underlying architecture advanced customizations Application extensions and when to use them. The presentation will include: ArcObjects product review ArcInfo, ArcEditor, ArcView, ArcMap, ArcCatalog and ArcToolBox.
Euan Cameron and allan laframboise will present customizing ArcGIS desktop applications Using COM objects. Esri's VB and c++ developers will Learn how to Move VBA customizations to COM objects Underlying architecture advanced customizations Application extensions and when to use them. The presentation will include: ArcObjects product review ArcInfo, ArcEditor, ArcView, ArcMap, ArcCatalog and ArcToolBox.
Customizing ArcGIS Desktop Applications Euan Cameron Allan Laframboise Agenda 8:30 12:00 PM ArcGIS development 1:00 5:30 PM Application extensions and advanced topics Breaks Introduction Who are we? Who are you? What is this presentation about? Who is this presentation for? Questionnaire How many people are: ArcObjects developers Writing VBA macros, used OMDs Developing with COM - commands, tools or extensions ArcView Avenue developers MapObjects developers VB / C++ / VC++ Why are you here? Learn how to extend ArcGIS desktop applications Move VBA customizations to COM objects Underlying architecture Advanced customizations Application extensions and when to use them Want to hang out in San Diego for the weekend What will be covered ArcGIS product review ArcObjects and COM backgrounder (short) ArcObjects development strategies and customization options Application framework Extensions Document Persistence Windows and property pages Advanced development and integration Code Samples and Prizes Downloadable via www.esri.com\arcobjectsonline All samples are written in VB and VC++ Professionally printed ArcObjects OMDs (4x) $50 value Based on participation Exploring ArcObjects books (2x) $100 value Must complete presentation evaluation at end! ArcGIS Product Review Desktop Products ArcInfo ArcEditor ArcView Core applications ArcMap, ArcCatalog and ArcToolBox Extensions Server Products - ArcSDE - ArcIMS ArcObjects: The Foundation One object model, many products ArcInfo ArcEditor ArcView All share the following DLLs, classes, interfaces and members Developers Write multi-product ArcGIS components and extensions Product Licensing License manager controls Which product can be installed and used License file floating and fixed seats Desktop Administrator Enables a product and functionality based on license available E.g. ArcView vs ArcEditor Re-installation NOT required Demo: Desktop Administrator Licensing and Development Clients must have a license to support the objects that you develop with All licensed interfaces are listed in Exploring ArcObjects Appendix C ArcMap and ArcCatalog detects license on startup Using extensions requires checking out licenses More on this later Develop distributable components with the same license that your end-users will have ArcObjects and COM for VB and VC++ developers A 20 minute quiz ArcObjects ArcObjects is a set of COM objects Provides a framework and development platform Extend and customize ArcGIS applications Develop custom tools and views Enhance map presentation Handle custom map and data processing Manage data Help system, Object Model Diagrams COM Microsofts Component Object Model Protocol that connects one software module to another Not a language Binary specification Language independent Programming model that uses interfaces Why do most VBA, VB and pure C++ developers find it difficult to program with COM? COM Classes and Interfaces Class encapsulates interface implementation Working details of an interface are within a class implementation, a so called CoClass COM classes can support multiple interfaces COM objects communicate via their interfaces Acts as a contract Access to COM objects is made via its interfaces AO Interfaces and Classes 1674 interfaces All custom interfaces Early binding Inbound and outbound 1192 coclasses Support multiple interfaces Default interfaces AO classes have a default inbound and outbound IUnknown is default for ArcObjects VB programming considerations VB hides the default interface in Object Browser VB returns default interface if none is specified Forces you to declare all variable types Not an issue for VC++ Remember the AlaMO? Demo: EOBrowser.exe How can you find the default interface for a class? Where is IApplication in VB/VBA? The well known Interface IUnknown Maintains reference counting QueryInterface (QI) AddRef() Release() QueryInterface() IUnknown IUnknown What interface do all other interfaces inherit from? Querying for Interfaces Private Sub PopulateMap(pMap as IMap) AddLayers pMap IActiveView pAV Set pAV = pMap ' QueryInterface pAV.Refresh End Sub Private Sub PopulateMap(pMap as IMap) AddLayers pMap IActiveView pAV Set pAV = pMap ' QueryInterface pAV.Refresh End Sub void CMyClass::PopulateMap(IMap* pMap) { ::AddLayers (pMap); IActiveView* pAV; pMap->QueryInterface(IID_IActiveView, (void **) &pAV); // QI pAV->Refresh(); pAV->Release(); } void CMyClass::PopulateMap(IMap* pMap) { ::AddLayers (pMap); IActiveView* pAV; pMap->QueryInterface(IID_IActiveView, (void **) &pAV); // QI pAV->Refresh(); pAV->Release(); } ArcObjects Type Library Main library is esriCore.olb Describes interfaces, coclasses, enums Written with IDL (Interface Definition Language) Stores GUIDs ProgID, CLSID, IID Clients and development environments use type library to discover available data types VB -> References VC++ -> #import and importlib What are three ways to explore esriCore library? ArcObjects Help Tools 1. ArcObjects Developer Help 2. ArcObjects Developer Help (on-line) 3. Exploring ArcObjects (PDF and hard copy) 4. ArcObjects Object Model Diagrams (.pdfs and hard copy) 5. In VBA\VB\VC++ F1 -> ArcObjects Developer help (VB and VC++ version) F2 -> Object Viewer 6. EOBrowser.exe 7. OLEView.exe 8. RegEdit.exe or RegEdit32.exe ArcObjects Help in VC++ Additional resources VC++ Add-In Arc8Help.dll AoDevVC.chm AO C++ help Demo: AoDevVC.chm Review Definitions ArcObjects and COM Interface programming How to work with esriCore.olb ArcObjects help tools ArcObjects Development The Application Framework Before Starting Realize that ArcObjects are COM objects Familiar with the ArcGIS customization framework Understand what customizations are available Know the recommended entry points Familiar with the OMDs Know help resources, tools and samples Customization Directions 1. Work inside of the ArcGIS applications Customize ArcMap and ArcCatalog with VBA Macros, buttons, tools, menus Build and deliver documents or templates 2. Create custom components with a COM-compliant language Everything possible in VBA Advanced functionality e.g. extensions Deliver COM components Development Triangle Recommended progression Start here Embedding ArcObjects Stand-alone applications Custom features and workspaces Custom layers and renderers Document persistence Windows Property pagesViews Application extensions Geodatabase class extensions Editor tools Commands Buttons Tools Menus Toolbars VBA Macros and UIControls Map Control Difficulty of implementation To VBA or not VBA Advantages Free! No development platform required Easy to write macros and scripts Create buttons, tools and toolbars Easy to debug Distribute code as documents or templates Disadvantages Can not write or compile COM components Many parts of the application framework require the creation of COM components Can not create application extensions To VB or not VB Advantages Fast and easy to write COM components Manages interface pointer references Hides much of the low level plumbing Easy to design forms and complex GUIs Disadvantages Debugging issues Cant implement all interfaces in esriCore Its VB To VC++ or not VC++ Advantages Can implement all esriCore interfaces Complete control over internal COM plumbing ATL wizards make life easer, but Disadvantages Requires C++ and COM programming experience Must handle reference counting carefully Sinking outbound interface is more complex Its VC++ When to write components Anytime you want to extend the architecture Move away from VBA customizations Advanced customizations such as extensions Want to package functionality as a binary General Approach Create a COM object and implement one or more interfaces IUnknown IExtension IUnknown IExtension Editor yourExtension esriCore yourLibrary Demo: Existing Extension Levels of Implementation Interface chosen depends on functionality desired External GUI Framework components: ICommand, ITool, IToolbarDef and IMenuDef Editor: IEditSketch, IEditTask Windows: IDockableWindowDef, IContentsView, IGxView, ICOMPropertyPage Internal Extensions: IExtension, IExtensionConfig, ICustomizationFilter Geodatabase IClassExtension and IFeature Component Categories All advanced customizations must be registered in the correct ESRI component category Applications load components at runtime faster! Managing and exploring categories Customize Dialog, Categories.exe, .reg scripts VB Add-ins ESRI Compile and Register VC++ Macros IMPLEMENTED_CATEGORY(UUID) ArcCATIDs.h and CategoryIDs.cls Demo: Categories.exe Name two ways to explore component categories? Finding the right Interface - I Part I: Define the programming task Part II: Find the OMD Describe problem in AO terms Subtask 1 Subtask 2 ArcObjects Programming Task ArcObjects ArcObjects Programming Programming Task Task COM DLL COM COM DLL DLL Extract KeyWords Search for the correct OMD(s) Review all related documentation Trace the flow between classes and write code Divide task into subtasks Decide where to write code Search for a related sample Review the Structure of the OMD Part III: Navigate the OMD VBA Macro VBA VBA Macro Macro Finding the right interface - II Look at the existing coclasses e.g. TOC objects Browse the component categories Browse existing samples! Creating AO Components High-level steps 1. Create a COM project 2. Define library and class 3. Reference or import the esriCore.olb 4. Implement an esriCore interface 5. Compile and register in component category * General steps are the same regardless of the language and development environment Writing your first Component Choose a simple interface Framework ->ICommand, ITool Model code in VBA first UIButtonControl Demo: VBA Zoom In UIButton Writing your first Component Easier to use VB than VC++ Use the ESRI Add-ins ESRI Interface Implementer ESRI Error Handler and Line Generator Many more Look at ESRI-provided code and samples Example: Use the ESRI Command Wizard Demo: Command Wizard AfCommands Pre-written ESRI Commands Work with ArcMap and the Map Control Buttons and tools with lots of functionality Data access commands File save and open commands Map query and view tools Editing commands and tools Source can be found in \ArcObjects Developer Kit\Kits\ArcObjects Source\Commands\VB/VC++ Just register and use. Demo: CommandTestHarness Components from Scratch Visual Basic: 1. Create a VB ActiveX DLL project 2. Define library and class 3. Reference or import the esriCore.olb 4. Implement an esriCore interface 5. Compile and register in component category Example: SelectLabel ICommand and ITool Demo: UCVBServer - SelectLabel Components from Scratch Visual C++: 1. Create an ATL COM AppWizard project 2. Define library and class 3. Reference or import the esriCore.olb 4. Implement an esriCore interface 5. Compile and register in component category Example: UnSelectLabel - ICommand Demo: UCVBServer - UnSelectLabel Review Development Triangle Choosing a development language Process for extending ArcObjects Writing simple ArcObjects components Framework interfaces commands and tools VB and VC++ VB Add-ins and ATL wizards Application Extension Development The Essentials Topics Application extensions IExtension and IExtensionConfig Event handling concepts Locking application functionality Writing custom interfaces Persistence Application Extensions Mechanism to seamlessly integrate customizations into ArcMap and ArcCatalog Application-level customizations Generally used to: Maintain state throughout an app session Share information between tools Persist information into a MXD file Product license detection and tool management Enable functionality via the Extensions window Example ESRI Editor, Spatial Analyst How Extensions Work User starts application Application object is created Document object is created * Extensions are loaded New or existing document is loaded Application start-up is completed General Implementation Implement IExtension IExtension::Name IExtension::StartUp() IMxApplication, IGxApplication IEditor IExtension::ShutDown() Must register extension in component category ESRI Mx Extension > ArcMap ESRI Gx Extension > ArcCatalog ESRI Editor Extensions -> ArcMap Simple Extension - I Implements IExtension Private Property Get IExtension_Name() As String IExtension_Name = "ESRI UC 2001 Extension" End Property Private Sub IExtension_Startup(ByRef initializationData As Variant) If (TypeOf initializationData Is IApplication) Then Set m_pApp = initializationData m_frmSounds.play m_sSoundLoc & "\clap.wav" End If End Sub Private Sub IExtension_Shutdown() Set m_pApp = Nothing m_frmSounds.play m_sSoundLoc & "\laser.wav" End Sub Implements IExtension Private Property Get IExtension_Name() As String IExtension_Name = "ESRI UC 2001 Extension" End Property Private Sub IExtension_Startup(ByRef initializationData As Variant) If (TypeOf initializationData Is IApplication) Then Set m_pApp = initializationData m_frmSounds.play m_sSoundLoc & "\clap.wav" End If End Sub Private Sub IExtension_Shutdown() Set m_pApp = Nothing m_frmSounds.play m_sSoundLoc & "\laser.wav" End Sub Demo: Simple Extension - I Using the Extension Window Implement IExtensionConfig IExtensionConfig::Description IExtensionConfig::State Looks like an ESRI extension You are responsible for: What happens when checkbox is checked Storing the state of the extension esriESEnabled, esriESDisabled or esriESUnavailable State is stored in registry when application closes Simple Extension - II Demo: Simple Extension - II Private m_esriExtensionState As esriExtensionState Implements IExtension Implements IExtensionConfig Private Property Get IExtensionConfig_Description() As String IExtensionConfig_Description = "Sounds Extension" End Property Private Property Get IExtensionConfig_State() As esriCore.esriExtensionState IExtensionConfig_State = m_esriExtensionState End Property Private Property Let IExtensionConfig_State(ByVal ExtensionState As esriCore.esriExtensionState) m_esriExtensionState = ExtensionState Select Case m_esriExtensionState Case esriESEnabled: _ m_frmSounds.play m_sSoundLoc & "\cashreg.wav" Case esriESDisabled: _ m_frmSounds.play m_sSoundLoc & "\laser.wav" Case esriESUnavailable: _ m_frmSounds.play m_sSoundLoc & "\carbrake.wav" End Select End Property Private m_esriExtensionState As esriExtensionState Implements IExtension Implements IExtensionConfig Private Property Get IExtensionConfig_Description() As String IExtensionConfig_Description = "Sounds Extension" End Property Private Property Get IExtensionConfig_State() As esriCore.esriExtensionState IExtensionConfig_State = m_esriExtensionState End Property Private Property Let IExtensionConfig_State(ByVal ExtensionState As esriCore.esriExtensionState) m_esriExtensionState = ExtensionState Select Case m_esriExtensionState Case esriESEnabled: _ m_frmSounds.play m_sSoundLoc & "\cashreg.wav" Case esriESDisabled: _ m_frmSounds.play m_sSoundLoc & "\laser.wav" Case esriESUnavailable: _ m_frmSounds.play m_sSoundLoc & "\carbrake.wav" End Select End Property Advanced Implementations Extension acts as a central controlling object Maintains global data for tools, views, windows Detect current product version and license Check out appropriate extension license Control enabled property of other tools Lock down certain application functionality Requires Application must listen for events May need to make use of custom interfaces Understanding Events Application fires events to all components that sink an outbound interface Necessary to react to Documents opened, view changes, refresh MyTool MyCmd MyTOC ArcMap MyTool MyCommand MyExtension ArcMap Levels of Event Handling Decide what level of event handling is necessary Document: IDocumentEvents Map: IActiveViewEvents, IMapEvents, ISelectionEvents Layout: IActiveViewEvents, IPageEvents, ISelectionEvents Layer: ILayerEvents, ISelectionEvents Editor: IEditorEvents Workspace: IWorkspaceEditEvents Sinking Events in VB Use WithEvents IExtension::Startup and Shutdown Dim WithEvents m_pDocEvents As DocumentEvents Private Sub IExtension_Startup(initializationData As Variant) Set m_ipApp = initializationData 'connect to document events Set m_pDocEvents = m_ipApp.Document End Sub Private Sub IExtension_Shutdown() Set m_ipApp = Nothing 'disconnect from document events Set m_pDocEvents = Nothing End Sub Dim WithEvents m_pDocEvents As DocumentEvents Private Sub IExtension_Startup(initializationData As Variant) Set m_ipApp = initializationData 'connect to document events Set m_pDocEvents = m_ipApp.Document End Sub Private Sub IExtension_Shutdown() Set m_ipApp = Nothing 'disconnect from document events Set m_pDocEvents = Nothing End Sub Sinking Events in VC++ - I Connect manually on IExtension::Startup void CPersistExt::ConnectToDocument() { IDocumentPtr ipDoc; m_ipApp->get_Document(&ipDoc); if (ipDoc == NULL) return; // Nothing to connect to m_ipMxDoc = ipDoc; if (m_ipMxDoc == NULL) return; // Nothing to connect to //Avoid multiple connects if (m_dwDocCookie) return; //Connect to document events HRESULT hr = AtlAdvise(m_ipMxDoc, this->GetUnknown(), IID_IDocumentEvents, &m_dwDocCookie); } void CPersistExt::ConnectToDocument() { IDocumentPtr ipDoc; m_ipApp->get_Document(&ipDoc); if (ipDoc == NULL) return; // Nothing to connect to m_ipMxDoc = ipDoc; if (m_ipMxDoc == NULL) return; // Nothing to connect to //Avoid multiple connects if (m_dwDocCookie) return; //Connect to document events HRESULT hr = AtlAdvise(m_ipMxDoc, this->GetUnknown(), IID_IDocumentEvents, &m_dwDocCookie); } Sinking Events in VC++ - II Disconnect manually on IExtension::Shutdown void CPersistExt::DisconnectFromDocument() { if (m_ipMxDoc == NULL) return; //Disconnect from document events HRESULT hr = AtlUnadvise(m_ipMxDoc, IID_IDocumentEvents, m_dwDocCookie); if (FAILED(hr)) MessageBoxW(::GetActiveWindow(),L"Could not disconnect from Document events",L"Persist Settings Extension", MB_OK); m_ipMxDoc = 0; m_dwDocCookie = 0; } void CPersistExt::DisconnectFromDocument() { if (m_ipMxDoc == NULL) return; //Disconnect from document events HRESULT hr = AtlUnadvise(m_ipMxDoc, IID_IDocumentEvents, m_dwDocCookie); if (FAILED(hr)) MessageBoxW(::GetActiveWindow(),L"Could not disconnect from Document events",L"Persist Settings Extension", MB_OK); m_ipMxDoc = 0; m_dwDocCookie = 0; } Extensions and Events IDocumentEvents Members ActiveViewChanged() BeforeDocumentClosed() CloseDocument() MapsChanged() NewDocument() OnContextMenu() OpenDocument() Simple Extension - III Private WithEvents m_pMxDocumentEvents As MxDocument Private Sub IExtension_Startup(ByRef initializationData As Variant) If (TypeOf initializationData Is IMxApplication) Then Set m_pApp = initializationData Set m_pMxDocumentEvents = m_pApp.Document m_frmSounds.play m_sSoundLoc & "\clap.wav" End If End Sub Private Function m_pMxDocumentEvents_CloseDocument() As Boolean m_frmSounds.play m_sSoundLoc & "\slidedwn.wav" End Function Private Function m_pMxDocumentEvents_NewDocument() As Boolean m_frmSounds.play m_sSoundLoc & "\slideup.wav" End Function Private Function m_pMxDocumentEvents_OpenDocument() As Boolean m_frmSounds.play m_sSoundLoc & "\pop.wav" End Function Private WithEvents m_pMxDocumentEvents As MxDocument Private Sub IExtension_Startup(ByRef initializationData As Variant) If (TypeOf initializationData Is IMxApplication) Then Set m_pApp = initializationData Set m_pMxDocumentEvents = m_pApp.Document m_frmSounds.play m_sSoundLoc & "\clap.wav" End If End Sub Private Function m_pMxDocumentEvents_CloseDocument() As Boolean m_frmSounds.play m_sSoundLoc & "\slidedwn.wav" End Function Private Function m_pMxDocumentEvents_NewDocument() As Boolean m_frmSounds.play m_sSoundLoc & "\slideup.wav" End Function Private Function m_pMxDocumentEvents_OpenDocument() As Boolean m_frmSounds.play m_sSoundLoc & "\pop.wav" End Function Demo: Simple Extension - III Locking Functionality Implement ICustomizationFilter Document-level scope Use IDocumentEvents to apply filter Dim m_pMyFilter as ICustomizationFilter Set m_pMyFilter = FilterExt.cMyCustomizationFilter Private Sub IExtension_Startup(ByRef initializationData As Variant) Set m_pMyFilter = New ArcObjectsExtension.cExtensionFilter End Sub Private Function m_pDocumentEvents_NewDocument() As Boolean m_pApp.LockCustomization "password", m_pMyFilter End Function Private Function m_pDocumentEvents_OpenDocument() As Boolean m_pApp.LockCustomization "password", m_pMyFilter End Function Dim m_pMyFilter as ICustomizationFilter Set m_pMyFilter = FilterExt.cMyCustomizationFilter Private Sub IExtension_Startup(ByRef initializationData As Variant) Set m_pMyFilter = New ArcObjectsExtension.cExtensionFilter End Sub Private Function m_pDocumentEvents_NewDocument() As Boolean m_pApp.LockCustomization "password", m_pMyFilter End Function Private Function m_pDocumentEvents_OpenDocument() As Boolean m_pApp.LockCustomization "password", m_pMyFilter End Function Simple Extension - IV Implements ICustomizationFilter Private Function ICustomizationFilter_OnCustomizationEvent(ByVal custEventType As esriCore.esriCustomizationEvent, ByVal eventCtx As Variant) As Boolean If (custEventType = esriCEShowCustDlg _ Or custEventType = esriCEShowVBAIDE) Then m_frmSounds.play "C:\WINNT\Media\Microsoft Office 2000\police.wav" ICustomizationFilter_OnCustomizationEvent = True Lock functionality Else ICustomizationFilter_OnCustomizationEvent = False End If End Function Implements ICustomizationFilter Private Function ICustomizationFilter_OnCustomizationEvent(ByVal custEventType As esriCore.esriCustomizationEvent, ByVal eventCtx As Variant) As Boolean If (custEventType = esriCEShowCustDlg _ Or custEventType = esriCEShowVBAIDE) Then m_frmSounds.play "C:\WINNT\Media\Microsoft Office 2000\police.wav" ICustomizationFilter_OnCustomizationEvent = True Lock functionality Else ICustomizationFilter_OnCustomizationEvent = False End If End Function Demo: Simple Extension - IV Extensions and Commands Integrate to control Availability - ICommand::Enabled property How they behave IUnknown _cSelectLabel cSelectLabel IUnknown IUnSelectLabel CUnSelectLabel IUnknown IExtension cMyExtension ICommand ITool ICommand Add a Custom Interface To handle application-specific operations VB and VC++ give you a default interface for free Or create your own IUnknown _cSelectLabel cSelectLabel IUnknown IUnSelectLabel CUnSelectLabel IUnknown IExtension cMyExtension IToolController ICommand ITool ICommand Creating Interfaces VB Create a new class Name it IWhatever Add members * Implement new interface in a class VC++ Simply add interface to IDL Add members using the wizard * Implement new interface in a class Extension IToolController Implements IExtension Implements IToolController Private Property Get IToolController_Enabled() As Boolean If (m_iExtensionState = esriESEnabled) Then ' Other criteria... IToolController_Enabled = True Else IToolController_Enabled = False End If End Property Implements IExtension Implements IToolController Private Property Get IToolController_Enabled() As Boolean If (m_iExtensionState = esriESEnabled) Then ' Other criteria... IToolController_Enabled = True Else IToolController_Enabled = False End If End Property ' cSelectLabel.cls Private m_pToolController As IToolController Private Property Get ICommand_Enabled() As Boolean ICommand_Enabled = m_pToolController.Enabled End Property Private Sub ICommand_OnCreate(ByVal hook As Object) Set m_pApp = hook Set m_pToolController = m_pApp.FindExtensionByCLSID(pUID) End Sub ' cSelectLabel.cls Private m_pToolController As IToolController Private Property Get ICommand_Enabled() As Boolean ICommand_Enabled = m_pToolController.Enabled End Property Private Sub ICommand_OnCreate(ByVal hook As Object) Set m_pApp = hook Set m_pToolController = m_pApp.FindExtensionByCLSID(pUID) End Sub Demo: UCVBServer Enhancing IToolController Add more state management functionality Checks for the following criteria: IExtensionConfig::State -> esriESEnabled (already done) Correct product license -> esriProductCodeProfessional Can check out an ArcPress license -> TRUE/FALSE If any of the above return FALSE, all tools are automatically disabled! Example: UCVBServer Demo: UCVBServer Extensions and Persistence IPersistVariant or IPersistStream (VC++ only) Mechanism for storing your data in documents Generally implemented with extensions Maintain user customizations and state data Two types of data can be stored 1. Standard types strings, integers, longs 2. Objects that support IPersistStream Many ArcObjects can be persisted Map, Graphic Elements, Renderer objects IPersistVariant - VB Private Sub IPersistVariant_Save(ByVal Stream As esriCore.IVariantStream) 'persist booleans Stream.Write m_bDataView Stream.Write m_bDisplayView 'persist com object Stream.Write m_ipMapBackgroundColor End Sub Private Sub IPersistVariant_Save(ByVal Stream As esriCore.IVariantStream) 'persist booleans Stream.Write m_bDataView Stream.Write m_bDisplayView 'persist com object Stream.Write m_ipMapBackgroundColor End Sub Sample: VBPersistVariant and VBPersistVariantCommand Private Sub IPersistVariant_Load(ByVal Stream As esriCore.IVariantStream) 'load booleans m_bDataView = Stream.Read m_bDisplayView = Stream.Read 'load com object Set m_ipMapBackgroundColor = Stream.Read End Sub Private Sub IPersistVariant_Load(ByVal Stream As esriCore.IVariantStream) 'load booleans m_bDataView = Stream.Read m_bDisplayView = Stream.Read 'load com object Set m_ipMapBackgroundColor = Stream.Read End Sub IPersistVariant VC++ STDMETHODIMP CPersistExt::Save(IVariantStream * Stream) { //persist booleans vSave.Clear(); vSave.vt = VT_BOOL; vSave.boolVal = m_bDataView; hr = Stream->Write(vSave); if (FAILED(hr)) return hr; vSave.Clear(); vSave.vt = VT_BOOL; vSave.boolVal = m_bDisplayView; hr = Stream->Write(vSave); if (FAILED(hr)) return hr; //persist com object IObjectStreamPtr ipObjStream(CLSID_ObjectStream); ipObjStream->putref_Stream(Stream); ipObjStream->SaveObject(m_ipMapBackgroundColor); if (FAILED(hr)) return hr; return S_OK; } STDMETHODIMP CPersistExt::Save(IVariantStream * Stream) { //persist booleans vSave.Clear(); vSave.vt = VT_BOOL; vSave.boolVal = m_bDataView; hr = Stream->Write(vSave); if (FAILED(hr)) return hr; vSave.Clear(); vSave.vt = VT_BOOL; vSave.boolVal = m_bDisplayView; hr = Stream->Write(vSave); if (FAILED(hr)) return hr; //persist com object IObjectStreamPtr ipObjStream(CLSID_ObjectStream); ipObjStream->putref_Stream(Stream); ipObjStream->SaveObject(m_ipMapBackgroundColor); if (FAILED(hr)) return hr; return S_OK; } IPersistVariant::Load VC++ STDMETHODIMP CPersistExt::Load(IVariantStream * Stream) { //load booleans hr = Stream->Read(&vLoad); if (FAILED(hr)) return hr; if (vLoad.vt == VT_BOOL) m_bDataView = vLoad.boolVal; vLoad.Clear(); hr = Stream->Read(&vLoad); if (FAILED(hr)) return hr; if (vLoad.vt == VT_BOOL) m_bDisplayView = vLoad.boolVal; vLoad.Clear(); //load com object IObjectStreamPtr ipObjStream(CLSID_ObjectStream); ipObjStream->putref_Stream(Stream); ipObjStream->LoadObject(m_ipMapBackgroundColor); if (FAILED(hr)) return hr; IUnknownPtr ipUnk; hr = ipObjectStream->LoadObject((GUID*) &IID_IUnknown, 0, &ipUnk); if (FAILED(hr) || (ipUnk == 0)) return E_FAIL; m_ipMapBackgroundColor = ipUnk; return S_OK; } STDMETHODIMP CPersistExt::Load(IVariantStream * Stream) { //load booleans hr = Stream->Read(&vLoad); if (FAILED(hr)) return hr; if (vLoad.vt == VT_BOOL) m_bDataView = vLoad.boolVal; vLoad.Clear(); hr = Stream->Read(&vLoad); if (FAILED(hr)) return hr; if (vLoad.vt == VT_BOOL) m_bDisplayView = vLoad.boolVal; vLoad.Clear(); //load com object IObjectStreamPtr ipObjStream(CLSID_ObjectStream); ipObjStream->putref_Stream(Stream); ipObjStream->LoadObject(m_ipMapBackgroundColor); if (FAILED(hr)) return hr; IUnknownPtr ipUnk; hr = ipObjectStream->LoadObject((GUID*) &IID_IUnknown, 0, &ipUnk); if (FAILED(hr) || (ipUnk == 0)) return E_FAIL; m_ipMapBackgroundColor = ipUnk; return S_OK; } Review Fundamentals of writing an application extension Essentials of event handling (VB and VC++) Lock application functionality Custom interfaces (VB and VC++) Extensions as a central management component Integrate extensions and persistence Extreme ArcObjects The road less traveled Topics Multi-component Development Window development Dockable Windows Custom Views Property Pages Custom Layers Custom Renderers Multi-component Design For complex integrations, it will necessary to implement multiple interfaces and possibly multiple components Dont forget about events Examples: Command + Toolbar + Extension + Events Locking functionality + Extension + Events Window + Command + Extension + Events PropertyPage + Events +/- Command Renderers + PropertyPage + Class Extensions Dockable Windows Embed new windows into the application itself Similar to existing TOC window Interface - IDockableWindowDef Key members OnCreate, OnDestroy, ChildWindow Integrated with ICommand Component Category: ESRI Mx Dockable Windows Sample: OverviewDockableWindow Demo: OverviewDockableWindow Custom Tab Views Generic application-level windows Must handle events and all documents, data ArcMap IContentsView, IActiveViewEvents ArcCatalog IGxView, IGxSelectionEvents Example: ArcMapContentsView Sample: HTML View Demo:: ArcMapContentsView Property Sheets and Pages Windows with tabs (pages) Generally activated on right-click or properties CoClasses ComPropertySheet Surrounding window Interfaces IComPropertyPage (VB) IPropertyPage IComPropertyPageEvents There are tones of ESRI-property pages already! On-The-Fly Property Sheets Re-use and display ESRI property pages 1. Create ComPropertySheet 2. Assign component Category 3. Add an interface to QI for 4. Call IComPropertySheet::EditProperties Should be called from a command or menu Sample: PropertySheet (Map pages) Demo:: PropertySheetOnTheFly Implementing PropertyPages You provide a window to display inside the page IPropertyPage and IPropertyPageEvents Must add your component to appropriate component category for property pages System automatically adds pages to the property sheet when instantiated In VC++, use ATL property page wizard Sample: PropertyPage (Custom Map Page) Demo:: PropertyPageCustom Custom Layers Possible to create custom layers lots of work! Implement ILayer Need to manage and display elements somehow What about selecting, persisting, editing, feature management Should create a custom property page Example: LayerAndPropertyPage Demo:: PropertyPageCustom Custom Renderers Provide custom symbolization for features SimpleRenderer, UniqueValue, ClassBreaks Implement IFeatureRenderer May want to implement custom symbols as well Sample: Sliver (small polygons) Renderers and ClassExtensions ClassExtension extends a standard feature class Implemented at the Geodatabase-level Associates the render with the featureclass IClassExtension IFeatureClassExtension IFeatureClassDraw::CustomRenderer (doesnt need to be custom implementation!) Data always draws the same way Final Integration Sample More complex integration Set of custom commands, tools and a toolbar Custom extension Persists user settings into MXD Listens for ArcObjects events Supports custom interface and custom events Written in VC++ and VB Sample: DisplayToolbarExtension (Grand Finale) Summary Virtually everything is customizable by implementing interfaces and plugging in new COM objects Look at existing implementations (coclasses) and categories to determine which direction to take Extensions are simple to implement Event handling is essential Custom interfaces can be useful Components often co-exist with others The new ArcObjects on-line help system and samples are invaluable! The End