Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


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

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

2 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-2 Lesson 3 overview Overview of ATL ArcObjects/ATL applications ATL smart types ATL wizards Connection point handling Exercise 3: Modeless zoom dialog tool

3 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-3 What is ATL? Active Template Library (ATL) Set of COM template classes Small, fast, and extensible Loosely modeled after the Standard Template Library (STL) Designed for building lightweight COM servers Wizards for common COM programming tasks Application: Create an ATL C++ project Object: Create new COM objects (C++ and IDL code) Members: Add properties and methods (updates IDL) Interface Implementation: Provide stub code for interfaces

4 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-4 When to write ATL/ArcObjects applications When you want to create new COM components Implement an interface Especially for interfaces that inherit from interfaces If members contain IUnknown* parameters Reuse ArcObjects functionality through aggregation Examples Custom commands, tools, property pages, layers, extensions Custom features…

5 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-5 ATL classes: In short CComXxxThreadModel Provides thread safety for global, static, and instance data CComObjectRootEx Provides behavior of IUnknown for appropriate threading model IXxxImpl Implementation of default interface CMyObject You provide implementation of interface CComObject Inherits your class Supports object allocation and server lifetime Provides implementation of IUnknown (QueryInterface)

6 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-6 Organization of template classes CComXxxThreadModel IXxxImplCComObjectRootEx CComObject CMyObject IMyInt IMyInt2

7 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-7 Typical ArcObjects ATL class Simple ICommand implementation // CTestCommand.h class ATL_NO_VTABLE CTestCommand : public CComObjectRootEx, public CComCoClass, public ITestCommand, public ICommand { public: CTestCommand(); ~CTestCommand(); DECLARE_REGISTRY_RESOURCEID(IDR_TESTCOMMAND) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CTestCommand) COM_INTERFACE_ENTRY(ITestCommand) COM_INTERFACE_ENTRY(ICommand) END_COM_MAP() // ICommand members below… // CTestCommand.h class ATL_NO_VTABLE CTestCommand : public CComObjectRootEx, public CComCoClass, public ITestCommand, public ICommand { public: CTestCommand(); ~CTestCommand(); DECLARE_REGISTRY_RESOURCEID(IDR_TESTCOMMAND) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CTestCommand) COM_INTERFACE_ENTRY(ITestCommand) COM_INTERFACE_ENTRY(ICommand) END_COM_MAP() // ICommand members below… IUnknown ITestCommand CTestCommand ICommand Instructor Demo

8 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-8 FinalConstruct() and FinalRelease() Called after constructor and before destructor Use to create and destroy objects Way to propagate HRESULTs back to client // CShowModalZoom.h DECLARE_PROTECT_FINAL_CONSTRUCT() // Initialization Sequence public: CShowModalZoom() : m_bBitmap(0), m_ipCustomizationFilter(0) {}// 1. ~CShowModalZoom() { m_hBitmap = 0}// 4. HRESULT CShowModalZoom::FinalConstruct()// 2. { ICustomizationFilterPtr ipFilter(clsid); m_ipCustomizationFilter = ipFilter; if (m_ipCustomizationFilter == NULL) return E_POINTER;//Send error to client return S_OK; } void CShowModalZoom::FinalRelease() // 3. { m_ipCustomizationFilter = 0; } // CShowModalZoom.h DECLARE_PROTECT_FINAL_CONSTRUCT() // Initialization Sequence public: CShowModalZoom() : m_bBitmap(0), m_ipCustomizationFilter(0) {}// 1. ~CShowModalZoom() { m_hBitmap = 0}// 4. HRESULT CShowModalZoom::FinalConstruct()// 2. { ICustomizationFilterPtr ipFilter(clsid); m_ipCustomizationFilter = ipFilter; if (m_ipCustomizationFilter == NULL) return E_POINTER;//Send error to client return S_OK; } void CShowModalZoom::FinalRelease() // 3. { m_ipCustomizationFilter = 0; }

