advanced arcobjects/atl applications
DESCRIPTION
Advanced ArcObjects/ATL applications. Lesson 4 overview. Integrated component solutions Dockable windows Custom layers Property pages Persistence Exercise 4: Great circle custom layer. ArcObjects component integration . Applications often require integrating many objects - PowerPoint PPT PresentationTRANSCRIPT
Copyright © 2002 ESRI. All rights reserved. Advanced ArcObjects Component Development II (C++)
Advanced ArcObjects/ATL applications
4-2Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Lesson 4 overview Integrated component solutions Dockable windows Custom layers Property pages Persistence Exercise 4: Great circle custom layer
4-3Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
ArcObjects component integration Applications often require integrating many objects Logical groupings
1. External: Commands, toolbars, property pages, windows, layers
2. Internal: Application extensions, filters, persistence
3. Database: Custom features and class extensions
IExtension
Extension
DockableWindowCommand
Toolbar
IExtensionConfigICustom ClassExtension
4-4Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Application startup revisited
1. Application
2. Document
3. Extensions
4. New or existing document
5. Registered dockable windows are created
6. Commands and toolbars
4-5Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Dockable windows Application-level customization Application manages window creation Visible state is saved in .mxt or .mxd Show and hide window with a tool
Instructor DemoInstructor Demo
4-6Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Implementing dockable windows IDockableWindowDef
OnCreate – Passed in an application reference when createdChildHWND – Provide a child hWnd sourceUserData – Window can maintain user data if necessary
// ICAoVBDockWindowpublic:// IDockableWindowDef
STDMETHOD(OnCreate)(IDispatch * hook);STDMETHOD(get_ChildHWND)(OLE_HANDLE * hWnd);STDMETHOD(get_Name)(BSTR * Name);STDMETHOD(get_Caption)(BSTR * Caption);STDMETHOD(OnDestroy)();STDMETHOD(get_UserData)(VARIANT * data);
private:IApplicationPtr m_ipApp;OLE_HANDLE m_childHwnd; //Child window
4-7Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Consuming VB window components
// PreviewDockWindow.h : Declaration of the CPreviewDockWindow
#import "..\AoVBServer\AoLib_VBServer.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids
HRESULT CAoDockWindow::FinalConstruct(){
return m_ipVBPreviewer.CreateInstance(CLSID_CAoWindowServer);}
STDMETHODIMP CAoDockWindow::get_ChildHWND(OLE_HANDLE * hWnd){
if (hWnd == NULL) return E_POINTER;m_ipVBPreviewer->get_hWnd(hWnd); // Get window from VB componentreturn S_OK;
}
Create VB ActiveX DLL or OCX Add components to a frame Create public member(s) to access window
Import into VC++
4-8Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Finding the dockable window
STDMETHODIMP CAoDockableWindowCommand::OnCreate(IDispatch * hook){ m_ipApp = hook;
CComBSTR bsVal; ::StringFromCLSID(CLSID_PreviewDockWindow, &bsVal); // Dockable window to find
IUIDPtr ipUid(CLSID_UID); ipUid->put_Value(CComVariant(bsVal)); // Dockable window CLSID
…
IDockableWindowManagerPtr ipDockMgr(m_ipApp); // Get the window manager
IDockableWindowPtr ipDockWindow; ipDockMgr->GetDockableWindow(ipUID, &m_ipDockWindow); // Find the window
return S_OK;}
Reference the application: Hook Use IDockableWindowManager::GetDockableWindow() Pass in the CLSID to find window
4-9Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Controlling the visibility of the window Use a command to manage the state
ICommand::OnClick() to open and closeIDockableWindow::Dock(esriDockxxx) ESRI constants: esriDockShow and esriDockHide
Deactivate your tool when the window is hiddenSTDMETHODIMP CAoDockableWindowCommand::OnClick(){
m_bVisible = !m_bVisible; // Toggle this each time
HRESULT hr;if (m_bVisible)
hr = m_ipDockWindow->Dock(esriDockShow);else{
hr = m_ipDockWindow->Dock(esriDockHide);m_ipApp->putref_CurrentTool(0); // Deactivate the tool
}
return hr;}
4-10Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Dockable window design considerations Window can be closed manually by user with the x Manage ICommand, Enabled, and Checked properties
Match command with the window state// ICommandSTDMETHODIMP CAoDockableWindowCommand::get_Enabled(VARIANT_BOOL * Enabled){
VARIANT_BOOL bVisible;m_ipDockWindow->IsVisible(&bVisible);if (bVisible == VARIANT_FALSE) // Window was manually closed ‘x’{
m_ipApp->putref_CurrentTool(0); // Deactivate toolm_bVisible = FALSE; // Don't deactivate again!
}*Enabled = VARIANT_TRUE;return S_OK;
}
STDMETHODIMP CAoDockableWindowCommand::get_Checked(VARIANT_BOOL * Checked){
VARIANT_BOOL bVisible;m_ipDockWindow->IsVisible(&bVisible);*Checked = bVisible;return S_OK;
}
4-11Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Custom layers Map-level customization Very application specific
Involve drawing (custom) elements to the screen Used as an alternative to custom workspace factories
Design considerations Drawing and storing elements Make as functional as an esriCore::FeatureLayer May require writing custom tools and other components
Example: GreatCircleLayer
Instructor DemoInstructor Demo
4-12Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Implementing a layer ILayer
Supports draw phases Controls drawing behavior Controls visibility
IGeoDataset Extent Spatial reference
IPersist and IPersistStream Enables ILayer property data to be stored Enables custom layer data to be stored
4-13Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Drawing phases Custom layer must identify the supported draw phases Tells system how and when to draw the layer tagesriDrawPhase
Each phase represents an off-screen bitmap (cache)STDMETHODIMP CMyLayer::get_SupportedDrawPhases(long* pDrawPhases){ if (!pDrawPhases) return E_POINTER;
// We are only interested in the geography phase, can be or’ed *pDrawPhases = esriDPGeography;
return S_OK;}
esriDPGeography 1 - Draw geography
esriDPAnnoation 2 - Draw annotation
esriDPSelection 4 – Draw selection
4-14Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Layer caches
STDMETHODIMP CMyLayer::get_Cached(VARIANT_BOOL* pCached) {
if (!pCached) return E_POINTER;
*pCached = m_bCached; return S_OK;
}
STDMETHODIMP CMyLayer::put_Cached(VARIANT_BOOL cached) {
m_bCached = cached; return S_OK;
}
All layers are drawn into one cache Any layer can be drawn into a separate cache Improves drawing speed if refreshed frequently
IActiveView::PartialRefresh(esriViewGeography, pUnkLayer, ipLayerExtent);
4-15Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Drawing the layer The system can ask to draw the layer at any time Draw code must be ready in ILayer::Draw Always verify the following
esriDrawPhase, pDisplay, and pTrackCancel
STDMETHODIMP CMyLayer::Draw(esriDrawPhase drawPhase, IDisplay* pDisplay, ITrackCancel* pTrackCancel){ if (!pDisplay) return E_POINTER;
if (drawPhase == esriDPGeography) {
VARIANT_BOOL continueDrawing;if (pTrackCancel)
pTrackCancel->Continue(&continueDrawing);
if (continueDrawing) // Ok to draw featuresDrawFeatures();
… }}
4-16Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Drawing layer features Draw each geometry manually Decide on best methodology: Linear, by size, position… Set symbol into the display first Do not call StartDrawing() or FinishDrawing()
STDMETHODIMP CMyLayer::Draw(esriDrawPhase drawPhase, IDisplay* pDisplay, ITrackCancel* pTrackCancel){
if (!pDisplay) return E_POINTER;…
// Ok to draw feature(s)HRESULT hr = pDisplay->SetSymbol(m_pSymbol);if (FAILED(hr)) return hr;
hr = pDisplay->DrawPoint(pGeom);if (FAILED(hr)) return hr;
}
4-17Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Georeferencing layers All layers must support IGeoDataset Defines the extent and spatial reference Required by ArcMap to
Control layer visibility from TOC Control invalid drawing extent Enable command tools (e.g., Zoom to layer)
4-18Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Completing the layer implementation IPersistStream ILegendInfo Others are optional
See FeatureLayerIPublishLayer for internet publishing
Associated objects may be required Specialized commands and tools Specialized property page Specialize event handling
4-19Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Property sheets and pages
Instructor DemoInstructor Demo
Purpose: To view and edit attributes of objects Examples: Element, layer, or a map frame
Potential uses Show property sheets on-the-fly Show custom sheets with selected property pages only Create custom property pages for specific objects
Example: GCLPropertyPage
4-20Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Showing property sheets and pages ComPropertySheet Automatically loads pages in a specific category Populate an ISet to pass in filter objects (e.g., Layer) EditProperties – Shows property sheet and pages
IComPropertySheetPtr ipComPropertySheet(CLSID_ComPropertySheet); // Generic sheet
IUIDPtr ipUID(CLSID_UID); // Define the category GUID v.bstrVal = ::SysAllocString(OLESTR("{1476C782-6F57-11D2-A2C6-080009B6F22B}")); ipUID->put_Value(v);
ipComPropertySheet->AddCategoryID(ipUID); // Filter pages by category
IUnknown* pUnk; if (FAILED(hr = pLayer->QueryInterface(&pUnk))) return hr;
ISetPtr ipSet(CLSID_Set); ipSet->Add(pUnk); // Search criteria is type ILayer
ipComPropertySheet->EditProperties(ipSet,(OLE_HANDLE) hParentWindow, &vb) // Show
4-21Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Loading property pages
ComponentCategories
2. Pass ISet
Load all pages that apply to ISet
Each page evaluates ISet
1. CATID
1. CATID:ESRI Layer Property Pages
2. ISet: ILayer
4-22Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Custom property pages Implement
IPropertyPage IPropertyPageContext
Design same as MS property pages Key members
Applies, Show, and Apply
4-23Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Designing a property page in ATL
Instructor DemoInstructor Demo
New ATL property page object Provides default implementation
IPropertyPageImpl<>IPropertyPage Need IPropertyPageContext
Use the Resource Wizard Add and position window elements
Event handling code must be added manually MSG_MAP
4-24Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
STDMETHODIMP CGCLayerPropertyPage::Applies(VARIANT unkArray, VARIANT_BOOL * Applies){
// Default Applies to False*Applies = VARIANT_FALSE;
SAFEARRAY *saArray;saArray = unkArray.parray;HRESULT hr = SafeArrayLock(saArray);if (FAILED(hr)) return hr;
// Look for object we can editlong lNumElements = saArray->rgsabound->cElements;for (long i = 0; i < lNumElements; i++){
// Attempt to QI for IEventCustomLayerIGreatCircleLayerPtr ipGCLayer(ippUnk[i]);if (ipGCLayer != 0){
// Interface and the property page therefore applies*Applies = VARIANT_TRUE;
}}return S_OK;
}
PropertySheet passes in an array of objects (ISet) Page tells the sheet to load page or not
IPropertyPage::Applies
4-25Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
IPropertyPage::Show
STDMETHODIMP CGCLayerPropertyPage::Show(UINT nCmdShow){ // Let the ATL property page take care of showing and hiding the dialog hr = IPropertyPageImpl<CGCLayerPropertyPage>::Show(nCmdShow);
if (nCmdShow != SW_HIDE) { for (UINT i = 0; i < m_nObjects; i++) {
IGreatCircleLayerPtr ipGCLayer(m_ppUnk[i]);// Get the properties from the layerif ((ipGCLayer != 0) && (m_hWnd != 0)){
long lDelay;hr = ipGCLayer->get_Delay(&lDelay);SetDlgItemInt(IDC_TIMERINTERVAL, (UINT) (lDelay));
double dShift;hr = ipGCLayer->get_Shift(&dShift);SetDlgItemInt(IDC_SPEEDVALUE, (UINT) dShift);
}
} }}
Executes when the window itself is created Opportunity to set the value of the page elements
4-26Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
IPropertyPage::Apply Access property page array of objects Find your object and set the new values Synchronize property page values with object
STDMETHODIMP CGCLayerPropertyPage::Apply(void){ for (UINT i = 0; i < m_nObjects; i++) {
IGreatCircleLayerPtr ipGCLayer(m_ppUnk[i]);if (ipGCLayer != 0){
// Apply the changes from the property pagehr = ipGCLayer->put_Delay(GetDlgItemInt(IDC_TIMERINTERVAL)); if (FAILED(hr)) return hr;
hr = ipGCLayer->put_Shift((double) GetDlgItemInt(IDC_SPEEDVALUE));if (FAILED(hr)) return hr;
}
m_bDirty = FALSE; return S_OK;}
4-27Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Supporting persistence Implement IPersistStream Objects may contain other objects that support
persistence Internal objects are automatically asked to persist themselves
(e.g., MxDocument > Map > Layers > Symbols)
Must be supported by all custom layers Store ILayer data: Name, visibility, min, and max scale Store custom data if necessary
Example: GreatCircleLayer
Instructor DemoInstructor Demo
4-28Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
IPersistStream::Save Save standard types and objects
STDMETHODIMP CGreatCircleLayer::Save(IStream * pStm, BOOL fClearDirty){ // Persist the relevant info to the stream pStm->Write(&cCurVers , sizeof(cCurVers), 0));
// ILayer members m_bsName.WriteToStream(pStm); pStm->Write(&m_bIsVisible, sizeof(m_bIsVisible), 0); pStm->Write(&m_bShowTips, sizeof(m_bShowTips), 0); pStm->Write(&m_bCached, sizeof(m_bCached), 0); pStm->Write(&m_dMinimumScale, sizeof(m_dMinimumScale), 0); pStm->Write(&m_dMaximumScale, sizeof(m_dMaximumScale), 0); pStm->Write(&m_dReferenceScale, sizeof(m_dReferenceScale), 0);
// IGreatCircleLayer members pStm->Write(&m_lDelay, sizeof(m_lDelay), 0); pStm->Write(&m_dShift, sizeof(m_dShift), 0);
IObjectStreamPtr ipObjectStream(CLSID_ObjectStream); ipObjectStream->putref_Stream(pStm);
hr = ipObjectStream->SaveObject(m_ipMovingSymbol); hr = ipObjectStream->SaveObject(m_ipAnimatePoint); hr = ipObjectStream->SaveObject(m_ipProjectedExtent);
m_bIsDirty = false; return S_OK;}
4-29Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
IPersistStream::Load Populate data values and objectsSTDMETHODIMP CGreatCircleLayer::Load(IStream * pStm){ // Check the version of persistence short vers; if (FAILED(pStm->Read(&vers, sizeof(vers), 0))) return E_FAIL; if (vers > cCurVers) return E_FAIL; // Not forward compatible
// ILayer members m_bsName.ReadFromStream(pStm); pStm->Read(&m_bIsVisible, sizeof(m_bIsVisible), 0); pStm->Read(&m_bShowTips, sizeof(m_bShowTips), 0); pStm->Read(&m_bCached, sizeof(m_bCached), 0); pStm->Read(&m_dMinimumScale, sizeof(m_dMinimumScale), 0); pStm->Read(&m_dMaximumScale, sizeof(m_dMaximumScale), 0); pStm->Read(&m_dReferenceScale, sizeof(m_dReferenceScale), 0);
// IGreatCircleLayer members pStm->Read(&m_lDelay, sizeof(m_lDelay), 0); pStm->Read(&m_dShift, sizeof(m_dShift), 0); // Now the objects - use an object stream IObjectStreamPtr ipObjectStream(CLSID_ObjectStream); ipObjectStream->putref_Stream(pStm); hr = ipObjectStream->LoadObject((GUID*) &IID_ISymbol, 0, (IUnknown**) &m_ipMovingSymbol); … m_bIsDirty = false; return S_OK;}
4-30Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
IPersistStream::GetSizeMax Determine the size required to store all data
STDMETHODIMP CGreatCircleLayer::GetSizeMax(_ULARGE_INTEGER* pcbSize){ pcbSize->QuadPart = sizeof(cCurVers);
// Ilayer – Standard types pcbSize->QuadPart += m_bsName ? SysStringByteLen(m_bsName) + sizeof(OLECHAR) : 0; pcbSize->QuadPart += sizeof(m_bIsVisible); pcbSize->QuadPart += sizeof(m_bShowTips); pcbSize->QuadPart += sizeof(m_bCached); pcbSize->QuadPart += sizeof(m_dMinimumScale); pcbSize->QuadPart += sizeof(m_dMaximumScale); pcbSize->QuadPart += sizeof(m_dReferenceScale);
// IGreatCircleLayer – Standard types pcbSize->QuadPart += sizeof(m_lDelay); pcbSize->QuadPart += sizeof(m_dShift); pcbSize->QuadPart += sizeof(m_bActive); pcbSize->QuadPart += sizeof(m_dPlace);
_ULARGE_INTEGER objSize; // 64 bit unsigned integer struct
// IGreatCircleLayer – Objects IPersistStreamPtr ipPersistStream(m_ipMovingSymbol); ipPersistStream->GetSizeMax(&objSize); pcbSize->QuadPart += objSize.QuadPart;…}
4-31Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Exercise 4 overview Implements ILayer… Custom tools and toolbar Property page and persistence Challenge: Legend support
CGreatCircleLayer
IUnknown
CGCLayerPropertyPage
ILayerIGeoDataset
ILayerDrawPropertiesIPersistStream
ILegendInfo
IPropertyPageIPropertyPageContext
CGCClear
CGCAnimate
CGCClear
IUnknown
ICommand
CGCDigitizeDestination
CGCDigitizeDeparture
CGCAddLayer
CGCLToolBarIToolBarDef
ICommand
ICommand
ICommand
ICommand
4-32Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Review Explain the start up sequence for commands and
windows? What object should control the visibility of a dockable
window? What interfaces should be implemented with ILayer? When should a layer draw itself? Describe the property page loading cycle? How are data and objects persisted in VC++?