MoleSymbolsWindow.cpp
// Copyright 2010 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions. // #include <math.h> #include "MoleSymbols.h" #include "MoleSymbolsWindow.h" //////////////////////////////////////////////////// // private member functions for MoleSymbolsWindow // //////////////////////////////////////////////////// // add the named tool to the toolbar control void MoleSymbolsWindow::addTool (const char *name) { CComBSTR toolID ("esriControlCommands."); toolID.Append (name); long itemIndex; m_ipToolbarControl->AddItem (CComVariant(toolID), 0, -1, VARIANT_FALSE, 0, esriCommandStyleIconOnly, &itemIndex); } // create a new point instance and initialize its coordinates IPointPtr MoleSymbolsWindow::createPoint (double x, double y) { IPointPtr ipPoint (CLSID_Point); ipPoint->PutCoords (x, y); return ipPoint; } // generate a random floating-point number in the specified range [low, high) double MoleSymbolsWindow::dRandom (double low, double high) { #if defined(ESRI_UNIX) return low + ((double)random() / (double)RAND_MAX) * (high - low); #elif defined(ESRI_WINDOWS) return low + ((double)rand() / (double)RAND_MAX) * (high - low); #endif } void MoleSymbolsWindow::drawSymbol (IPointPtr ipLocation, const char *sic, bool suppressRefresh) { // the first time we create a symbol, display the wait cursor while MOLE loads up QCursor previousCursor (cursor()); if ( m_firstTime ) setCursor (QCursor(Qt::WaitCursor)); IMoleSymbolPtr ipMoleSymbol (CLSID_MoleMarkerSymbol); IMarkerSymbolPtr ipMarkerSymbol (ipMoleSymbol); IMarkerElementPtr ipMarkerElement (CLSID_MarkerElement); IElementPtr ipElement (ipMarkerElement); IActiveViewPtr ipActiveView; IGraphicsContainerPtr ipGraphicsContainer; m_ipMapControl->get_ActiveView (&ipActiveView); ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); // set up a MOLE symbol for the new graphic; minimally validate the symbol ID code if ( strlen(sic) == 15 ) ipMoleSymbol->put_SymbolID (CComBSTR(sic)); ipMoleSymbol->put_TextLabels (getLabels()); // to remove the symbol's fill, uncomment this code //IMoleMarkerSymbolPtr ipMoleMarkerSymbol (ipMoleSymbol); //ipMoleMarkerSymbol->put_ShowFill (VARIANT_FALSE); // initialize the marker symbol size property double size = m_txtSize->text().toDouble(); if ( size < 1 ) size = 36; ipMarkerSymbol->put_Size (size); // create the graphic element for the marker symbol and add it to the map ipMarkerElement->put_Symbol (ipMarkerSymbol); ipElement->put_Geometry (IGeometryPtr(ipLocation)); ipGraphicsContainer->AddElement (ipElement, 0); if ( ! suppressRefresh ) ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); // update the user interface if ( m_firstTime ) { setCursor (previousCursor); m_firstTime = false; } ++m_unitCount; updateTitle(); } // get a collection of label properties for a MOLE symbol IPropertySetPtr MoleSymbolsWindow::getLabels() { IPropertySetPtr ipLabelSet (CLSID_PropertySet); // all of the below are supported - comment and uncomment to experiment ipLabelSet->SetProperty (CComBSTR("Name"), CComVariant(CComBSTR("Name"))); ipLabelSet->SetProperty (CComBSTR("Comment"), CComVariant(CComBSTR("Comment"))); //ipLabelSet->SetProperty (CComBSTR("Parent"), CComVariant(CComBSTR("Parent"))); //ipLabelSet->SetProperty (CComBSTR("Info"), CComVariant(CComBSTR("Info"))); //ipLabelSet->SetProperty (CComBSTR("Strength"), CComVariant(CComBSTR("Strength"))); //ipLabelSet->SetProperty (CComBSTR("EvalRating"), CComVariant(CComBSTR("EvalRating"))); //ipLabelSet->SetProperty (CComBSTR("Location"), CComVariant(CComBSTR("Location"))); //ipLabelSet->SetProperty (CComBSTR("Alt_Depth"), CComVariant(CComBSTR("Alt_Depth"))); //ipLabelSet->SetProperty (CComBSTR("Speed"), CComVariant(CComBSTR("Speed"))); //ipLabelSet->SetProperty (CComBSTR("DTG"), CComVariant(CComBSTR("DTG"))); //ipLabelSet->SetProperty (CComBSTR("HQ"), CComVariant(CComBSTR("HQ"))); //ipLabelSet->SetProperty (CComBSTR("Quantity"), CComVariant(CComBSTR("Quantity"))); //ipLabelSet->SetProperty (CComBSTR("EType"), CComVariant(CComBSTR("EType"))); //ipLabelSet->SetProperty (CComBSTR("Effective"), CComVariant(CComBSTR("Effective"))); //ipLabelSet->SetProperty (CComBSTR("Signature"), CComVariant(CComBSTR("Signature"))); //ipLabelSet->SetProperty (CComBSTR("IFFSIF"), CComVariant(CComBSTR("IFFSIF"))); return ipLabelSet; } IColorPtr MoleSymbolsWindow::getRandomColor() { // create a random opaque RGB color IRgbColorPtr rgb (CLSID_RgbColor); #if defined(ESRI_UNIX) rgb->put_Red (random() % 256); rgb->put_Green (random() % 256); rgb->put_Blue (random() % 256); #elif defined(ESRI_WINDOWS) rgb->put_Red (rand() % 256); rgb->put_Green (rand() % 256); rgb->put_Blue (rand() % 256); #endif return rgb; } void MoleSymbolsWindow::moveGraphics (double deltaX, double deltaY) { // move all selected graphics along a delta (change) vector printf ("moving delta = (%f, %f)\n", deltaX, deltaY); // get reference to graphics container and its selected elements IActiveViewPtr ipActiveView; IGraphicsContainerPtr ipGraphicsContainer; IGraphicsContainerSelectPtr ipGraphicsContainerSelect; IEnumElementPtr ipEnumElement; IElementPtr ipElement; IGeometryPtr ipGeometry; m_ipMapControl->get_ActiveView (&ipActiveView); ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); ipGraphicsContainerSelect = ipGraphicsContainer; ipGraphicsContainerSelect->get_SelectedElements (&ipEnumElement); // iterate through the selected elements ipEnumElement->Reset(); ipEnumElement->Next (&ipElement); while ( ipElement ) { // apply the delta vector to each element's geometry and update it the container ipElement->get_Geometry (&ipGeometry); ITransform2DPtr(ipGeometry)->Move (deltaX, deltaY); ipElement->put_Geometry (ipGeometry); ipGraphicsContainer->UpdateElement (ipElement); ipEnumElement->Next (&ipElement); } // refresh the active view ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); } bool MoleSymbolsWindow::selectElements (IPointPtr ipPoint, IActiveViewPtr ipActiveView, IEnvelopePtr ipSelectedBounds) { // this function is written in such a way that it should be pastable double x, y; ipPoint->QueryCoords (&x, &y); printf ("selecting graphics near (%f, %f)\n", x, y); IGraphicsContainerPtr ipGraphicsContainer; IGraphicsContainerSelectPtr ipGraphicsContainerSelect; IScreenDisplayPtr ipScreenDisplay; IEnumElementPtr ipEnumElement; bool selected (false); bool refreshRequired (false); ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); ipActiveView->get_ScreenDisplay (&ipScreenDisplay); ipGraphicsContainerSelect = ipGraphicsContainer; // start with a precise search, and then widen the tolerance if nothing is found // (you may need to change these tolerances if using this code in your own application) ipGraphicsContainer->LocateElements (ipPoint, 0.0000001, &ipEnumElement); if ( ! ipEnumElement ) ipGraphicsContainer->LocateElements (ipPoint, 0.5, &ipEnumElement); // if no elements were selected if ( ! ipEnumElement ) { // if the previous selection is nonempty long count; ipGraphicsContainerSelect->get_ElementSelectionCount (&count); if ( count > 0 ) { // clear the selection and refresh the display printf ("clearing selection\n"); ipGraphicsContainerSelect->UnselectAllElements(); ipSelectedBounds->SetEmpty(); refreshRequired = true; } // else do nothing } else { // get the extent of the selected elements IEnvelopePtr ipEnvelope (CLSID_Envelope); IElementPtr ipElement; ipEnumElement->Next (&ipElement); while ( ipElement ) { // establish selectedBounds as the extent of all selected elements ipElement->QueryBounds (ipScreenDisplay, ipEnvelope); ipSelectedBounds->Union (ipEnvelope); ipEnumElement->Next (&ipElement); } // add all the newly selected elements to the graphics container's selection ipEnumElement->Reset(); ipGraphicsContainerSelect->SelectElements (ipEnumElement); refreshRequired = selected = true; } // refresh the display if anything has changed if ( refreshRequired ) ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); // return true if any elements on the display are currently selected; selectedBounds has their extent return selected; } // put the number of symbols in the title bar, when there are any void MoleSymbolsWindow::updateTitle() { if ( m_unitCount == 0 ) setWindowTitle ("MOLE Symbols"); else if ( m_unitCount == 1 ) setWindowTitle ("Mole Symbols (1 unit)"); else setWindowTitle (QString("Mole Symbols (%1 units)").arg(m_unitCount)); } //////////////////////////////////// // Qt slots for MoleSymbolsWindow // //////////////////////////////////// void MoleSymbolsWindow::add200() { // this one takes a little while, especially when it's the first one chosen QCursor previousCursor (cursor()); if ( m_firstTime ) setCursor (QCursor(Qt::WaitCursor)); // create concentric rings of units centered around where the user last clicked double centerLon, centerLat; m_ipLastMouseClick->QueryCoords (¢erLon, ¢erLat); const double circleRadiusInRad = 1.0; const int numberPerCircle = 10; for ( int i = 0; i < 200; ++i ) { // draw a random symbol at the next position in the pattern double currentRadius = (i / numberPerCircle) * circleRadiusInRad + circleRadiusInRad; double currentAngle = (i % numberPerCircle) * 2.0 * 3.1415926536 / (double)numberPerCircle; drawSymbol ( createPoint( centerLon + (currentRadius * sin(currentAngle)), centerLat + (currentRadius * cos(currentAngle)) ), getSIC(), true ); } //refresh the display and restore the cursor IActiveViewPtr ipActiveView; m_ipMapControl->get_ActiveView (&ipActiveView); ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); setCursor (previousCursor); } void MoleSymbolsWindow::addArea() { // create the symbol using a default symbol ID code (obstacle restricted area) IMoleSymbolPtr ipMoleSymbol (CLSID_MoleFillSymbol); ipMoleSymbol->put_SymbolID (CComBSTR("GUMPOGR-------X")); ipMoleSymbol->put_TextLabels (getLabels()); ipMoleSymbol->put_TextSize (3.0); // override the default fill color and outline symbol - these settings are optional //ILineSymbolPtr ipLineSymbol (CLSID_SimpleLineSymbol); //ipLineSymbol->put_Color (getrandomColor()); //ipLineSymbol->put_Width (dRandom(1, 5)); //IFillSymbolPtr ipFillSymbol (ipMoleSymbol); //ipFillSymbol->put_Outline (ipLineSymbol); //ipFillSymbol->put_Color (getrandomColor()); // center the polygon somewhere inside the current map extent IActiveViewPtr ipActiveView; m_ipMapControl->get_ActiveView (&ipActiveView); IEnvelopePtr ipExtent; ipActiveView->get_Extent (&ipExtent); double xMin, yMin, xMax, yMax; ipExtent->QueryCoords (&xMin, &yMin, &xMax, &yMax); double lat = dRandom (yMin, yMax); double lon = dRandom (xMin, xMax); // create a new polygon geometry for this symbol (four points in this example) // place the four corners somewhere within a specified threshold of the center IPointCollectionPtr ipPointCollection (CLSID_Polygon); const double threshold = 20; ipPointCollection->AddPoint (createPoint(lon, dRandom(lat, lat + threshold)), NULL, NULL); ipPointCollection->AddPoint (createPoint(dRandom(lon, lon + threshold), lat), NULL, NULL); ipPointCollection->AddPoint (createPoint(lon, dRandom(lat - threshold, lat)), NULL, NULL); ipPointCollection->AddPoint (createPoint(dRandom(lon - threshold, lon), lat), NULL, NULL); // set up the graphic element with the random geometry IFillShapeElementPtr ipFillShapeElement (CLSID_PolygonElement); ipFillShapeElement->put_Symbol (IFillSymbolPtr(ipMoleSymbol)); IElementPtr ipElement (ipFillShapeElement); ipElement->put_Geometry (IGeometryPtr(ipPointCollection)); // add the new element to the map and update the user interface IGraphicsContainerPtr ipGraphicsContainer; ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); ipGraphicsContainer->AddElement (ipElement, 0); ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); ++m_unitCount; updateTitle(); } void MoleSymbolsWindow::addLine() { // create the symbol using a default symbol ID code (fix task line) IMoleSymbolPtr ipMoleSymbol (CLSID_MoleLineSymbol); ipMoleSymbol->put_SymbolID (CComBSTR("GUTPF---------X")); ipMoleSymbol->put_TextLabels (getLabels()); ipMoleSymbol->put_TextSize (2.0); // override the default line color and width - these settings are optional //ILineSymbolPtr ipLineSymbol (ipMoleSymbol); //ipLineSymbol->put_Color (getrandomColor()); //ipLineSymbol->put_Width (dRandom(1, 5)); // place the first endpoint of the line somewhere inside the current map extent IActiveViewPtr ipActiveView; m_ipMapControl->get_ActiveView (&ipActiveView); IEnvelopePtr ipExtent; ipActiveView->get_Extent (&ipExtent); double xMin, yMin, xMax, yMax; ipExtent->QueryCoords (&xMin, &yMin, &xMax, &yMax); double lat = dRandom (yMin, yMax); double lon = dRandom (xMin, xMax); // create a new line geometry for the symbol - this symbol requires two points IPointCollectionPtr ipPointCollection (CLSID_Polyline); ipPointCollection->AddPoint (createPoint(lon, lat), NULL, NULL); // place the second endpoint somewhere within a specified threshold of the first const double threshold = 20; ipPointCollection->AddPoint ( createPoint( dRandom(lon - threshold, lon + threshold), dRandom(lat - threshold, lat + threshold) ), NULL, NULL ); // set up the graphic element with the random geometry ILineElementPtr ipLineElement (CLSID_LineElement); ipLineElement->put_Symbol (ILineSymbolPtr(ipMoleSymbol)); IElementPtr ipElement (ipLineElement); ipElement->put_Geometry (IGeometryPtr(ipPointCollection)); // add the new element to the map and update the user interface IGraphicsContainerPtr ipGraphicsContainer; ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); ipGraphicsContainer->AddElement (ipElement, 0); ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); ++m_unitCount; updateTitle(); } void MoleSymbolsWindow::addMoleSymbol (bool checked) { // make this button exclusive both in the Qt toolbar and in the ToolbarControl // the primary logic is in OnMouseDown printf ("add MOLE symbol = %s\n", (checked ? "checked" : "unchecked")); if ( checked ) { m_btnSelect->setChecked (false); m_ipToolbarControl->SetBuddyControl (NULL); m_ipToolbarControl->put_Enabled (VARIANT_FALSE); } else { m_ipToolbarControl->SetBuddyControl (m_ipMapControl); m_ipToolbarControl->put_Enabled (VARIANT_TRUE); } } void MoleSymbolsWindow::moveUnits() { // get reference to graphics container and its selected elements IActiveViewPtr ipActiveView; IGraphicsContainerPtr ipGraphicsContainer; IGraphicsContainerSelectPtr ipGraphicsContainerSelect; m_ipMapControl->get_ActiveView (&ipActiveView); ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); ipGraphicsContainerSelect = ipGraphicsContainer; // MoveGraphics only applies to units in the selection - this will erase any previous selection ipGraphicsContainerSelect->SelectAllElements(); moveGraphics (0.75, 0.75); ipGraphicsContainerSelect->UnselectAllElements(); ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); m_ipSelectedBounds->SetEmpty(); } void MoleSymbolsWindow::select (bool checked) { // make this button exclusive both in the Qt toolbar and in the ToolbarControl // the primary logic is in OnMouseDown, OnMouseMove, and OnMouseUp printf ("select = %s\n", (checked ? "checked" : "unchecked")); if ( checked ) { m_btnAddMoleSymbol->setChecked (false); m_ipToolbarControl->SetBuddyControl (NULL); m_ipToolbarControl->put_Enabled (VARIANT_FALSE); } else { m_ipToolbarControl->SetBuddyControl (m_ipMapControl); m_ipToolbarControl->put_Enabled (VARIANT_TRUE); } } //////////////////////////////////////////////////////// // IMapControlEvents2 implementation - event handlers // //////////////////////////////////////////////////////// void MoleSymbolsWindow::OnMapReplaced (VARIANT newMap) { // update the window title m_unitCount = 0; updateTitle(); } void MoleSymbolsWindow::OnMouseDown (long button, long shift, long x, long y, double mapX, double mapY) { m_ipLastMouseClick->PutCoords (mapX, mapY); if ( m_btnAddMoleSymbol->isChecked() ) { // "Add MOLE Symbol" command: draw a symbol at the click point drawSymbol (m_ipLastMouseClick, m_txtSIC->text().toAscii(), false); m_txtSIC->setText (getSIC()); } else if ( m_btnSelect->isChecked() ) { IActiveViewPtr ipActiveView; m_ipMapControl->get_ActiveView (&ipActiveView); if ( selectElements(m_ipLastMouseClick, ipActiveView, m_ipSelectedBounds) ) { // "Select & Drag Graphics" command: initialize mouse tracking to move the selected elements printf ("mouse down at (%f, %f)\n", mapX, mapY); // the envelope feedback draws a rectangle of the selected elements' extent following the mouse IMoveEnvelopeFeedbackPtr ipMoveEnvelopeFeedback (CLSID_MoveEnvelopeFeedback); ipMoveEnvelopeFeedback->Start (m_ipSelectedBounds, m_ipLastMouseClick); m_ipMoveFeedback = ipMoveEnvelopeFeedback; IScreenDisplayPtr ipScreenDisplay; ipActiveView->get_ScreenDisplay (&ipScreenDisplay); m_ipMoveFeedback->putref_Display (ipScreenDisplay); } } } void MoleSymbolsWindow::OnMouseMove (long button, long shift, long x, long y, double mapX, double mapY) { // update the current map location of the mouse m_ipCurrentMouseLocation->PutCoords (mapX, mapY); // "Select & Drag Graphics" command: move the feedback graphic if ( m_btnSelect->isChecked() && button == 1 && m_ipMoveFeedback ) m_ipMoveFeedback->MoveTo (m_ipCurrentMouseLocation); } void MoleSymbolsWindow::OnMouseUp (long button, long shift, long x, long y, double mapX, double mapY) { if ( m_ipMoveFeedback ) { // stop the feedback graphic and save its geometry for future use IMoveEnvelopeFeedbackPtr(m_ipMoveFeedback)->Stop (&m_ipSelectedBounds); m_ipMoveFeedback = 0; double startX, startY; m_ipLastMouseClick->QueryCoords (&startX, &startY); if ( startX != mapX || startY != mapY ) { // only update the graphics if the minimum move time has elapsed printf ("finish drag at (%f, %f)\n", mapX, mapY); moveGraphics (mapX - startX, mapY - startY); } } } //////////////////////////////// // constructor and destructor // //////////////////////////////// MoleSymbolsWindow::MoleSymbolsWindow() : m_firstTime (true), m_ipCurrentMouseLocation (createPoint(0, 0)), m_ipLastMouseClick (createPoint(0, 0)), m_ipSelectedBounds (CLSID_Envelope), m_unitCount (0) { printf ("creating widgets\n"); // create the child widgets of this window QWidget *toolbar = new QWidget (this); QToolButton *btnAdd200 = new QToolButton (toolbar); QToolButton *btnMoveUnits = new QToolButton (toolbar); m_btnSelect = new QToolButton (toolbar); m_btnAddMoleSymbol = new QToolButton (toolbar); m_txtSIC = new QLineEdit (getSIC(), toolbar); m_txtSize = new QLineEdit ("36", toolbar); QToolButton *btnAddLine = new QToolButton (toolbar); QToolButton *btnAddArea = new QToolButton (toolbar); QSplitter *split = new QSplitter (this); QAxCtl *tlbControl = new QAxCtl (AoPROGID_ToolbarControl, toolbar, "Toolbar Control"); QAxCtl *tocControl = new QAxCtl (AoPROGID_TOCControl, split, "TOC Control"); QAxCtl *mapControl = new QAxCtl (AoPROGID_MapControl, split, "Map Control"); // set properties on some of the widgets tlbControl->setMinimumHeight (28); tlbControl->setMaximumHeight (28); split->setOpaqueResize (false); QList<int> sizes (split->sizes()); sizes[0] = 250; sizes[1] = 650; split->setSizes (sizes); // set the properties on the toolbar widgets m_btnSelect ->setCheckable (true); m_btnAddMoleSymbol->setCheckable (true); btnAdd200 ->setIcon (QIcon("Add.png")); btnMoveUnits ->setIcon (QIcon("Move.png")); m_btnSelect ->setIcon (QIcon("Select.png")); m_btnAddMoleSymbol->setIcon (QIcon("Jazz.png")); btnAddLine ->setIcon (QIcon("Line.png")); btnAddArea ->setIcon (QIcon("Area.png")); btnAdd200 ->setToolTip ("Create 200 graphics"); btnMoveUnits ->setToolTip ("Move units"); m_btnSelect ->setToolTip ("Select & drag graphics"); m_txtSIC ->setToolTip ("ID code of MOLE symbol to add"); m_txtSize ->setToolTip ("Size of MOLE symbol to add"); btnAddLine ->setToolTip ("Add a sample line graphic"); btnAddArea ->setToolTip ("Add a sample area graphic"); m_btnAddMoleSymbol->setToolTip ("Add MOLE symbol"); // establish the toolbar layout QHBoxLayout *toolbarLayout = new QHBoxLayout (toolbar); toolbarLayout->setMargin (0); toolbarLayout->addWidget (btnAdd200); toolbarLayout->addWidget (btnMoveUnits); toolbarLayout->addWidget (m_btnSelect); toolbarLayout->addWidget (m_btnAddMoleSymbol); toolbarLayout->addWidget (m_txtSIC); toolbarLayout->addWidget (m_txtSize); toolbarLayout->addWidget (btnAddLine); toolbarLayout->addWidget (btnAddArea); toolbarLayout->addWidget (tlbControl, 1); // establish the main window layout QVBoxLayout *rootLayout = new QVBoxLayout (this); rootLayout->setSpacing (0); rootLayout->setMargin (2); rootLayout->addWidget (toolbar); rootLayout->addWidget (split, 1); // set properties on this widget and connect event handlers resize (900, 600); updateTitle(); connect (btnAdd200, SIGNAL(clicked()), SLOT(add200())); connect (btnMoveUnits, SIGNAL(clicked()), SLOT(moveUnits())); connect (m_btnSelect, SIGNAL(clicked(bool)), SLOT(select(bool))); connect (m_btnAddMoleSymbol, SIGNAL(clicked(bool)), SLOT(addMoleSymbol(bool))); connect (btnAddLine, SIGNAL(clicked()), SLOT(addLine())); connect (btnAddArea, SIGNAL(clicked()), SLOT(addArea())); printf ("setting up the controls\n"); // extricate the COM interfaces of the ArcGIS controls IUnknownPtr ipUnknown; mapControl->getInterface (&ipUnknown); m_ipMapControl = ipUnknown; if ( ! m_ipMapControl ) ABORT; tlbControl->getInterface (&ipUnknown); m_ipToolbarControl = ipUnknown; if ( ! m_ipToolbarControl ) ABORT; tocControl->getInterface (&ipUnknown); ITOCControlPtr ipTocControl (ipUnknown); if ( ! ipTocControl ) ABORT; // buddy up and load the toolbar ipTocControl->SetBuddyControl (m_ipMapControl); m_ipToolbarControl->SetBuddyControl (m_ipMapControl); addTool ("ControlsOpenDocCommand"); addTool ("ControlsAddDataCommand"); addTool ("ControlsSaveAsDocCommand"); addTool ("ControlsMapZoomPanTool"); addTool ("ControlsMapFullExtentCommand"); addTool ("ControlsMapZoomToLastExtentBackCommand"); addTool ("ControlsMapZoomToLastExtentForwardCommand"); addTool ("ControlsMapZoomToolControl"); addTool ("ControlsSelectTool"); addTool ("ControlsMapGoToCommand"); addTool ("ControlsMapIdentifyTool"); addTool ("ControlsMapMeasureTool"); m_ipToolbarControl->put_ToolTips (VARIANT_TRUE); // register for map control events - use static cast because argument type != interface m_ipMapControlEventsHelper.CreateInstance (CLSID_MapControlEvents2Listener); m_ipMapControlEventsHelper->Startup (static_cast<IMapControlEvents2Helper*>(this)); m_ipMapControlEventsHelper->AdviseEvents (m_ipMapControl, NULL); printf ("loading the map\n"); // load a default map file CComVariant vUndefined ((long)DISP_E_PARAMNOTFOUND, VT_ERROR); CComBSTR bstmp; m_ipMapControl->LoadMxFile ((bstmp = dsDataPath("Continents/Continents.mxd")), vUndefined, vUndefined); SysFreeString(bstmp); } MoleSymbolsWindow::~MoleSymbolsWindow() { printf ("deregistering event handler\n"); m_ipMapControlEventsHelper->UnadviseEvents(); m_ipMapControlEventsHelper->Shutdown(); printf ("releasing MOLE resources\n"); IMoleCoreHelperPtr ipMoleCoreHelper (CLSID_MoleCoreHelper); ipMoleCoreHelper->ReleaseForceElementRenderer(); // the controls are in the Qt tree, but dereference them for completeness m_ipMapControl = 0; m_ipMapControlEventsHelper = 0; m_ipToolbarControl = 0; }