Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


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

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

2 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-2 Lesson 2 overview VC++ and ArcObjects/COM programming review How to import type libraries Smart pointers COM data types, HRESULTs, strings, and variants Microsoft Visual Studio Exercise 2: Simple console application

3 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-3 How VC++ facilitates ArcObjects development Client-side COM support Native compiler support: Direct-To-COM (DTC) #import directive to import type libraries Support classes for standard OLE types (BSTRs, VARIANTs, …) Server-side COM support ATL (Active Template Library) Templates and wizards for building COM objects and servers

4 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-4 Importing the ArcObjects library #import modifiers are required Specify esriCore.olb path: Tools > Options > Directories // stdafx.h #pragma warning(push) // Sets the current warning state #pragma warning(disable : 4146) // Ignore – for uint #pragma warning(disable : 4192)// Excludename while importing #import "c:\arcgis\arcexe81\bin\esriCore.olb" \// Type lib to generate C++ mapping raw_interfaces_only, \ // Dont add raw_ to method names raw_native_types, \ // Dont map to DTC smart types no_namespace, \ // Dont wrap with C++ name space named_guids, \// Named guids and declspecs exclude("OLE_COLOR", "OLE_HANDLE") // Exclude conflicting types #pragma warning(pop)// Restores state of warnings – undo // stdafx.h #pragma warning(push) // Sets the current warning state #pragma warning(disable : 4146) // Ignore – for uint #pragma warning(disable : 4192)// Excludename while importing #import "c:\arcgis\arcexe81\bin\esriCore.olb" \// Type lib to generate C++ mapping raw_interfaces_only, \ // Dont add raw_ to method names raw_native_types, \ // Dont map to DTC smart types no_namespace, \ // Dont wrap with C++ name space named_guids, \// Named guids and declspecs exclude("OLE_COLOR", "OLE_HANDLE") // Exclude conflicting types #pragma warning(pop)// Restores state of warnings – undo Instructor Demo

5 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-5 ArcObjects wrapper classes #import automatically generates type library wrappers Creates typedefs, smart pointers, structures… // Created by Microsoft (R) C/C++ Compiler Version (d727fb44). // // c:\student\arcobjectscpp\exercises\(1) - cpp\aoconsoleapp_solution\debug\esriCore.tlh // // C++ source equivalent of Win32 type library esriCore.olb // compiler-generated file created 12/20/01 at 11:33:49 - DO NOT EDIT! … /* interface */ IMap; struct __declspec(uuid("34b2ef81-f4ac-11d1-a b6f22b")) … extern "C" const GUID __declspec(selectany) CLSID_Map = {0xe6bdaa76,0x4d35,0x11d0,{0x98,0xbe,0x00,0x80,0x5f,0x7c,0xed,0x21}}; … _COM_SMARTPTR_TYPEDEF(IMap, __uuidof(IMap)); Typedef _com_ptr_t > IMapPtr; … struct __declspec(uuid("e6bdaa75-4d35-11d0-98be-00805f7ced21")) IMap : IUnknown { // Raw methods provided by interface virtual HRESULT __stdcall get_Name ( BSTR * Name ) = 0; virtual HRESULT __stdcall put_Name ( BSTR Name ) = 0; … // Created by Microsoft (R) C/C++ Compiler Version (d727fb44). // // c:\student\arcobjectscpp\exercises\(1) - cpp\aoconsoleapp_solution\debug\esriCore.tlh // // C++ source equivalent of Win32 type library esriCore.olb // compiler-generated file created 12/20/01 at 11:33:49 - DO NOT EDIT! … /* interface */ IMap; struct __declspec(uuid("34b2ef81-f4ac-11d1-a b6f22b")) … extern "C" const GUID __declspec(selectany) CLSID_Map = {0xe6bdaa76,0x4d35,0x11d0,{0x98,0xbe,0x00,0x80,0x5f,0x7c,0xed,0x21}}; … _COM_SMARTPTR_TYPEDEF(IMap, __uuidof(IMap)); Typedef _com_ptr_t > IMapPtr; … struct __declspec(uuid("e6bdaa75-4d35-11d0-98be-00805f7ced21")) IMap : IUnknown { // Raw methods provided by interface virtual HRESULT __stdcall get_Name ( BSTR * Name ) = 0; virtual HRESULT __stdcall put_Name ( BSTR Name ) = 0; …

