About the Using MOLE symbol-based graphics with interactive maps Sample
[C#]
MainForm.cs
using System; using System.Collections; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Windows.Forms; using ESRI.ArcGIS.ADF; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.DataSourcesFile; using ESRI.ArcGIS.DefenseSolutions; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.SystemUI; namespace MoleSymbols { public sealed partial class MainForm : Form { #region class private members private IPoint m_currentMouseLocation = null; private int m_dragStartTime = 0; private bool m_firstTime = true; private IPoint m_lastMouseClick = new PointClass(); private IMapControl3 m_mapControl = null; private IDisplayFeedback m_moveFeedBack = null; private Random m_random = new Random(); private IEnvelope m_selectedBounds = new EnvelopeClass(); private DemoSIC m_sic = new DemoSIC(); private int m_unitCount = 0; #endregion #region Constructor public MainForm() { InitializeComponent(); m_lastMouseClick.PutCoords (0, 0); UpdateStatusBar(); UpdateTitle(); } #endregion #region Tool strip button event handlers private void tsbAdd200_Click (object sender, EventArgs e) { // this one takes a little while, especially when it's the first one chosen Cursor = Cursors.WaitCursor; // create concentric rings of units centered around where the user last clicked double centerLon = m_lastMouseClick.X; double centerLat = m_lastMouseClick.Y; 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 * Math.Sin(currentAngle)), centerLat + (currentRadius * Math.Cos(currentAngle)) ), m_sic[m_random.Next()], true ); } //refresh the display and restore the cursor axMapControl1.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); Cursor = Cursors.Default; } private void tsbAddArea_Click (object sender, EventArgs e) { // create the symbol using a default symbol ID code (obstacle restricted area) IMoleSymbol moleSymbol = new MoleFillSymbolClass(); moleSymbol.SymbolID = "GUMPOGR-------X"; moleSymbol.TextLabels = GetLabels(); // override the default fill color and outline symbol - these settings are optional //ILineSymbol lineSymbol = new SimpleLineSymbolClass(); //lineSymbol.Color = GetRandomColor(); //lineSymbol.Width = dRandom (1, 5); //IFillSymbol fillSymbol = moleSymbol as IFillSymbol; //fillSymbol.Outline = lineSymbol; //fillSymbol.Color = GetRandomColor(); // create a new polygon geometry for this symbol (four points in this example) IPointCollection pointCollection = new PolygonClass(); // center the polygon somewhere inside the current map extent IEnvelope extent = m_mapControl.ActiveView.Extent; double lat = dRandom (extent.YMin, extent.YMax); double lon = dRandom (extent.XMin, extent.XMax); // place the four corners somewhere within a specified threshold of the center const double threshold = 20; object missing = Type.Missing; pointCollection.AddPoint (CreatePoint(lon, dRandom(lat, lat + threshold)), ref missing, ref missing); pointCollection.AddPoint (CreatePoint(dRandom(lon, lon + threshold), lat), ref missing, ref missing); pointCollection.AddPoint (CreatePoint(lon, dRandom(lat - threshold, lat)), ref missing, ref missing); pointCollection.AddPoint (CreatePoint(dRandom(lon - threshold, lon), lat), ref missing, ref missing); // set up the graphic element with the random geometry IFillShapeElement fillShapeElement = new PolygonElementClass(); fillShapeElement.Symbol = moleSymbol as IFillSymbol; IElement element = fillShapeElement as IElement; element.Geometry = pointCollection as IGeometry; // add the new element to the map and update the user interface m_mapControl.ActiveView.GraphicsContainer.AddElement (element, 0); m_mapControl.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); ++m_unitCount; UpdateTitle(); } private void tsbAddLine_Click (object sender, EventArgs e) { // create the symbol using a default symbol ID code (fix task line) IMoleSymbol moleSymbol = new MoleLineSymbolClass(); moleSymbol.SymbolID = "GUTPF---------X"; moleSymbol.TextLabels = GetLabels(); // override the default line color and width - these settings are optional //ILineSymbol lineSymbol = moleSymbol as ILineSymbol; //lineSymbol.Color = GetRandomColor(); //lineSymbol.Width = dRandom (1, 5); // create a new line geometry for the symbol - this symbol requires two points IPointCollection pointCollection = new PolylineClass(); // place the first endpoint of the line somewhere inside the current map extent IEnvelope ext = m_mapControl.ActiveView.Extent; double lat = dRandom (ext.YMin, ext.YMax); double lon = dRandom (ext.XMin, ext.XMax); object missing = Type.Missing; pointCollection.AddPoint (CreatePoint(lon, lat), ref missing, ref missing); // place the second endpoint somewhere within a specified threshold of the first const double threshold = 20; pointCollection.AddPoint ( CreatePoint( dRandom(lon - threshold, lon + threshold), dRandom(lat - threshold, lat + threshold) ), ref missing, ref missing ); // set up the graphic element with the random geometry ILineElement lineElement = new LineElementClass(); lineElement.Symbol = moleSymbol as ILineSymbol; IElement element = lineElement as IElement; element.Geometry = pointCollection as IGeometry; // add the new element to the map and update the user interface m_mapControl.ActiveView.GraphicsContainer.AddElement (element, 0); m_mapControl.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); ++m_unitCount; UpdateTitle(); } private void tsbAddMoleSymbol_Click (object sender, EventArgs e) { // make this TSB exclusive both in the tool strip and in the AxToolbarControl // the primary logic is in axMapControl1_OnMouseDown if ( tsbAddMoleSymbol.Checked ) { axToolbarControl1.SetBuddyControl (null); axToolbarControl1.Enabled = false; tsbSelect.Checked = false; } else { axToolbarControl1.SetBuddyControl (axMapControl1); axToolbarControl1.Enabled = true; } } private void tsbMoveUnits_Click (object sender, EventArgs e) { // MoveGraphics only applies to units in the selection - this will erase any previous selection IGraphicsContainerSelect graphicsContainerSelect = m_mapControl.ActiveView.GraphicsContainer as IGraphicsContainerSelect; graphicsContainerSelect.SelectAllElements(); MoveGraphics (0.75, 0.75); graphicsContainerSelect.UnselectAllElements(); m_selectedBounds.SetEmpty(); } private void tsbSelect_Click (object sender, EventArgs e) { // make this TSB exclusive both in the tool strip and in the AxToolbarControl // the primary logic is in axMapControl1_OnMouseDown and axMapControl1_OnMouseMove if ( tsbSelect.Checked ) { axToolbarControl1.SetBuddyControl (null); axToolbarControl1.Enabled = false; tsbAddMoleSymbol.Checked = false; } else { axToolbarControl1.SetBuddyControl (axMapControl1); axToolbarControl1.Enabled = true; } } #endregion #region Form event handlers private string GetSdkDataPath() { //get the ArcGIS path from the registry Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\ESRI\ArcGIS_SXS_SDK"); string path = Convert.ToString(key.GetValue("InstallDir")); //set the of the logo string str = System.IO.Path.Combine(path, @"Samples\data\"); if (!System.IO.Directory.Exists(str)) { MessageBox.Show("Path :" + str + " does not exist!"); return string.Empty; } return str; } private void MainForm_Load (object sender, EventArgs e) { // get a reference to the MapControl for local use m_mapControl = axMapControl1.Object as IMapControl3; // get a map from the SDK sample data string dataPath = GetSdkDataPath() + @"MilitaryOverlayEditor\"; string defaultMxDoc = dataPath + "molebasemap.mxd"; if ( m_mapControl.CheckMxFile(defaultMxDoc) ) { // load the map into the map control object missing = Type.Missing; m_mapControl.LoadMxFile (defaultMxDoc, missing, missing); } else { string errorMsg = "Could not load default map document - Application may not work!"; errorMsg += Environment.NewLine + defaultMxDoc; Trace.WriteLine (errorMsg); MessageBox.Show (errorMsg); } } private void MainForm_FormClosing (object sender, FormClosingEventArgs e) { // tell MOLE to save its settings and release its resources (new MoleCoreHelperClass()).ReleaseForceElementRenderer(); } #endregion #region Map control event handlers private void axMapControl1_OnMapReplaced (object sender, IMapControlEvents2_OnMapReplacedEvent e) { // initialize the last mouse click point to the center of the map's extent IEnvelope extent = m_mapControl.ActiveView.Extent; m_lastMouseClick.PutCoords ( extent.XMin + extent.Width * 0.5, extent.YMin + extent.Height * 0.5 ); // update the status bar and the title bar m_unitCount = 0; UpdateStatusBar(); UpdateTitle(); } private void axMapControl1_OnMouseDown (object sender, IMapControlEvents2_OnMouseDownEvent e) { m_lastMouseClick.PutCoords (e.mapX, e.mapY); if ( tsbAddMoleSymbol.Checked ) { // "Add MOLE Symbol" command: draw a symbol at the click point DrawSymbol (m_lastMouseClick, tstSIC.Text, false); tstSIC.Text = m_sic[m_random.Next()]; } else if ( tsbSelect.Checked && SelectElements(m_lastMouseClick, m_mapControl.ActiveView, m_selectedBounds) ) { // "Select & Drag Graphics" command: initialize mouse tracking to move the selected elements Trace.WriteLine ("Start tracking at (" + m_lastMouseClick.X + ", " + m_lastMouseClick.Y + ")"); // the envelope feedback draws a rectangle of the selected elements' extent following the mouse IMoveEnvelopeFeedback moveEnvelopeFeedback = new MoveEnvelopeFeedbackClass(); moveEnvelopeFeedback.Start (m_selectedBounds, m_lastMouseClick); m_moveFeedBack = moveEnvelopeFeedback as IDisplayFeedback; m_moveFeedBack.Display = axMapControl1.ActiveView.ScreenDisplay; // the tick count is used to filter out short, unintentional mouse drags m_dragStartTime = Environment.TickCount; } } private void axMapControl1_OnMouseMove (object sender, IMapControlEvents2_OnMouseMoveEvent e) { // update the current map location of the mouse if ( m_currentMouseLocation == null ) m_currentMouseLocation = new PointClass(); m_currentMouseLocation.PutCoords (e.mapX, e.mapY); UpdateStatusBar(); // "Select & Drag Graphics" command: move the feedback graphic if ( tsbSelect.Checked && e.button == 1 && m_moveFeedBack != null ) m_moveFeedBack.MoveTo (m_currentMouseLocation); } private void axMapControl1_OnMouseUp (object sender, IMapControlEvents2_OnMouseUpEvent e) { if ( m_moveFeedBack != null ) { // stop the feedback graphic and save its geometry for future use m_selectedBounds = ((IMoveEnvelopeFeedback)m_moveFeedBack).Stop(); m_moveFeedBack = null; int endTicks = Environment.TickCount - m_dragStartTime; if ( endTicks > 250 && m_currentMouseLocation != null ) { // only update the graphics if the minimum move time has elapsed Trace.WriteLine ("drag start = (" + m_lastMouseClick.X + ", " + m_lastMouseClick.Y + ")"); Trace.WriteLine ("drag end = (" + m_currentMouseLocation.X + ", " + m_currentMouseLocation.Y + ")"); MoveGraphics ( m_currentMouseLocation.X - m_lastMouseClick.X, m_currentMouseLocation.Y - m_lastMouseClick.Y ); } } } #endregion #region Helper Methods private IPoint CreatePoint (double x, double y) { // create a new point instance and initialize its coordinates IPoint point = new PointClass(); point.PutCoords (x, y); return point; } private void DrawSymbol (IPoint location, string sic, bool suppressRefresh) { // the first time we create a symbol, display the wait cursor while MOLE loads up System.Windows.Forms.Cursor previousCursor = Cursor; if ( m_firstTime ) Cursor = Cursors.WaitCursor; // set up a MOLE symbol for the new graphic; minimally validate the symbol ID code IMoleSymbol moleSymbol = new MoleMarkerSymbolClass(); if ( sic.Length == 15 ) moleSymbol.SymbolID = sic; moleSymbol.TextLabels = GetLabels(); // to remove the symbol's fill, uncomment this code //IMoleMarkerSymbol moleMarkerSymbol = moleSymbol as IMoleMarkerSymbol; //moleMarkerSymbol.ShowFill = false; // initialize the marker symbol properties IMarkerSymbol markerSymbol = moleSymbol as IMarkerSymbol; double size; if ( Double.TryParse(tstSize.Text, out size) ) markerSymbol.Size = size; else markerSymbol.Size = 48; // create the graphic element for the marker symbol and add it to the map IMarkerElement markerElement = new MarkerElementClass(); markerElement.Symbol = markerSymbol; IElement element = markerElement as IElement; element.Geometry = location as IGeometry; m_mapControl.ActiveView.GraphicsContainer.AddElement (element, 0); if ( ! suppressRefresh ) m_mapControl.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); // update the user interface if ( m_firstTime ) { Cursor = previousCursor; m_firstTime = false; } ++m_unitCount; UpdateTitle(); } private double dRandom (double low, double high) { // generate a random floating-point number within the indicated range [low, high) return low + m_random.NextDouble() * (high - low); } private IPropertySet GetLabels() { IPropertySet labelSet = new PropertySetClass(); // all of the below are supported - comment and uncomment to experiment labelSet.SetProperty ("Name", "Name"); labelSet.SetProperty ("Comment", "Comment"); //labelSet.SetProperty ("Parent", "Parent"); //labelSet.SetProperty ("Info", "Info"); //labelSet.SetProperty ("Strength", "Strength"); //labelSet.SetProperty ("EvalRating", "EvalRating"); //labelSet.SetProperty ("Location", "Location"); //labelSet.SetProperty ("Alt_Depth", "Alt_Depth"); //labelSet.SetProperty ("Speed", "Speed"); //labelSet.SetProperty ("DTG", "DTG"); //labelSet.SetProperty ("HQ", "HQ"); //labelSet.SetProperty ("Quantity", "Quantity"); //labelSet.SetProperty ("EType", "EType"); //labelSet.SetProperty ("Effective", "Effective"); //labelSet.SetProperty ("Signature", "Signature"); //labelSet.SetProperty ("IFFSIF", "IFFSIF"); return labelSet; } private IColor GetRandomColor() { // create a random opaque RGB color IRgbColor rgb = new RgbColorClass(); rgb.Red = m_random.Next (0, 255); rgb.Green = m_random.Next (0, 255); rgb.Blue = m_random.Next (0, 255); return rgb as IColor; } private void MoveGraphics (double deltaX, double deltaY) { try { // move all selected graphics along a delta (change) vector Trace.WriteLine ("moving delta = (" + deltaX + ", " + deltaY + ")"); // get reference to graphics container and its selected elements IGraphicsContainer graphicsContainer = axMapControl1.ActiveView.GraphicsContainer; IGraphicsContainerSelect graphicsContainerSelect = graphicsContainer as IGraphicsContainerSelect; IEnumElement enumElement = graphicsContainerSelect.SelectedElements; // iterate through the selected elements enumElement.Reset(); IElement element = enumElement.Next(); while (element != null) { // apply the delta vector to each element's geometry and update it the container IGeometry geometry = element.Geometry; (geometry as ITransform2D).Move (deltaX, deltaY); element.Geometry = geometry; graphicsContainer.UpdateElement (element); element = enumElement.Next(); } // refresh the active view axMapControl1.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); } catch ( Exception ex ) { MessageBox.Show ("Exception: " + ex.GetBaseException().ToString(), "MoveGraphics"); } } private bool SelectElements (IPoint point, IActiveView activeView, IEnvelope selectedBounds) { // this function is written in such a way that it should be pastable Trace.WriteLine ("selecting graphics near (" + point.X + ", " + point.Y + ")"); IGraphicsContainer graphicsContainer = activeView.GraphicsContainer; IGraphicsContainerSelect graphicsContainerSelect = graphicsContainer as IGraphicsContainerSelect; IScreenDisplay screenDisplay = activeView.ScreenDisplay; bool selected = false; bool refreshRequired = false; // 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) IEnumElement enumElement = graphicsContainer.LocateElements (point, 0.0000001); if ( enumElement == null ) enumElement = graphicsContainer.LocateElements (point, 0.5); // if no elements were selected if ( enumElement == null ) { // if the previous selection is nonempty if ( graphicsContainerSelect.ElementSelectionCount > 0 ) { // clear the selection and refresh the display Trace.WriteLine ("clearing selection"); graphicsContainerSelect.UnselectAllElements(); selectedBounds.SetEmpty(); refreshRequired = true; } // else do nothing } else { // get the extent of the selected elements IEnvelope envelope = new EnvelopeClass(); enumElement.Reset(); IElement element = enumElement.Next(); while ( element != null ) { // establish selectedBounds as the extent of all selected elements element.QueryBounds (screenDisplay, envelope); selectedBounds.Union (envelope); element = enumElement.Next(); } // add all the newly selected elements to the graphics container's selection enumElement.Reset(); graphicsContainerSelect.SelectElements (enumElement); refreshRequired = selected = true; } // refresh the display if anything has changed if ( refreshRequired ) activeView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); // return true if any elements on the display are currently selected; selectedBounds has their extent return selected; } private void UpdateStatusBar() { if ( m_mapControl != null ) { // put the MXD name and current mouse location in the status bar, if available string documentFileName = System.IO.Path.GetFileName (m_mapControl.DocumentFilename); if ( documentFileName == null || documentFileName == String.Empty ) documentFileName = "<no map>"; if ( m_currentMouseLocation == null ) statusBarXY.Text = documentFileName; else statusBarXY.Text = String.Format ( "{0}: {1}, {2} {3}", documentFileName, m_currentMouseLocation.X.ToString("#######.##"), m_currentMouseLocation.Y.ToString("#######.##"), axMapControl1.MapUnits.ToString().Substring(4) ); } } private void UpdateTitle() { // put the number of symbols in the title bar, when there are any string title = "MOLE Symbols"; if ( m_unitCount == 1 ) title += " (" + m_unitCount + " unit)"; else if ( m_unitCount > 1 ) title += " (" + m_unitCount + " units)"; Text = title; } #endregion } }
[Visual Basic .NET]
MainForm.vb
Imports System Imports System.Collections Imports System.ComponentModel Imports System.Diagnostics Imports System.Drawing Imports System.IO Imports System.Runtime.InteropServices Imports System.Windows.Forms Imports ESRI.ArcGIS.ADF Imports ESRI.ArcGIS.Carto Imports ESRI.ArcGIS.Controls Imports ESRI.ArcGIS.DataSourcesFile Imports ESRI.ArcGIS.DefenseSolutions Imports ESRI.ArcGIS.Display Imports ESRI.ArcGIS.esriSystem Imports ESRI.ArcGIS.Geodatabase Imports ESRI.ArcGIS.Geometry Imports ESRI.ArcGIS.SystemUI Imports ESRI.ArcGIS Namespace MoleSymbols Public NotInheritable Partial Class MainForm Inherits Form #Region "class private members" Private m_currentMouseLocation As IPoint = Nothing Private m_firstTime As Boolean = True Private m_lastMouseClick As IPoint = New PointClass() Private m_mapControl As IMapControl3 = Nothing Private m_moveFeedBack As IDisplayFeedback = Nothing Private m_random As New Random() Private m_selectedBounds As IEnvelope = New EnvelopeClass() Private m_sic As New DemoSIC() Private m_dragStartTime As Integer = 0 Private m_unitCount As Integer = 0 #End Region #Region "Constructor" Public Sub New() InitializeComponent() m_lastMouseClick.PutCoords(0, 0) UpdateStatusBar() UpdateTitle() End Sub #End Region #Region "Tool strip button event handlers" Private Sub tsbAdd200_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tsbAdd200.Click ' this one takes a little while, especially when it's the first one chosen Cursor = Cursors.WaitCursor ' create concentric rings of units centered around where the user last clicked Dim centerLon As Double = m_lastMouseClick.X Dim centerLat As Double = m_lastMouseClick.Y Const circleRadiusInRad As Double = 1 Const numberPerCircle As Integer = 10 For i As Integer = 0 To 199 ' draw a random symbol at the next position in the pattern Dim currentRadius As Double = (i / numberPerCircle) * circleRadiusInRad + circleRadiusInRad Dim currentAngle As Double = (i Mod numberPerCircle) * 2 * 3.1415926536 / CDbl(numberPerCircle) DrawSymbol(CreatePoint(centerLon + (currentRadius * Math.Sin(currentAngle)), centerLat + (currentRadius * Math.Cos(currentAngle))), m_sic(m_random.Next()), True) Next 'refresh the display and restore the cursor axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) Cursor = Cursors.Default End Sub Private Sub tsbAddArea_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tsbAddArea.Click ' create the symbol using a default symbol ID code (obstacle restricted area) Dim moleSymbol As IMoleSymbol = New MoleFillSymbolClass() moleSymbol.SymbolID = "GUMPOGR-------X" moleSymbol.TextLabels = GetLabels() ' override the default fill color and outline symbol - these settings are optional 'Dim lineSymbol As ILineSymbol = New SimpleLineSymbolClass() 'lineSymbol.Color = GetRandomColor() 'lineSymbol.Width = dRandom(1, 5) 'Dim fillSymbol As IFillSymbol = TryCast(moleSymbol, IFillSymbol) 'fillSymbol.Outline = lineSymbol 'fillSymbol.Color = GetRandomColor() ' create a new polygon geometry for this symbol (four points in this example) Dim pointCollection As IPointCollection = New PolygonClass() ' center the polygon somewhere inside the current map extent Dim extent As IEnvelope = m_mapControl.ActiveView.Extent Dim lat As Double = dRandom(extent.YMin, extent.YMax) Dim lon As Double = dRandom(extent.XMin, extent.XMax) ' place the four corners somewhere within a specified threshold of the center Const threshold As Double = 20 Dim missing As Object = Type.Missing pointCollection.AddPoint(CreatePoint(lon, dRandom(lat, lat + threshold)), missing, missing) pointCollection.AddPoint(CreatePoint(dRandom(lon, lon + threshold), lat), missing, missing) pointCollection.AddPoint(CreatePoint(lon, dRandom(lat - threshold, lat)), missing, missing) pointCollection.AddPoint(CreatePoint(dRandom(lon - threshold, lon), lat), missing, missing) ' set up the graphic element with the random geometry Dim fillShapeElement As IFillShapeElement = New PolygonElementClass() fillShapeElement.Symbol = TryCast(moleSymbol, IFillSymbol) Dim element As IElement = TryCast(fillShapeElement, IElement) element.Geometry = TryCast(pointCollection, IGeometry) ' add the new element to the map and update the user interface m_mapControl.ActiveView.GraphicsContainer.AddElement(element, 0) m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) m_unitCount += 1 UpdateTitle() End Sub Private Sub tsbAddLine_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tsbAddLine.Click ' create the symbol using a default symbol ID code (fix task line) Dim moleSymbol As IMoleSymbol = New MoleLineSymbolClass() moleSymbol.SymbolID = "GUTPF---------X" moleSymbol.TextLabels = GetLabels() ' override the default line color and width - these settings are optional 'Dim lineSymbol As ILineSymbol = TryCast(moleSymbol, ILineSymbol) 'lineSymbol.Color = GetRandomColor() 'lineSymbol.Width = dRandom(1, 5) ' create a new line geometry for the symbol - this symbol requires two points Dim pointCollection As IPointCollection = New PolylineClass() ' place the first endpoint of the line somewhere inside the current map extent Dim ext As IEnvelope = m_mapControl.ActiveView.Extent Dim lat As Double = dRandom(ext.YMin, ext.YMax) Dim lon As Double = dRandom(ext.XMin, ext.XMax) Dim missing As Object = Type.Missing pointCollection.AddPoint(CreatePoint(lon, lat), missing, missing) ' place the second endpoint somewhere within a specified threshold of the first Const threshold As Double = 20 pointCollection.AddPoint(CreatePoint(dRandom(lon - threshold, lon + threshold), dRandom(lat - threshold, lat + threshold)), missing, missing) ' set up the graphic element with the random geometry Dim lineElement As ILineElement = New LineElementClass() lineElement.Symbol = TryCast(moleSymbol, ILineSymbol) Dim element As IElement = TryCast(lineElement, IElement) element.Geometry = TryCast(pointCollection, IGeometry) ' add the new element to the map and update the user interface m_mapControl.ActiveView.GraphicsContainer.AddElement(element, 0) m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) m_unitCount += 1 UpdateTitle() End Sub Private Sub tsbAddMoleSymbol_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tsbAddMoleSymbol.Click ' make this TSB exclusive both in the tool strip and in the AxToolbarControl ' the primary logic is in axMapControl1_OnMouseDown If tsbAddMoleSymbol.Checked Then axToolbarControl1.SetBuddyControl(Nothing) axToolbarControl1.Enabled = False tsbSelect.Checked = False Else axToolbarControl1.SetBuddyControl(axMapControl1) axToolbarControl1.Enabled = True End If End Sub Private Sub tsbMoveUnits_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tsbMoveUnits.Click ' MoveGraphics only applies to units in the selection - this will erase any previous selection Dim graphicsContainerSelect As IGraphicsContainerSelect = TryCast(m_mapControl.ActiveView.GraphicsContainer, IGraphicsContainerSelect) graphicsContainerSelect.SelectAllElements() MoveGraphics(0.75, 0.75) graphicsContainerSelect.UnselectAllElements() m_selectedBounds.SetEmpty() End Sub Private Sub tsbSelect_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tsbSelect.Click ' make this TSB exclusive both in the tool strip and in the AxToolbarControl ' the primary logic is in axMapControl1_OnMouseDown and axMapControl1_OnMouseMove If tsbSelect.Checked Then axToolbarControl1.SetBuddyControl(Nothing) axToolbarControl1.Enabled = False tsbAddMoleSymbol.Checked = False Else axToolbarControl1.SetBuddyControl(axMapControl1) axToolbarControl1.Enabled = True End If End Sub #End Region #Region "Form event handlers" Private Function GetSdkDataPath() As String 'get the ArcGIS path from the registry Dim key As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\ESRI\ArcGIS_SXS_SDK") Dim path As String = Convert.ToString(key.GetValue("InstallDir")) 'set the of the logo Dim str As String = System.IO.Path.Combine(path, "Samples\data\") If (Not System.IO.Directory.Exists(str)) Then MessageBox.Show("Path :" & str & " does not exist!") Return String.Empty End If Return str End Function Private Sub MainForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load ' get a reference to the MapControl for local use m_mapControl = DirectCast(axMapControl1.Object, IMapControl3) ' get a map from the SDK sample data Dim dataPath As String = GetSdkDataPath() + "MilitaryOverlayEditor\" Dim defaultMxDoc As String = dataPath & "molebasemap.mxd" If m_mapControl.CheckMxFile(defaultMxDoc) Then ' load the map into the map control Dim missing As Object = System.Reflection.Missing.Value m_mapControl.LoadMxFile(defaultMxDoc, missing, missing) Else Dim errorMsg As String = "Could not load default map document - Application may not work!" errorMsg &= Environment.NewLine & defaultMxDoc Trace.WriteLine(errorMsg) MessageBox.Show(errorMsg) End If End Sub Private Sub MainForm_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing ' tell MOLE to save its settings and release its resources Dim helper As IMoleCoreHelper = New MoleCoreHelperClass() helper.ReleaseForceElementRenderer() End Sub #End Region #Region "Map control event handlers" Private Sub axMapControl1_OnMapReplaced(ByVal sender As Object, ByVal e As IMapControlEvents2_OnMapReplacedEvent) Handles axMapControl1.OnMapReplaced ' initialize the last mouse click point to the center of the map's extent Dim extent As IEnvelope = m_mapControl.ActiveView.Extent m_lastMouseClick.PutCoords(extent.XMin + extent.Width * 0.5, extent.YMin + extent.Height * 0.5) ' update the status bar and the title bar m_unitCount = 0 UpdateStatusBar() UpdateTitle() End Sub Private Sub axMapControl1_OnMouseDown(ByVal sender As Object, ByVal e As IMapControlEvents2_OnMouseDownEvent) Handles axMapControl1.OnMouseDown m_lastMouseClick.PutCoords(e.mapX, e.mapY) If tsbAddMoleSymbol.Checked Then ' "Add MOLE Symbol" command: draw a symbol at the click point DrawSymbol(m_lastMouseClick, tstSIC.Text, False) tstSIC.Text = m_sic(m_random.Next()) ElseIf tsbSelect.Checked AndAlso SelectElements(m_lastMouseClick, m_mapControl.ActiveView, m_selectedBounds) = True Then ' "Select & Drag Graphics" command: initialize mouse tracking to move the selected elements Trace.WriteLine("Start tracking at (" & m_lastMouseClick.X & ", " & m_lastMouseClick.Y & ")") ' the envelope feedback draws a rectangle of the selected elements' extent following the mouse Dim moveEnvelopeFeedback As IMoveEnvelopeFeedback = New MoveEnvelopeFeedback() moveEnvelopeFeedback.Start(m_selectedBounds, m_lastMouseClick) m_moveFeedBack = TryCast(moveEnvelopeFeedback, IDisplayFeedback) m_moveFeedBack.Display = axMapControl1.ActiveView.ScreenDisplay ' the tick count is used to filter out short, unintentional mouse drags m_dragStartTime = Environment.TickCount End If End Sub Private Sub axMapControl1_OnMouseMove(ByVal sender As Object, ByVal e As IMapControlEvents2_OnMouseMoveEvent) Handles axMapControl1.OnMouseMove ' update the current map location of the mouse If m_currentMouseLocation Is Nothing Then m_currentMouseLocation = New PointClass() End If m_currentMouseLocation.PutCoords(e.mapX, e.mapY) UpdateStatusBar() ' "Select & Drag Graphics" command: move the feedback graphic If tsbSelect.Checked AndAlso e.button = 1 AndAlso m_moveFeedBack IsNot Nothing Then m_moveFeedBack.MoveTo(m_currentMouseLocation) End If End Sub Private Sub axMapControl1_OnMouseUp(ByVal sender As Object, ByVal e As IMapControlEvents2_OnMouseUpEvent) Handles axMapControl1.OnMouseUp If m_moveFeedBack IsNot Nothing Then ' stop the feedback graphic and save its geometry for future use m_selectedBounds = DirectCast(m_moveFeedBack, IMoveEnvelopeFeedback).Stop() m_moveFeedBack = Nothing Dim endTicks As Integer = Environment.TickCount - m_dragStartTime If endTicks > 250 AndAlso m_currentMouseLocation IsNot Nothing Then ' only update the graphics if the minimum move time has elapsed Trace.WriteLine("drag start = (" & m_lastMouseClick.X & ", " & m_lastMouseClick.Y & ")") Trace.WriteLine("drag end = (" & m_currentMouseLocation.X & ", " & m_currentMouseLocation.Y & ")") MoveGraphics(m_currentMouseLocation.X - m_lastMouseClick.X, m_currentMouseLocation.Y - m_lastMouseClick.Y) End If End If End Sub #End Region #Region "Helper Methods" Private Function CreatePoint(ByVal x As Double, ByVal y As Double) As IPoint ' create a new point instance and initialize its coordinates Dim point As IPoint = New PointClass() point.PutCoords(x, y) Return point End Function Private Sub DrawSymbol(ByVal location As IPoint, ByVal sic As String, ByVal suppressRefresh As Boolean) ' the first time we create a symbol, display the wait cursor while MOLE loads up Dim previousCursor As System.Windows.Forms.Cursor = Cursor If m_firstTime Then Cursor = Cursors.WaitCursor End If ' set up a MOLE symbol for the new graphic; minimally validate the symbol ID code Dim moleSymbol As IMoleSymbol = New MoleMarkerSymbolClass() If sic.Length = 15 Then moleSymbol.SymbolID = sic End If moleSymbol.TextLabels = GetLabels() ' to remove the symbol's fill, uncomment this code 'Dim moleMarkerSymbol As IMoleMarkerSymbol = TryCast(moleSymbol, IMoleMarkerSymbol) 'moleMarkerSymbol.ShowFill = False ' initialize the marker symbol properties Dim markerSymbol As IMarkerSymbol = TryCast(moleSymbol, IMarkerSymbol) Dim size As Double If Double.TryParse(tstSize.Text, size) Then markerSymbol.Size = size Else markerSymbol.Size = 48 End If ' create the graphic element for the marker symbol and add it to the map Dim markerElement As IMarkerElement = New MarkerElementClass() markerElement.Symbol = markerSymbol Dim element As IElement = TryCast(markerElement, IElement) element.Geometry = TryCast(location, IGeometry) m_mapControl.ActiveView.GraphicsContainer.AddElement(element, 0) If Not suppressRefresh Then m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) End If ' update the user interface If m_firstTime Then Cursor = previousCursor m_firstTime = False End If m_unitCount += 1 UpdateTitle() End Sub Private Function dRandom(ByVal low As Double, ByVal high As Double) As Double ' generate a random floating-point number within the indicated range [low, high) Return low + m_random.NextDouble() * (high - low) End Function Private Function GetLabels() As IPropertySet Dim labelSet As IPropertySet = New PropertySetClass() ' all of the below are supported - comment and uncomment to experiment labelSet.SetProperty("Name", "Name") labelSet.SetProperty("Comment", "Comment") 'labelSet.SetProperty ("Parent", "Parent"); 'labelSet.SetProperty ("Info", "Info"); 'labelSet.SetProperty ("Strength", "Strength"); 'labelSet.SetProperty ("EvalRating", "EvalRating"); 'labelSet.SetProperty ("Location", "Location"); 'labelSet.SetProperty ("Alt_Depth", "Alt_Depth"); 'labelSet.SetProperty ("Speed", "Speed"); 'labelSet.SetProperty ("DTG", "DTG"); 'labelSet.SetProperty ("HQ", "HQ"); 'labelSet.SetProperty ("Quantity", "Quantity"); 'labelSet.SetProperty ("EType", "EType"); 'labelSet.SetProperty ("Effective", "Effective"); 'labelSet.SetProperty ("Signature", "Signature"); 'labelSet.SetProperty ("IFFSIF", "IFFSIF"); Return labelSet End Function Private Function GetRandomColor() As IColor ' create a random opaque RGB color Dim rgb As IRgbColor = New RgbColorClass() rgb.Red = m_random.Next(0, 255) rgb.Green = m_random.Next(0, 255) rgb.Blue = m_random.Next(0, 255) Return TryCast(rgb, IColor) End Function Private Sub MoveGraphics(ByVal deltaX As Double, ByVal deltaY As Double) Try ' move all selected graphics along a delta (change) vector Trace.WriteLine("moving delta = (" & deltaX & ", " & deltaY & ")") ' get reference to graphics container and its selected elements Dim graphicsContainer As IGraphicsContainer = axMapControl1.ActiveView.GraphicsContainer Dim graphicsContainerSelect As IGraphicsContainerSelect = TryCast(graphicsContainer, IGraphicsContainerSelect) Dim enumElement As IEnumElement = graphicsContainerSelect.SelectedElements ' iterate through the selected elements enumElement.Reset() Dim element As IElement = enumElement.Next() While element IsNot Nothing ' apply the delta vector to each element's geometry and update it the container Dim geometry As IGeometry = element.Geometry TryCast(geometry, ITransform2D).Move(deltaX, deltaY) element.Geometry = geometry graphicsContainer.UpdateElement(element) element = enumElement.Next() End While ' refresh the active view axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) Catch ex As Exception MessageBox.Show("Exception: " & ex.GetBaseException().ToString(), "MoveGraphics") End Try End Sub Private Function SelectElements(ByVal point As IPoint, ByVal activeView As IActiveView, ByVal selectedBounds As IEnvelope) As Boolean ' this function is written in such a way that it should be pastable Trace.WriteLine("selecting graphics near (" & point.X & ", " & point.Y & ")") Dim graphicsContainer As IGraphicsContainer = activeView.GraphicsContainer Dim graphicsContainerSelect As IGraphicsContainerSelect = TryCast(graphicsContainer, IGraphicsContainerSelect) Dim screenDisplay As IScreenDisplay = activeView.ScreenDisplay Dim selected As Boolean = False Dim refreshRequired As Boolean = False ' 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) Dim enumElement As IEnumElement = graphicsContainer.LocateElements(point, 0.0000001) If enumElement Is Nothing Then enumElement = graphicsContainer.LocateElements(point, 0.5) End If ' if no elements were selected If enumElement Is Nothing Then ' if the previous selection is nonempty If graphicsContainerSelect.ElementSelectionCount > 0 Then ' clear the selection and refresh the display Trace.WriteLine("clearing selection") graphicsContainerSelect.UnselectAllElements() selectedBounds.SetEmpty() refreshRequired = True ' else do nothing End If Else ' get the extent of the selected elements Dim envelope As IEnvelope = New EnvelopeClass() enumElement.Reset() Dim element As IElement = enumElement.Next() While element IsNot Nothing ' establish selectedBounds as the extent of all selected elements element.QueryBounds(screenDisplay, envelope) selectedBounds.Union(envelope) element = enumElement.Next() End While ' add all the newly selected elements to the graphics container's selection enumElement.Reset() graphicsContainerSelect.SelectElements(enumElement) refreshRequired = True selected = True End If ' refresh the display if anything has changed If refreshRequired Then activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) End If ' return true if any elements on the display are currently selected; selectedBounds has their extent Return selected End Function Private Sub UpdateStatusBar() If m_mapControl IsNot Nothing Then ' put the MXD name and current mouse location in the status bar, if available Dim documentFileName As String = System.IO.Path.GetFileName(m_mapControl.DocumentFilename) If documentFileName Is Nothing OrElse documentFileName = String.Empty Then documentFileName = "<no map>" End If If m_currentMouseLocation Is Nothing Then statusBarXY.Text = documentFileName Else statusBarXY.Text = String.Format("{0}: {1}, {2} {3}", documentFileName, m_currentMouseLocation.X.ToString("#######.##"), m_currentMouseLocation.Y.ToString("#######.##"), axMapControl1.MapUnits.ToString().Substring(4)) End If End If End Sub Private Sub UpdateTitle() ' put the number of symbols in the title bar, when there are any Dim title As String = "MOLE Symbols" If m_unitCount = 1 Then title &= " (" & m_unitCount & " unit)" ElseIf m_unitCount > 1 Then title &= " (" & m_unitCount & " units)" End If Text = title End Sub #End Region End Class End Namespace