9 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 3-9 Important ATL maps Object Map: Makes the class publicly creatable COM Map: Publicly exposes supported interfaces // CTestCommandServer.cpp CComModule _Module; BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_TestCommand, CTestCommand) END_OBJECT_MAP() // CTestCommandServer.cpp CComModule _Module; BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_TestCommand, CTestCommand) END_OBJECT_MAP() // CTestCommand.h BEGIN_COM_MAP(CTestCommand) COM_INTERFACE_ENTRY(ITestCommand) COM_INTERFACE_ENTRY(ICommand) END_COM_MAP() … // ICommand members below… // CTestCommand.h BEGIN_COM_MAP(CTestCommand) COM_INTERFACE_ENTRY(ITestCommand) COM_INTERFACE_ENTRY(ICommand) END_COM_MAP() … // ICommand members below…

10 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Component category registration ATL provides a category map macro Use macro in class you want to register Required to Identify component category CLSID Include ArcCATIDs.h for CATID GUIDs VC++ registers your component upon compilation // CTestCommand.h // Add category registration code #include "D:\arcgis\arcexe81\ArcObjects Developer Kit\Kits\CATIDs\ArcCatids.h" … BEGIN_CATEGORY_MAP(CTestCommand) IMPLEMENTED_CATEGORY(CATID_MxCommands) END_CATEGORY_MAP() // CTestCommand.h // Add category registration code #include "D:\arcgis\arcexe81\ArcObjects Developer Kit\Kits\CATIDs\ArcCatids.h" … BEGIN_CATEGORY_MAP(CTestCommand) IMPLEMENTED_CATEGORY(CATID_MxCommands) END_CATEGORY_MAP()

11 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ATL smart types Provides smart types similar to DTC CComPtr<> Encapsulates an interface pointer CComQIPtr<> Also supports QueryInterface CComBSTR Encapsulates a BSTR data type CComVariant Encapsulates a VARIANT data type CComDispatchDriver Access IDispatch members

12 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved DTC versus ATL types Common to use DTC types for smart pointers Syntax is straight forward – no <> Easier to read Some ATL types are more flexible – constructors… ATL types do not throw exceptions // DTC HRESULT hr; IMapPtr ipMap(CLSID_Map); if (ipMap == 0) return E_FAIL; IActiveViewPtr ipActiveView; ipActiveViewPtr = ipMap; hr = ipActiveView->Refresh(); ipActiveView = 0; // DTC HRESULT hr; IMapPtr ipMap(CLSID_Map); if (ipMap == 0) return E_FAIL; IActiveViewPtr ipActiveView; ipActiveViewPtr = ipMap; hr = ipActiveView->Refresh(); ipActiveView = 0; // ATL HRESULT hr; CComQIPtr ipMap; hr = ipMap.CoCreateInstance(CLSID_Map); if (FAILED(hr)) return hr; CComQIPtr ipActiveView; ipActiveView = ipMap; hr = ipActiveView->Refresh(); ipActiveView = 0; // ATL HRESULT hr; CComQIPtr ipMap; hr = ipMap.CoCreateInstance(CLSID_Map); if (FAILED(hr)) return hr; CComQIPtr ipActiveView; ipActiveView = ipMap; hr = ipActiveView->Refresh(); ipActiveView = 0;

13 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Connecting to objects Source: Object that makes calls (MxDocument, Map…) Sink: Object implementing interface that receives calls Steps 1. Client accesses IConnectionPointContainer 2. Use IConnectionPoint to find a connection point 3. Call IConnectionPoint::Advise 4. Call IConnectionPoint::Unadvise MyTool MyCmd MyTOC ArcMap MyView MyTool MyCmd Document

14 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Identifying objects that support events Easiest way is by looking at the object model diagrams Lower-level tools: EOBrowser.exe or Oleview.exe Object must implement IConnectionPointContainer Identify default outbound interface (default, source)