6 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-6 DTC smart types VC++ classes that encapsulate data types _com_ptr_t<> Encapsulates a COM interface pointer (smart pointer) _bstr_t Encapsulates the BSTR data type _variant_t Encapsulates variant type and automatically initializes _com_error Represents a COM exception using IErrorInfo Classes behave like raw types Helpful constructors, functions, and operators Maps all COM errors to C++ exceptions Use to simplify ArcObjects code…

7 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-7 Initializing the COM library Necessary for stand-alone ArcObjects applications Steps 1. ::CoInitialize() - Loads the COM libraries 2. Cocreate and use ArcObjects objects 3. ::CoUninitialize() - Unloads COM libraries #include "stdafx.h" int main(int argc, char* argv[]) { ::CoInitialize(NULL); IMapPtr ipMap(CLSID_Map); // Simple code to create and call COM objects int iLayers; ipMap->get_LayerCount(&iLayers); _tprint(Number of layers: %i \n, iLayers); ::CoUninitialize(); } #include "stdafx.h" int main(int argc, char* argv[]) { ::CoInitialize(NULL); IMapPtr ipMap(CLSID_Map); // Simple code to create and call COM objects int iLayers; ipMap->get_LayerCount(&iLayers); _tprint(Number of layers: %i \n, iLayers); ::CoUninitialize(); }

8 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-8 Creating new ArcObjects objects COM API – ::CoCreateInstance() DTC smart pointers – Simplified but less control… // CoCreate a Map IMap* pMap; HRESULT hr = ::CoCreateInstance( CLSID_Map, // Class identifier (CLSID) of the object 0, // Pointer to outer unknown pointer CLSCTX_ALL, // Context for running executable code IID_IMap, // Reference to the interface identifier (void **) &pMap // Indirect pointer to requested interface ); if (FAILED(hr)) return hr;// Check HRESULT… // CoCreate a Map IMap* pMap; HRESULT hr = ::CoCreateInstance( CLSID_Map, // Class identifier (CLSID) of the object 0, // Pointer to outer unknown pointer CLSCTX_ALL, // Context for running executable code IID_IMap, // Reference to the interface identifier (void **) &pMap // Indirect pointer to requested interface ); if (FAILED(hr)) return hr;// Check HRESULT… // CoCreate a Map IMapPtr ipMap(CLSID_Map); if (ipMap == NULL) return E_POINTER;// Check for NULL // CoCreate a Map IMapPtr ipMap(CLSID_Map); if (ipMap == NULL) return E_POINTER;// Check for NULL

9 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved. 2-9 Querying interfaces COM API – IUnknown::QueryInterface() DTC smart pointers – Use assignment operator // CoCreate a Map IMap* pIMap; ::CoCreateInstance(CLSID_Map, 0, CLSCTX_ALL, IID_IMap, (void **) &pMap); IActiveView* pActiveView; pMap->QueryInterface(IID_IActiveView, (void **) &pActiveView); // QI // CoCreate a Map IMap* pIMap; ::CoCreateInstance(CLSID_Map, 0, CLSCTX_ALL, IID_IMap, (void **) &pMap); IActiveView* pActiveView; pMap->QueryInterface(IID_IActiveView, (void **) &pActiveView); // QI // CoCreate a Map IMapPtr ipMap(CLSID_Map);// QI IActiveViewPtr ipActiveView(ipMap);// QI // or use the assignment = operator directly IActiveViewPtr ipActiveView; ipActiveView = ipMap;// QI // CoCreate a Map IMapPtr ipMap(CLSID_Map);// QI IActiveViewPtr ipActiveView(ipMap);// QI // or use the assignment = operator directly IActiveViewPtr ipActiveView; ipActiveView = ipMap;// QI

