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