15 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Connecting to outbound interfaces void CMyClass::connect(IDocument* pDoc) { if (m_docEventsCookie != 0) return; IConnectionPointContainerPtr ipCPC(pDoc); IConnectionPointPtr ipCP; ipCPC->FindConnectionPoint(IID_IDocumentEvents, &ipCP); IUnknownPtr ipUnk(pDoc); ipCP->Advise(ipUnk, &m_docEventsCookie); } void CMyClass::disconnect( ) { if (m_docEventsCookie == 0) return; IConnectionPointContainerPtr ipCPC(m_ipDoc); IConnectionPointPtr ipCP; ipCPC->FindConnectionPoint(IID_IDocumentEvents, &ipCP); ipCP->Unadvise(m_docEventsCookie); m_docEventsCookie = 0; } void CMyClass::connect(IDocument* pDoc) { if (m_docEventsCookie != 0) return; IConnectionPointContainerPtr ipCPC(pDoc); IConnectionPointPtr ipCP; ipCPC->FindConnectionPoint(IID_IDocumentEvents, &ipCP); IUnknownPtr ipUnk(pDoc); ipCP->Advise(ipUnk, &m_docEventsCookie); } void CMyClass::disconnect( ) { if (m_docEventsCookie == 0) return; IConnectionPointContainerPtr ipCPC(m_ipDoc); IConnectionPointPtr ipCP; ipCPC->FindConnectionPoint(IID_IDocumentEvents, &ipCP); ipCP->Unadvise(m_docEventsCookie); m_docEventsCookie = 0; } Write connect() and disconnect() functions Documents can be opened and closed: Reconnect

16 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Sinking events directly in a command Implement outbound interface Use connection functions Need to manage connection carefully Document can be closed, command still lives… // AoCommand.h : Declaration of the CAoCommand // CTestCommand class ATL_NO_VTABLE CAoCommand : public CComObjectRootEx, public CComCoClass, public IAoCommand, public ICommand, public IDocumentEvents { private: IApplicationPtr m_ipApp; IMxDocumentPtr m_ipMxDoc; IActiveViewPtr m_ipConnectedView; DWORD m_dwDocCookie, m_dwViewCookie; void connect(); void disconnect(); // AoCommand.h : Declaration of the CAoCommand // CTestCommand class ATL_NO_VTABLE CAoCommand : public CComObjectRootEx, public CComCoClass, public IAoCommand, public ICommand, public IDocumentEvents { private: IApplicationPtr m_ipApp; IMxDocumentPtr m_ipMxDoc; IActiveViewPtr m_ipConnectedView; DWORD m_dwDocCookie, m_dwViewCookie; void connect(); void disconnect(); cAoCommand ICommand IUnknow n IDocumentEvents

17 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Controlling the connection lifetime // AoCommand.cpp : Implementation of the CAoCommand STDMETHODIMP CAoCommand::OnCreate(IDispatch * hook) { m_ipApp = hook; connect(); return S_OK; } … STDMETHODIMP CAoCommand::CloseDocument() { disconnect(); return S_OK; } … STDMETHODIMP CAoCommand::get_Enabled(VARIANT_BOOL * Enabled) { if (Enabled == NULL) return E_POINTER; if (m_dwDocCookie == 0) // Trick: Handle new or opening documents connect(); *Enabled = boolEnabled; return S_OK; } // AoCommand.cpp : Implementation of the CAoCommand STDMETHODIMP CAoCommand::OnCreate(IDispatch * hook) { m_ipApp = hook; connect(); return S_OK; } … STDMETHODIMP CAoCommand::CloseDocument() { disconnect(); return S_OK; } … STDMETHODIMP CAoCommand::get_Enabled(VARIANT_BOOL * Enabled) { if (Enabled == NULL) return E_POINTER; if (m_dwDocCookie == 0) // Trick: Handle new or opening documents connect(); *Enabled = boolEnabled; return S_OK; }