10 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Object lifetime control: Smart pointers // Smart pointer reference count test long refCount; // CoCreate the SimpleObject IUnknownPtr ipUnk(CLSID_SimpleObject); // AddRef ISimpleObjectPtr ipMagic(ipUnk);// AddRef ipMagic->get_ReferenceCount(&refCount); IAnotherInterfacePtr ipMagic2(ipMagic); // AddRef ipMagic->get_ReferenceCount(&refCount); ipMagic2 = NULL; // What happens? ipMagic->get_ReferenceCount(&refCount); ipMagic = NULL; // What happens? // What happens to ipUnk here? ::CoCreateInstance(CLSID_SimpleObject, 0, CLSCTX_ALL, IID_IUnknown, (void **) &ipUnk); ipUnk = NULL; // Smart pointer reference count test long refCount; // CoCreate the SimpleObject IUnknownPtr ipUnk(CLSID_SimpleObject); // AddRef ISimpleObjectPtr ipMagic(ipUnk);// AddRef ipMagic->get_ReferenceCount(&refCount); IAnotherInterfacePtr ipMagic2(ipMagic); // AddRef ipMagic->get_ReferenceCount(&refCount); ipMagic2 = NULL; // What happens? ipMagic->get_ReferenceCount(&refCount); ipMagic = NULL; // What happens? // What happens to ipUnk here? ::CoCreateInstance(CLSID_SimpleObject, 0, CLSCTX_ALL, IID_IUnknown, (void **) &ipUnk); ipUnk = NULL; Instructor Demo

11 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved COM data type mapping LanguageIDLMicrosoft C++Visual BasicMicrosoft Java Booleanunsigned charunsupportedchar byteunsigned charunsupportedchar smallcharunsupportedchar short Integershort long Longint Basehyper__int64unsupportedlong Typesfloat Singlefloat double Doubledouble charunsigned charunsupportedchar wchar_t Integershort enum Enumint Interface Pointer Interface Ref. ExtendedVARIANT Variantms.com.Variant TypesBSTR Stringjava.lang.String VARIANT_BOOL short (-1 true/0 false) Boolean[true/false]

12 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved BSTRs COM API – SysAllocString, SysStringLen, SysFreeString DTC smart type – _bstr_t int main(int argc, char* argv[]) { _bstr_t bstrDBPath(L"..\\..\\..\\Data\\US.mdb"); _bstr_t bstrFCName(L"States"); IFeatureClassPtr ipFeatureClass; SelectFeatureClass1(bstrDBPath, bstrFCName, &ipFeatureClass); } int main(int argc, char* argv[]) { _bstr_t bstrDBPath(L"..\\..\\..\\Data\\US.mdb"); _bstr_t bstrFCName(L"States"); IFeatureClassPtr ipFeatureClass; SelectFeatureClass1(bstrDBPath, bstrFCName, &ipFeatureClass); } int main(int argc, char* argv[]) { BSTR bstrDBPath = ::SysAllocString(L"..\\..\\..\\Data\\US.mdb"); BSTR bstrFCName = ::SysAllocString(L"States"); IFeatureClassPtr ipFeatureClass; SelectFeatureClass1(bstrDBPath, bstrFCName, &ipFeatureClass); ::SysFreeString(bstrDBPath); ::SysFreeString(bstrFCName); } int main(int argc, char* argv[]) { BSTR bstrDBPath = ::SysAllocString(L"..\\..\\..\\Data\\US.mdb"); BSTR bstrFCName = ::SysAllocString(L"States"); IFeatureClassPtr ipFeatureClass; SelectFeatureClass1(bstrDBPath, bstrFCName, &ipFeatureClass); ::SysFreeString(bstrDBPath); ::SysFreeString(bstrFCName); }

13 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved VARIANTs COM API – VariantInit() and VariantClear() DTC smart type – _variant_t long l = 1000; VARIANT vValue1; ::VariantInit(&vValue1); vValue1.vt = VT_R4;// Set variant type here vValue1.lVal = l; printf("The value is: %d\n", vValue1.lVal); ::VariantClear(&vValue1); long l = 1000; VARIANT vValue1; ::VariantInit(&vValue1); vValue1.vt = VT_R4;// Set variant type here vValue1.lVal = l; printf("The value is: %d\n", vValue1.lVal); ::VariantClear(&vValue1); long l = 1000; _variant_t vValue2(l); printf("The value is: %d\n", vValue2.lVal); long l = 1000; _variant_t vValue2(l); printf("The value is: %d\n", vValue2.lVal);

