Upload
isabella-drake
View
231
Download
2
Tags:
Embed Size (px)
Citation preview
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
DockableWindow
Command
Toolbar
IExtensionConfig
ICustom 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 created
ChildHWND – Provide a child hWnd source
UserData – 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
// 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;
}
// 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;}
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 stateICommand::OnClick() to open and close
IDockableWindow::Dock(esriDockxxx)
ESRI constants: esriDockShow and esriDockHide
Deactivate your tool when the window is hidden
STDMETHODIMP 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;}
STDMETHODIMP 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-10
Advanced 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;
}
// 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-11
Advanced 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-12
Advanced 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-13
Advanced 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;}
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-14
Advanced 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;
}
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-15
Advanced 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 followingesriDrawPhase, 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();
… }}
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-16
Advanced 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;
}
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-17
Advanced 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-18
Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Completing the layer implementation
IPersistStream
ILegendInfo
Others are optional See FeatureLayer
IPublishLayer for internet publishing
Associated objects may be required Specialized commands and tools
Specialized property page
Specialize event handling
4-19
Advanced 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-20
Advanced 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
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-21
Advanced 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-22
Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
Custom property pages
Implement IPropertyPage
IPropertyPageContext
Design same as MS property pages
Key membersApplies, Show, and Apply
4-23
Advanced 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 implementationIPropertyPageImpl<>
IPropertyPage
Need IPropertyPageContext
Use the Resource Wizard Add and position window elements
Event handling code must be added manually MSG_MAP
4-24
Advanced 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;
}
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-25
Advanced 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);
}
} }}
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-26
Advanced 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;}
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-27
Advanced 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-28
Advanced 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;}
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-29
Advanced ArcObjects Component Development II (C++)Copyright © 2002 ESRI. All rights reserved.
IPersistStream::Load
Populate data values and objects
STDMETHODIMP 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;}
STDMETHODIMP 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-30
Advanced 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;…}
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-31
Advanced 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
IPropertyPage
IPropertyPageContext
CGCClear
CGCAnimate
CGCClear
IUnknown
ICommand
CGCDigitizeDestination
CGCDigitizeDeparture
CGCAddLayer
CGCLToolBarIToolBarDef
ICommand
ICommand
ICommand
ICommand
4-32
Advanced 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++?