18 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved The command creation cycle ArcMap Starts List is populated CommandItems List Component Categories Cmd ICommandItem ESRI Mx Commands ICommand::OnCreate() ICommandItem Cmd1 ICommandItem Cmd2 ICommandItem Cmd3 … Instructor Demo Command created

19 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Sinking events in an intermediate sink object Use a standard ATL object and implement the interface Design considerations Easier to manage sink lifetime Need to call back to command class IMySink IUnknow n IDocumentEvents IAoCommand ICommand SetParentCommand() ActiveViewChangedCallBack() IUnknow n MapsChangedCallBack() NewDocumentCallBack() OpenDocumentCallBack() BeforeCloseDocumentCallBack() CloseDocumentCallBack() ActiveViewChanged MapsChanged NewDocument OpenDocument BeforeCloseDocument CloseDocument CMySink CAoCommand

20 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Controlling the sink object lifetime Use OnCreate and FinalRelease Pass a reference to the sink to facilitate the call back // CAoCommand.cpp STDMETHODIMP CAoCommand::OnCreate(IDispatch * hook) { m_ipApp = hook; CSink* pSink = new CComObject (this); // Create the intermediate sink pSink->SetParentCmd(this); m_ipSink = pSink->GetUnknown(); connect(); // Connect CSink to MxDocument return S_OK; } void CAoCommand::FinalRelease() { if (m_dwDocCookie) // Disconnect from MxDocument if connected! disconnect(); m_ipSink = 0; } // CAoCommand.cpp STDMETHODIMP CAoCommand::OnCreate(IDispatch * hook) { m_ipApp = hook; CSink* pSink = new CComObject (this); // Create the intermediate sink pSink->SetParentCmd(this); m_ipSink = pSink->GetUnknown(); connect(); // Connect CSink to MxDocument return S_OK; } void CAoCommand::FinalRelease() { if (m_dwDocCookie) // Disconnect from MxDocument if connected! disconnect(); m_ipSink = 0; }

21 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Implementing the CallBack mechanism Call back to the command object Use public functions // Sink.cpp : Implementation of CSink // IDocumentEvents STDMETHODIMP CSink::ActiveViewChanged() { m_pCmd->ActiveViewChangedCallBack(); return S_OK; } // Sink.cpp : Implementation of CSink // IDocumentEvents STDMETHODIMP CSink::ActiveViewChanged() { m_pCmd->ActiveViewChangedCallBack(); return S_OK; } // AoCommand.cpp : Implementation of CAoCommand // Called from intermediate sink object HRESULT CAoCommand::ActiveViewChangedCallBack() { if (m_ipMxDoc) { HRESULT hr; IActiveViewPtr ipActiveView; if (FAILED(hr = m_ipMxDoc->get_ActiveView(&ipActiveView))) return hr; IMapPtr ipMap(ipActiveView); m_bEnabled = ipMap ? VARIANT_TRUE : VARIANT_FALSE; } return S_OK; } // AoCommand.cpp : Implementation of CAoCommand // Called from intermediate sink object HRESULT CAoCommand::ActiveViewChangedCallBack() { if (m_ipMxDoc) { HRESULT hr; IActiveViewPtr ipActiveView; if (FAILED(hr = m_ipMxDoc->get_ActiveView(&ipActiveView))) return hr; IMapPtr ipMap(ipActiveView); m_bEnabled = ipMap ? VARIANT_TRUE : VARIANT_FALSE; } return S_OK; }

22 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ATL helper functions AtlAdvise() and AtlUnadvise() Pass in source, sink, outbound interface, and a dw Simplifies the connection process DWORD dwEventCookie; // Connect hr = AtlAdvise(ipSource, ipSink, IID_IActiveViewEvents, &dwEventCookie); // Disconnect hr = AtlUnadvise(ipSource, IID_IActiveViewEvents, dwEventCookie); DWORD dwEventCookie; // Connect hr = AtlAdvise(ipSource, ipSink, IID_IActiveViewEvents, &dwEventCookie); // Disconnect hr = AtlUnadvise(ipSource, IID_IActiveViewEvents, dwEventCookie);