14 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Not so smart smart types // Variant and smart pointer test IUnknownPtr ipUnk(CLSID_SimpleObject); // Create an object #1 _variant_t vValue; vValue.vt = VT_UNKNOWN; vValue.punkVal = ipUnk; // What happens? ipMagic = ipUnk; ipMagic->get_ReferenceCount(&refCount); // Release these ipMagic = 0; ipUnk = 0; vValue.punkVal->QueryInterface(&ipMagic2); // What happens? ipMagic2 = 0; vValue.vt = VT_EMPTY; // What happens now? What is missing from this code? // Variant and smart pointer test IUnknownPtr ipUnk(CLSID_SimpleObject); // Create an object #1 _variant_t vValue; vValue.vt = VT_UNKNOWN; vValue.punkVal = ipUnk; // What happens? ipMagic = ipUnk; ipMagic->get_ReferenceCount(&refCount); // Release these ipMagic = 0; ipUnk = 0; vValue.punkVal->QueryInterface(&ipMagic2); // What happens? ipMagic2 = 0; vValue.vt = VT_EMPTY; // What happens now? What is missing from this code? Instructor Demo Understand the behavior beforehand

15 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved HRESULTs Always check HRESULTs returned by ArcObjects Use SUCCEEDED() or FAILED() macros Non-zero severity means failed HRESULT hr; IWorkspaceFactoryPtr ipWorkspaceFactory(CLSID_AccessWorkspaceFactory); if (ipWorkspaceFactory == NULL) return E_FAIL; IWorkspacePtr ipWorkspace; if (FAILED(hr = ipWorkspaceFactory->OpenFromFile(bstrDatabasePath, NULL, &ipWorkspace))) return hr; … HRESULT hr; IWorkspaceFactoryPtr ipWorkspaceFactory(CLSID_AccessWorkspaceFactory); if (ipWorkspaceFactory == NULL) return E_FAIL; IWorkspacePtr ipWorkspace; if (FAILED(hr = ipWorkspaceFactory->OpenFromFile(bstrDatabasePath, NULL, &ipWorkspace))) return hr; …