23 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ISupportsErrorInfo Server objects can provide rich error information 1. Client asks object for object that supports ISupportsErrorInfo 2. Client acquires global error object with ::GetErrorInfo() 3. Access IErrorInfo members for detailed information 4. Otherwise Automation Error: Unspecified Error is returned ATL – ISupportErrorInfoImpl<> Implementation that returns IErrorInfo AtlReportError() to populate error object Clients (VB) can then retrieve rich error information Instructor Demo

24 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Creating ArcObjects components with ATL General approach 1. Create a new ATL COM Wizard project and define server name 2. Create and define a new object 3. Choose an interface to implement 4. Add implementation code 5. Compile and register component Similar to steps for VB in Advanced ArcObjects Component Development I (AACD I)

25 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Step 1. Create the ATL project Define the name Name becomes type library name Appends Lib Create a Dynamic Link Library Choose support options Avoid MFC where possible

26 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Step 2. Create and define a new Object Simple Object Set the following Object name Threading model Interface support Aggregation ISupportErrorInfo Connection point support code

27 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Step 3. Implement an interface Select esriCore.olb Select interface Generates stub code In the CMyObject.h Adds interface to COM_MAP Updates IDL

28 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Step 4. Edit and add implementation Move #import to stdafx.h and fix Move implementation from.h to.cpp Change STDMETHOD to STDMETHODIMP Add category reference and fix IDL ( IUnknown ) Add source to implement each member… // CAoCommand.h : Declaration of the CcAoZoomIn //#import "D:\arcgis\arcexe81\bin\esriCore.olb" raw_interfaces_only, //raw_native_types, no_namespace, named_guids, exclude("OLE_COLOR", "OLE_HANDLE") // Add category registration code #include "D:\arcgis\arcexe81\ArcObjects Developer Kit\Kits\CATIDs\ArcCatids.h" BEGIN_CATEGORY_MAP(CcAoZoomIn) IMPLEMENTED_CATEGORY(__uuidof(CATID_MxCommands)) END_CATEGORY_MAP() // Move implementation code to.cpp // CAoCommand.h : Declaration of the CcAoZoomIn //#import "D:\arcgis\arcexe81\bin\esriCore.olb" raw_interfaces_only, //raw_native_types, no_namespace, named_guids, exclude("OLE_COLOR", "OLE_HANDLE") // Add category registration code #include "D:\arcgis\arcexe81\ArcObjects Developer Kit\Kits\CATIDs\ArcCatids.h" BEGIN_CATEGORY_MAP(CcAoZoomIn) IMPLEMENTED_CATEGORY(__uuidof(CATID_MxCommands)) END_CATEGORY_MAP() // Move implementation code to.cpp IcAoZoomin IUnknown ICommand cAoZoomin

29 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Step 5. Compile and register component VC++ registers component Updates categories automatically Set up debugging environment Project > Settings > Debug Test

30 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved ATL replaces COM, right? Wrong! ATL helps implement generic COM objects ATL saves the developer typing A developer still needs to know how COM works

31 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved CSink CCustomFilter Exercise 3 overview Implement ICommand and ITool Show the zoom area in a dialog window Sink document events and apply a customization filter Challenge: Intermediate sink object ZoomDlg ICustomFilter IUnknow n ICustomizationFilter IShowModalZoom IUnknown ICommand CShowModalZoom ISink IUnknown IDocumentEvents ITool

32 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Review How does ATL assist VC++/ArcObjects developers? Which ATL functions should be used to create and destroy objects? What two methodologies can be employed to sink an objects outbound interface? Identify some of the edits required after using the ATL wizard to create an ArcObjects COM object? What is ISupportErrorInfo ?


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

Similar presentations


Ads by Google