16 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Formatting HRESULTs inline void HRESULTMESSAGE( HRESULT hr ) { LPVOID lpMsgBuf; ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr,// HRESULT MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); _TCHAR buf[256]; _stprintf( buf, "%s", (_TCHAR *) lpMsgBuf ); ::LocalFree( lpMsgBuf ); MessageBox(0, buf, _T("HRESULT ERROR MESSAGE"), MB_OK | MB_ICONINFORMATION ); } inline void HRESULTMESSAGE( HRESULT hr ) { LPVOID lpMsgBuf; ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr,// HRESULT MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); _TCHAR buf[256]; _stprintf( buf, "%s", (_TCHAR *) lpMsgBuf ); ::LocalFree( lpMsgBuf ); MessageBox(0, buf, _T("HRESULT ERROR MESSAGE"), MB_OK | MB_ICONINFORMATION ); } int main(int argc, char* argv[]) { IMapPtr ipMap(CLSID_Map); IMxDocument ipMxDoc; if (FAILED(hr = ipMap->QueryInterface(&ipMxDoc))) // Force a failed HRESULT HRESULTMESSAGE(hr); } int main(int argc, char* argv[]) { IMapPtr ipMap(CLSID_Map); IMxDocument ipMxDoc; if (FAILED(hr = ipMap->QueryInterface(&ipMxDoc))) // Force a failed HRESULT HRESULTMESSAGE(hr); } Possible to get and display the error code message

17 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Exception handling for DTC types Native DTC classes throw _com_error exceptions _com_error Wraps IErrorInfo object Returns: Description, HelpContext, HelpFile, Source void ErrorHandler(_com_error err) { _bstr_t bstrError; if (&err == NULL) return; bstrError = _T("Smart type error:"+ err.Description().length() > 0 ? (LPCTSTR) err.Description() : err.ErrorMessage()); ::MessageBox(NULL, bstrError, _T("Generic Error"), MB_OK | MB_TASKMODAL); } void ErrorHandler(_com_error err) { _bstr_t bstrError; if (&err == NULL) return; bstrError = _T("Smart type error:"+ err.Description().length() > 0 ? (LPCTSTR) err.Description() : err.ErrorMessage()); ::MessageBox(NULL, bstrError, _T("Generic Error"), MB_OK | MB_TASKMODAL); } try { // Force smart pointer error... IMapPtr ipMap; IActiveViewPtr ipAV; ipMap->QueryInterface(&ipAV); } catch (_com_error & err) { ErrorHandler(err); } try { // Force smart pointer error... IMapPtr ipMap; IActiveViewPtr ipAV; ipMap->QueryInterface(&ipAV); } catch (_com_error & err) { ErrorHandler(err); }

18 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Developing console applications Database related – Adding, deleting, and updating Utility applications – Print jobs, describe feature classes int main(int argc, char* argv[]) { CoInitialize(NULL); HRESULT hr; IFeatureClassPtr ipFeatureClass; _bstr_t bstrDBPath(L"..\\..\\..\\Data\\US.mdb"); _bstr_t bstrFCName(L"States"); hr = SelectFeatureClass1(bstrDBPath, bstrFCName, &ipFeatureClass); if (FAILED(hr))return -1; ::MessageBox(0, _T("Found feature class!"), _T("Console Applicaiton"), MB_OK); hr = PrintFeatureClassInformation(ipFeatureClass); if (FAILED(hr))return -1; ::MessageBox(0, _T("Printed feature class info!"), _T("Console Applicaiton"), MB_OK); CoUninitialize(); return 0; } int main(int argc, char* argv[]) { CoInitialize(NULL); HRESULT hr; IFeatureClassPtr ipFeatureClass; _bstr_t bstrDBPath(L"..\\..\\..\\Data\\US.mdb"); _bstr_t bstrFCName(L"States"); hr = SelectFeatureClass1(bstrDBPath, bstrFCName, &ipFeatureClass); if (FAILED(hr))return -1; ::MessageBox(0, _T("Found feature class!"), _T("Console Applicaiton"), MB_OK); hr = PrintFeatureClassInformation(ipFeatureClass); if (FAILED(hr))return -1; ::MessageBox(0, _T("Printed feature class info!"), _T("Console Applicaiton"), MB_OK); CoUninitialize(); return 0; }

19 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Writing ArcObjects/Visual Studio exercises Some VS projects are written from scratch Format-related All code inserts are prefixed with file name (e.g., File.h) … means scroll down until you find Some steps have step insert numbers Bold means write code // MBFeature.h : Declaration of the CMBFeature … public: CMBFeature() : m_pInnerUnk(NULL) { } // Step DECLARE_GET_CONTROLLING_UNKNOWN() … BEGIN_COM_MAP(CMBFeature) COM_INTERFACE_ENTRY(IMBFeature) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IFeatureDraw) END_COM_MAP() }; // MBFeature.h : Declaration of the CMBFeature … public: CMBFeature() : m_pInnerUnk(NULL) { } // Step DECLARE_GET_CONTROLLING_UNKNOWN() … BEGIN_COM_MAP(CMBFeature) COM_INTERFACE_ENTRY(IMBFeature) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IFeatureDraw) END_COM_MAP() };

20 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved More exercise hints… Follow conventions Project and class names Project and file paths Copy and paste ExerciseFunctions.h file Use exercise shortcuts Be careful cutting and pasting solutions

21 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Exercise 2 overview Create a single ArcObjects COM client Import the esriCore.olb correctly Initialize the COM library Accesses a geodatabase Print featureclass name and field information Challenge: Provide client-side error handling

22 Advanced ArcObjects Component Development II (C++) Copyright © 2002 ESRI. All rights reserved Review What is the first thing you need to do to work with ArcObjects in VC++? Why might you want to create an ArcObjects console- type application? What are the dangers of using smart types? True or False: VARIANT_TRUE = 1 and VARIANT_FALSE = 0?


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

Similar presentations


Ads by Google