About the Network Analyst Engine application Sample
[C#]
frmMain.cs
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.SystemUI; using ESRI.ArcGIS.NetworkAnalyst; using ESRI.ArcGIS.Geodatabase; // This is the main form of the application. namespace NAEngine { /// <summary> /// Summary description for Form1. /// </summary> public class frmMain : System.Windows.Forms.Form { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; private System.Windows.Forms.Splitter splitter1; // Context menu objects for NAWindow's context menu private System.Windows.Forms.ContextMenu contextMenu1; private System.Windows.Forms.MenuItem miLoadLocations; private System.Windows.Forms.MenuItem miClearLocations; private System.Windows.Forms.MenuItem miAddItem; // ArcGIS Controls on the form private ESRI.ArcGIS.Controls.AxMapControl axMapControl1; private ESRI.ArcGIS.Controls.AxLicenseControl axLicenseControl1; private ESRI.ArcGIS.Controls.AxToolbarControl axToolbarControl1; private ESRI.ArcGIS.Controls.AxTOCControl axTOCControl1; // Listen for context menu on NAWindow private IEngineNAWindowEventsEx_OnContextMenuEventHandler m_onContextMenu; // Reference to Network Analyst Environment private IEngineNetworkAnalystEnvironment m_naEnv; // Reference to NAWindow. Need to hold on to reference for events to work. private IEngineNAWindow m_naWindow; // Menu for our commands on the TOC context menu private IToolbarMenu m_menuLayer; // incrementor for auto generated names private static int autogenInt = 0; public frmMain() { // // Required for Windows Form Designer support // InitializeComponent(); } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose(bool disposing) { ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown(); if (disposing) { if (components != null) { components.Dispose(); } } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); this.axMapControl1 = new ESRI.ArcGIS.Controls.AxMapControl(); this.axLicenseControl1 = new ESRI.ArcGIS.Controls.AxLicenseControl(); this.axToolbarControl1 = new ESRI.ArcGIS.Controls.AxToolbarControl(); this.splitter1 = new System.Windows.Forms.Splitter(); this.axTOCControl1 = new ESRI.ArcGIS.Controls.AxTOCControl(); this.contextMenu1 = new System.Windows.Forms.ContextMenu(); this.miLoadLocations = new System.Windows.Forms.MenuItem(); this.miClearLocations = new System.Windows.Forms.MenuItem(); this.miAddItem = new System.Windows.Forms.MenuItem(); ((System.ComponentModel.ISupportInitialize)(this.axMapControl1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.axLicenseControl1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.axToolbarControl1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.axTOCControl1)).BeginInit(); this.SuspendLayout(); // // axMapControl1 // this.axMapControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.axMapControl1.Location = new System.Drawing.Point(227, 28); this.axMapControl1.Name = "axMapControl1"; this.axMapControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axMapControl1.OcxState"))); this.axMapControl1.Size = new System.Drawing.Size(645, 472); this.axMapControl1.TabIndex = 2; // // axLicenseControl1 // this.axLicenseControl1.Enabled = true; this.axLicenseControl1.Location = new System.Drawing.Point(664, 0); this.axLicenseControl1.Name = "axLicenseControl1"; this.axLicenseControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axLicenseControl1.OcxState"))); this.axLicenseControl1.Size = new System.Drawing.Size(32, 32); this.axLicenseControl1.TabIndex = 1; // // axToolbarControl1 // this.axToolbarControl1.Dock = System.Windows.Forms.DockStyle.Top; this.axToolbarControl1.Location = new System.Drawing.Point(0, 0); this.axToolbarControl1.Name = "axToolbarControl1"; this.axToolbarControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axToolbarControl1.OcxState"))); this.axToolbarControl1.Size = new System.Drawing.Size(872, 28); this.axToolbarControl1.TabIndex = 0; // // splitter1 // this.splitter1.Location = new System.Drawing.Point(224, 28); this.splitter1.Name = "splitter1"; this.splitter1.Size = new System.Drawing.Size(3, 472); this.splitter1.TabIndex = 4; this.splitter1.TabStop = false; // // axTOCControl1 // this.axTOCControl1.Dock = System.Windows.Forms.DockStyle.Left; this.axTOCControl1.Location = new System.Drawing.Point(0, 28); this.axTOCControl1.Name = "axTOCControl1"; this.axTOCControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axTOCControl1.OcxState"))); this.axTOCControl1.Size = new System.Drawing.Size(224, 472); this.axTOCControl1.TabIndex = 1; this.axTOCControl1.OnMouseDown += new ESRI.ArcGIS.Controls.ITOCControlEvents_Ax_OnMouseDownEventHandler(this.axTOCControl1_OnMouseDown); // // contextMenu1 // this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.miLoadLocations, this.miClearLocations}); // // miLoadLocations // this.miLoadLocations.Index = 0; this.miLoadLocations.Text = "Load Locations..."; this.miLoadLocations.Click += new System.EventHandler(this.miLoadLocations_Click); // // miClearLocations // this.miClearLocations.Index = 1; this.miClearLocations.Text = "Clear Locations"; this.miClearLocations.Click += new System.EventHandler(this.miClearLocations_Click); // // miAddItem // this.miAddItem.Index = -1; this.miAddItem.Text = "Add Item"; this.miAddItem.Click += new System.EventHandler(this.miAddItem_Click); // // frmMain // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(872, 500); this.Controls.Add(this.axLicenseControl1); this.Controls.Add(this.axMapControl1); this.Controls.Add(this.splitter1); this.Controls.Add(this.axTOCControl1); this.Controls.Add(this.axToolbarControl1); this.Name = "frmMain"; this.Text = "Network Analyst Engine Application"; this.Load += new System.EventHandler(this.frmMain_Load); ((System.ComponentModel.ISupportInitialize)(this.axMapControl1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.axLicenseControl1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.axToolbarControl1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.axTOCControl1)).EndInit(); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { if (!ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine)) { if (!ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop)) { if (ESRI.ArcGIS.RuntimeManager.ActiveRuntime.Version == "") // "" is less than 10 { System.Windows.Forms.MessageBox.Show("Loading ArcGIS Version Failed"); return; } } } Application.Run(new frmMain()); } private void frmMain_Load(object sender, System.EventArgs e) { // Add commands to the NALayer context menu m_menuLayer = new ToolbarMenuClass(); int nItem = -1; m_menuLayer.AddItem(new cmdLoadLocations(), -1, ++nItem, false, esriCommandStyles.esriCommandStyleTextOnly); m_menuLayer.AddItem(new cmdRemoveLayer(), -1, ++nItem, false, esriCommandStyles.esriCommandStyleTextOnly); m_menuLayer.AddItem(new cmdClearAnalysisLayer(), -1, ++nItem, true, esriCommandStyles.esriCommandStyleTextOnly); m_menuLayer.AddItem(new cmdNALayerProperties(), -1, ++nItem, true, esriCommandStyles.esriCommandStyleTextOnly); m_menuLayer.SetHook(axMapControl1); // Add command for Network Analyst env properties to end of "Network Analyst" dropdown menu nItem = -1; for (int i = 0; i < axToolbarControl1.Count; ++i) { IToolbarItem item = axToolbarControl1.GetItem(i); IToolbarMenu mnu = item.Menu; if (mnu == null) continue; IMenuDef mnudef = mnu.GetMenuDef(); string name = mnudef.Name; if (name == "ControlToolsNetworkAnalyst_SolverMenu") { nItem = i; break; } } if (nItem >= 0) { IToolbarItem item = axToolbarControl1.GetItem(nItem); IToolbarMenu mnu = item.Menu; if (mnu != null) mnu.AddItem(new cmdNAProperties(), -1, mnu.Count, true, esriCommandStyles.esriCommandStyleTextOnly); } // Initialize naEnv variables m_naEnv = new EngineNetworkAnalystEnvironmentClass(); m_naEnv.ZoomToResultAfterSolve = false; m_naEnv.ShowAnalysisMessagesAfterSolve = (int)(esriEngineNAMessageType.esriEngineNAMessageTypeInformative | esriEngineNAMessageType.esriEngineNAMessageTypeWarning); // Explicitly setup buddy control and initialize NA extension // so we can get to NAWindow to listen to window events // This is necessary the various controls are not yet setup and they // need to be in order to get the NAWindow's events. axToolbarControl1.SetBuddyControl(axMapControl1); IExtension ext = m_naEnv as IExtension; object obj = axToolbarControl1.Object; ext.Startup(ref obj); m_naWindow = m_naEnv.NAWindow; m_onContextMenu = new IEngineNAWindowEventsEx_OnContextMenuEventHandler(OnContextMenu); ((IEngineNAWindowEventsEx_Event)m_naWindow).OnContextMenu += m_onContextMenu; } // Show the TOC context menu when an NALayer is right-clicked on private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e) { if (e.button != 2) return; esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone; IBasicMap map = null; ILayer layer = null; object other = null; object index = null; //Determine what kind of item has been clicked on axTOCControl1.HitTest(e.x, e.y, ref item, ref map, ref layer, ref other, ref index); // Only implemented a context menu for NALayers. Exit if the layer is anything else. if ((layer as INALayer) == null) return; axTOCControl1.SelectItem(layer); // Set the layer into the CustomProperty. // This is used by the other commands to know what layer was right-clicked on // in the table of contents. axMapControl1.CustomProperty = layer; //Popup the correct context menu and update the TOC when it's done. if (item == esriTOCControlItem.esriTOCControlItemLayer) { m_menuLayer.PopupMenu(e.x, e.y, axTOCControl1.hWnd); ITOCControl toc = axTOCControl1.Object as ITOCControl; toc.Update(); } } public bool OnContextMenu(int x, int y) { System.Drawing.Point pt = this.PointToClient(System.Windows.Forms.Cursor.Position); //Get the active category IEngineNAWindowCategory2 activeCategory = m_naWindow.ActiveCategory as IEngineNAWindowCategory2; if (activeCategory == null) return false; MenuItem separator = new MenuItem("-"); miLoadLocations.Enabled = false; miClearLocations.Enabled = false; // in order for the AddItem choice to appear in the context menu, the class // should be an input class, and it should not be editable INAClassDefinition pNAClassDefinition = activeCategory.NAClass.ClassDefinition; if (pNAClassDefinition.IsInput) { miLoadLocations.Enabled = true; miClearLocations.Enabled = true; // canEditShape should be false for AddItem to Apply (default is false) // if it's a StandaloneTable canEditShape is implicitly false (there's no shape to edit) bool canEditShape = false; IFields pFields = pNAClassDefinition.Fields; int nField = -1; nField = pFields.FindField("Shape"); if (nField >= 0) { int naFieldType = 0; naFieldType = pNAClassDefinition.get_FieldType("Shape"); // determining whether or not the shape field can be edited consists of running a bitwise comparison // on the FieldType of the shape field. See the online help for a list of the possible field types. // For our case, we want to verify that the shape field is an input field. If it is an input field, // then we do NOT want to display the Add Item menu option. canEditShape = ((naFieldType & (int)esriNAFieldType.esriNAFieldTypeInput) == (int)esriNAFieldType.esriNAFieldTypeInput) ? true : false; } if (!canEditShape) { contextMenu1.MenuItems.Add(separator); contextMenu1.MenuItems.Add(miAddItem); } } contextMenu1.Show(this, pt); // even if the miAddItem menu item has not been added, Remove() won't crash. contextMenu1.MenuItems.Remove(separator); contextMenu1.MenuItems.Remove(miAddItem); return true; } private void miLoadLocations_Click(object sender, System.EventArgs e) { IMapControl3 mapControl = (IMapControl3)axMapControl1.Object; // Show the Property Page form for Network Analyst frmLoadLocations loadLocations = new frmLoadLocations(); if (loadLocations.ShowModal(mapControl, m_naEnv)) { // notify that the context has changed because we have added locations to a NAClass within it INAContextEdit contextEdit = m_naEnv.NAWindow.ActiveAnalysis.Context as INAContextEdit; contextEdit.ContextChanged(); // If loaded locations, refresh the NAWindow and the Screen INALayer naLayer = m_naWindow.ActiveAnalysis; mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent); m_naWindow.UpdateContent(m_naWindow.ActiveCategory); } } private void miClearLocations_Click(object sender, System.EventArgs e) { IMapControl3 mapControl = (IMapControl3)axMapControl1.Object; IEngineNetworkAnalystHelper naHelper = m_naEnv as IEngineNetworkAnalystHelper; IEngineNAWindow naWindow = m_naWindow; INALayer naLayer = naWindow.ActiveAnalysis; // we do not have to run ContextChanged() as with adding an item and loading locations, // because that is done by the DeleteAllNetworkLocations method. naHelper.DeleteAllNetworkLocations(); mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent); } private void miAddItem_Click(object sender, System.EventArgs e) { // Developers Note: // Once an item has been added, the user can double click on the item to edit the properties // of the item. For the purposes of this sample, only the default values from the InitDefaultValues method // and an auto generated Name value are populated initially for the new item. IMapControl3 mapControl = (IMapControl3)axMapControl1.Object; IEngineNAWindowCategory2 activeCategory = m_naWindow.ActiveCategory as IEngineNAWindowCategory2; IDataLayer pDataLayer = activeCategory.DataLayer; // In order to add an item, we need to create a new row in the class and populate it // with the initial default values for that class. ITable table = pDataLayer as ITable; IRow row = table.CreateRow(); IRowSubtypes rowSubtypes = row as IRowSubtypes; rowSubtypes.InitDefaultValues(); // we need to auto generate a display name for the newly added item. // In some cases (depending on how the schema is set up) InitDefaultValues may result in a nonempty name string // in these cases do not override the preexisting non-empty name string with our auto generated one. IFeatureLayer ipFeatureLayer = activeCategory.Layer as IFeatureLayer; IStandaloneTable ipStandaloneTable = pDataLayer as IStandaloneTable; string name = ""; if (ipFeatureLayer != null) name = ipFeatureLayer.DisplayField; else if (ipStandaloneTable != null) name = ipStandaloneTable.DisplayField; //If the display field is an empty string or does not represent an actual field on the NAClass just skip the auto generation. // (Some custom solvers may not have set the DisplayField for example). // Note: The name we are auto generating does not have any spaces in it. This is to ensure that any classes // that are space sensitive will be able to handle the name (ex Specialties). string currentName = ""; int fieldIndex = row.Fields.FindField(name); if (fieldIndex >= 0) { currentName = row.get_Value(fieldIndex) as string; if (currentName.Length <= 0) row.set_Value(fieldIndex, "Item" + ++autogenInt); } // A special case is OrderPairs NAClass because that effectively has a combined 2 field display field. // You will have to hard code to look for that NAClassName and create a default name for // both first order and second order field names so the name will display correctly // (look for the NAClass Name and NOT the layer name). INAClassDefinition naClassDef = activeCategory.NAClass.ClassDefinition; if (naClassDef.Name == "OrderPairs") { fieldIndex = row.Fields.FindField("SecondOrderName"); if (fieldIndex >= 0) { string secondName = row.get_Value(fieldIndex) as string; if (secondName.Length <= 0) row.set_Value(fieldIndex, "Item" + ++autogenInt); } } row.Store(); // notify that the context has changed because we have added an item to a NAClass within it INAContextEdit contextEdit = m_naEnv.NAWindow.ActiveAnalysis.Context as INAContextEdit; contextEdit.ContextChanged(); // refresh the NAWindow and the Screen INALayer naLayer = m_naWindow.ActiveAnalysis; mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent); m_naWindow.UpdateContent(m_naWindow.ActiveCategory); } } }
[Visual Basic .NET]
frmMain.vb
Imports Microsoft.VisualBasic Imports System Imports System.Drawing Imports System.Collections Imports System.ComponentModel Imports System.Windows.Forms Imports System.Data Imports ESRI.ArcGIS.Carto Imports ESRI.ArcGIS.Controls Imports ESRI.ArcGIS.esriSystem Imports ESRI.ArcGIS.SystemUI Imports ESRI.ArcGIS.NetworkAnalyst Imports ESRI.ArcGIS.Geodatabase ' This is the main form of the application. Namespace NAEngine ''' <summary> ''' Summary description for Form1. ''' </summary> Public Class frmMain : Inherits System.Windows.Forms.Form ''' <summary> ''' Required designer variable. ''' </summary> Private components As System.ComponentModel.Container = Nothing Private splitter1 As System.Windows.Forms.Splitter ' Context menu objects for NAWindow's context menu Private contextMenu1 As System.Windows.Forms.ContextMenu Private WithEvents miLoadLocations As System.Windows.Forms.MenuItem Private WithEvents miClearLocations As System.Windows.Forms.MenuItem Private WithEvents miAddItem As System.Windows.Forms.MenuItem ' ArcGIS Controls on the form Private axMapControl1 As ESRI.ArcGIS.Controls.AxMapControl Private axLicenseControl1 As ESRI.ArcGIS.Controls.AxLicenseControl Private axToolbarControl1 As ESRI.ArcGIS.Controls.AxToolbarControl Private WithEvents axTOCControl1 As ESRI.ArcGIS.Controls.AxTOCControl ' Listen for context menu on NAWindow Private m_onContextMenu As IEngineNAWindowEventsEx_OnContextMenuEventHandler ' Reference to Network Analyst Environment Private m_naEnv As IEngineNetworkAnalystEnvironment ' Reference to NAWindow. Need to hold on to reference for events to work. Private m_naWindow As IEngineNAWindow ' Menu for our commands on the TOC context menu Private m_menuLayer As IToolbarMenu ' integer to use for auto generated names Private autogenInt As Integer Public Sub New() ' ' Required for Windows Form Designer support ' InitializeComponent() End Sub ''' <summary> ''' Clean up any resources being used. ''' </summary> Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) 'Release COM objects ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown() If disposing Then If Not components Is Nothing Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub #Region "Windows Form Designer generated code" ''' <summary> ''' Required method for Designer support - do not modify ''' the contents of this method with the code editor. ''' </summary> Private Sub InitializeComponent() Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(frmMain)) Me.axMapControl1 = New ESRI.ArcGIS.Controls.AxMapControl Me.axLicenseControl1 = New ESRI.ArcGIS.Controls.AxLicenseControl Me.axToolbarControl1 = New ESRI.ArcGIS.Controls.AxToolbarControl Me.splitter1 = New System.Windows.Forms.Splitter Me.axTOCControl1 = New ESRI.ArcGIS.Controls.AxTOCControl Me.contextMenu1 = New System.Windows.Forms.ContextMenu Me.miLoadLocations = New System.Windows.Forms.MenuItem Me.miClearLocations = New System.Windows.Forms.MenuItem Me.miAddItem = New System.Windows.Forms.MenuItem CType(Me.axMapControl1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.axLicenseControl1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.axToolbarControl1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.axTOCControl1, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() ' 'axMapControl1 ' Me.axMapControl1.Dock = System.Windows.Forms.DockStyle.Fill Me.axMapControl1.Location = New System.Drawing.Point(227, 28) Me.axMapControl1.Name = "axMapControl1" Me.axMapControl1.OcxState = CType(resources.GetObject("axMapControl1.OcxState"), System.Windows.Forms.AxHost.State) Me.axMapControl1.Size = New System.Drawing.Size(645, 472) Me.axMapControl1.TabIndex = 2 ' 'axLicenseControl1 ' Me.axLicenseControl1.Enabled = True Me.axLicenseControl1.Location = New System.Drawing.Point(664, 0) Me.axLicenseControl1.Name = "axLicenseControl1" Me.axLicenseControl1.OcxState = CType(resources.GetObject("axLicenseControl1.OcxState"), System.Windows.Forms.AxHost.State) Me.axLicenseControl1.Size = New System.Drawing.Size(32, 32) Me.axLicenseControl1.TabIndex = 1 ' 'axToolbarControl1 ' Me.axToolbarControl1.Dock = System.Windows.Forms.DockStyle.Top Me.axToolbarControl1.Location = New System.Drawing.Point(0, 0) Me.axToolbarControl1.Name = "axToolbarControl1" Me.axToolbarControl1.OcxState = CType(resources.GetObject("axToolbarControl1.OcxState"), System.Windows.Forms.AxHost.State) Me.axToolbarControl1.Size = New System.Drawing.Size(872, 28) Me.axToolbarControl1.TabIndex = 0 ' 'splitter1 ' Me.splitter1.Location = New System.Drawing.Point(224, 28) Me.splitter1.Name = "splitter1" Me.splitter1.Size = New System.Drawing.Size(3, 472) Me.splitter1.TabIndex = 4 Me.splitter1.TabStop = False ' 'axTOCControl1 ' Me.axTOCControl1.Dock = System.Windows.Forms.DockStyle.Left Me.axTOCControl1.Location = New System.Drawing.Point(0, 28) Me.axTOCControl1.Name = "axTOCControl1" Me.axTOCControl1.OcxState = CType(resources.GetObject("axTOCControl1.OcxState"), System.Windows.Forms.AxHost.State) Me.axTOCControl1.Size = New System.Drawing.Size(224, 472) Me.axTOCControl1.TabIndex = 1 ' 'contextMenu1 ' Me.contextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.miLoadLocations, Me.miClearLocations}) ' 'miLoadLocations ' Me.miLoadLocations.Index = 0 Me.miLoadLocations.Text = "Load Locations..." ' 'miClearLocations ' Me.miClearLocations.Index = 1 Me.miClearLocations.Text = "Clear Locations" ' 'miAddItem ' Me.miAddItem.Index = -1 Me.miAddItem.Text = "Add Item" ' 'frmMain ' Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(872, 500) Me.Controls.Add(Me.axLicenseControl1) Me.Controls.Add(Me.axMapControl1) Me.Controls.Add(Me.splitter1) Me.Controls.Add(Me.axTOCControl1) Me.Controls.Add(Me.axToolbarControl1) Me.Name = "frmMain" Me.Text = "Network Analyst Engine Application" CType(Me.axMapControl1, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.axLicenseControl1, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.axToolbarControl1, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.axTOCControl1, System.ComponentModel.ISupportInitialize).EndInit() Me.ResumeLayout(False) End Sub #End Region ''' <summary> ''' The main entry point for the application. ''' </summary> <STAThread()> _ Shared Sub Main() If (ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine) Or _ ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop)) Then Application.Run(New frmMain()) Else If (ESRI.ArcGIS.RuntimeManager.ActiveRuntime.Version = "") Then ' "" is less than 10 System.Windows.Forms.MessageBox.Show("Loading ArcGIS Version Failed") End If End If End Sub Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Add commands to the NALayer context menu m_menuLayer = New ToolbarMenuClass() Dim nItem As Integer = -1 m_menuLayer.AddItem(New LoadLocations(), -1, ++nItem, False, esriCommandStyles.esriCommandStyleTextOnly) m_menuLayer.AddItem(New RemoveLayer(), -1, ++nItem, False, esriCommandStyles.esriCommandStyleTextOnly) m_menuLayer.AddItem(New ClearAnalysisLayer(), -1, ++nItem, True, esriCommandStyles.esriCommandStyleTextOnly) m_menuLayer.AddItem(New NALayerProperties(), -1, ++nItem, True, esriCommandStyles.esriCommandStyleTextOnly) m_menuLayer.SetHook(axMapControl1) For i As Integer = 0 To axToolbarControl1.Count - 1 Dim item As IToolbarItem = axToolbarControl1.GetItem(i) Dim mnu As IToolbarMenu = item.Menu If mnu Is Nothing Then Continue For End If Dim mnudef As IMenuDef = mnu.GetMenuDef() Dim name As String = mnudef.Name If name = "ControlToolsNetworkAnalyst_SolverMenu" Then nItem = i Exit For End If Next If nItem >= 0 Then Dim item As IToolbarItem = axToolbarControl1.GetItem(nItem) Dim mnu As IToolbarMenu = item.Menu If mnu IsNot Nothing Then mnu.AddItem(New NAProperties(), -1, mnu.Count, True, esriCommandStyles.esriCommandStyleTextOnly) End If End If ' Initialize naEnv variables m_naEnv = New EngineNetworkAnalystEnvironmentClass() m_naEnv.ZoomToResultAfterSolve = False m_naEnv.ShowAnalysisMessagesAfterSolve = CInt(esriEngineNAMessageType.esriEngineNAMessageTypeInformative Or esriEngineNAMessageType.esriEngineNAMessageTypeWarning) ' Explicitly setup buddy control and initialize NA extension ' so we can get to NAWindow to listen to window events ' This is necessary the various controls are not yet setup and they ' need to be in order to get the NAWindow's events. axToolbarControl1.SetBuddyControl(axMapControl1) Dim ext As IExtension = TryCast(m_naEnv, IExtension) Dim obj As Object = axToolbarControl1.Object ext.Startup(obj) m_naWindow = m_naEnv.NAWindow m_onContextMenu = New IEngineNAWindowEventsEx_OnContextMenuEventHandler(AddressOf OnContextMenu) AddHandler CType(m_naWindow, IEngineNAWindowEventsEx_Event).OnContextMenu, m_onContextMenu End Sub ' Show the TOC context menu when an NALayer is right-clicked on Private Sub axTOCControl1_OnMouseDown(ByVal sender As Object, ByVal e As ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent) Handles axTOCControl1.OnMouseDown If e.button <> 2 Then Return End If Dim item As esriTOCControlItem = esriTOCControlItem.esriTOCControlItemNone Dim map As IBasicMap = Nothing Dim layer As ILayer = Nothing Dim other As Object = Nothing Dim index As Object = Nothing 'Determine what kind of item has been clicked on axTOCControl1.HitTest(e.x, e.y, item, map, layer, other, index) ' Only implemented a context menu for NALayers. Exit if the layer is anything else. If (TryCast(layer, INALayer)) Is Nothing Then Return End If axTOCControl1.SelectItem(layer) ' Set the layer into the CustomProperty. ' This is used by the other commands to know what layer was right-clicked on ' in the table of contents. axMapControl1.CustomProperty = layer 'Popup the correct context menu and update the TOC when it's done. If item = esriTOCControlItem.esriTOCControlItemLayer Then m_menuLayer.PopupMenu(e.x,e.y,axTOCControl1.hWnd) Dim toc As ITOCControl = TryCast(axTOCControl1.Object, ITOCControl) toc.Update() End If End Sub Public Function OnContextMenu(ByVal x As Integer, ByVal y As Integer) As Boolean Dim pt As System.Drawing.Point = Me.PointToClient(System.Windows.Forms.Cursor.Position) ' Get the active category Dim activeCategory As IEngineNAWindowCategory2 = TryCast(m_naWindow.ActiveCategory, IEngineNAWindowCategory2) If (activeCategory Is Nothing) Then Return False End If Dim separator As MenuItem = New MenuItem("-") miLoadLocations.Enabled = False miClearLocations.Enabled = False ' in order for the AddItem choice to appear in the context menu, the class ' should be an input class, and it should not be editable Dim pNAClassDefinition As INAClassDefinition = activeCategory.NAClass.ClassDefinition If (pNAClassDefinition.IsInput) Then miLoadLocations.Enabled = True miClearLocations.Enabled = True ' canEditShape should be false for AddItem to Apply (default is false) ' if it's a StandaloneTable canEditShape is implicitly false (there's no shape to edit) Dim canEditShape As Boolean = False Dim pFields As IFields = pNAClassDefinition.Fields Dim nfield As Integer = -1 nfield = pFields.FindField("Shape") If (nfield >= 0) Then Dim naFieldtype As Integer = 0 naFieldtype = pNAClassDefinition.FieldType("Shape") ' determining whether or not the shape field can be edited consists of running a bitwise comparison ' on the FieldType of the shape field. See the online help for a list of the possible field types. ' For our case, we want to verify that the shape field is an input field. If it is an input field, ' then we do NOT want to display the Add Item menu option. Dim bitwiseAnd As Integer = (naFieldtype And esriNAFieldType.esriNAFieldTypeInput) If (bitwiseAnd = esriNAFieldType.esriNAFieldTypeInput) Then canEditShape = True End If End If If (Not canEditShape) Then contextMenu1.MenuItems.Add(separator) contextMenu1.MenuItems.Add(miAddItem) End If End If contextMenu1.Show(Me, pt) ' even if the miAddItem menu item has not been added, Remove() won't crash. contextMenu1.MenuItems.Remove(separator) contextMenu1.MenuItems.Remove(miAddItem) Return True End Function Private Sub miLoadLocations_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles miLoadLocations.Click Dim mapControl As IMapControl3 = CType(axMapControl1.Object, IMapControl3) ' Show the Property Page form for Network Analyst Dim dlgLoadLocations As frmLoadLocations = New frmLoadLocations() If dlgLoadLocations.ShowModal(mapControl, m_naEnv) Then ' If loaded locations, refresh the NAWindow and the Screen Dim naLayer As INALayer = m_naWindow.ActiveAnalysis ' notify that the context has changed because we have added locations to a NAClass within it Dim contextEdit As INAContextEdit = TryCast(m_naEnv.NAWindow.ActiveAnalysis.Context, INAContextEdit) contextEdit.ContextChanged() mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent) m_naWindow.UpdateContent(m_naWindow.ActiveCategory) End If End Sub Private Sub miClearLocations_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles miClearLocations.Click Dim mapControl As IMapControl3 = CType(axMapControl1.Object, IMapControl3) Dim naHelper As IEngineNetworkAnalystHelper = TryCast(m_naEnv, IEngineNetworkAnalystHelper) Dim naWindow As IEngineNAWindow = m_naWindow Dim naLayer As INALayer = naWindow.ActiveAnalysis ' we do not have to run ContextChanged() as with adding an item and loading locations, ' because that is done by the DeleteAllNetworkLocations method. naHelper.DeleteAllNetworkLocations() mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent) End Sub Private Sub miAddItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles miAddItem.Click ' Developers Note: ' Once an item has been added, the user can double click on the item to edit the properties ' of the item. For the purposes of this sample, only the default values from the InitDefaultValues method ' and an auto generated Name value are populated initially for the new item. Dim mapControl As IMapControl3 = CType(axMapControl1.Object, IMapControl3) Dim activeCategory As IEngineNAWindowCategory2 = CType(m_naWindow.ActiveCategory, IEngineNAWindowCategory2) Dim pDataLayer As IDataLayer = activeCategory.DataLayer ' In order to add an item, we need to create a new row in the class and populate it ' with the initial default values for that class. Dim table As ITable = CType(pDataLayer, ITable) Dim row As IRow = table.CreateRow() Dim rowSubtypes As IRowSubtypes = CType(row, IRowSubtypes) rowSubtypes.InitDefaultValues() ' we need to auto generate a display name for the newly added item. ' In some cases (depending on how the schema is set up) InitDefaultValues may result in a nonempty name string ' in these cases do not override the preexisting non-empty name string with our auto generated one. Dim ipFeatureLayer As IFeatureLayer = TryCast(activeCategory.Layer, IFeatureLayer) Dim ipStandaloneTable As IStandaloneTable = TryCast(pDataLayer, IStandaloneTable) Dim name As String = "" If Not ipFeatureLayer Is Nothing Then name = ipFeatureLayer.DisplayField ElseIf Not ipStandaloneTable Is Nothing Then name = ipStandaloneTable.DisplayField End If ' If the display field is an empty string or does not represent an actual field on the NAClass just skip the auto generation. ' (Some custom solvers may not have set the DisplayField for example). ' Note: The name we are auto generating does not have any spaces in it. This is to ensure that that any classes ' that are space sensitive will be able to handle the name (ex Specialties). Dim currentName As String = "" Dim fieldIndex As Integer = row.Fields.FindField(name) If (fieldIndex >= 0) Then currentName = CType(row.Value(fieldIndex), String) If (currentName.Length <= 0) Then autogenInt += 1 row.Value(fieldIndex) = "Item" & autogenInt End If End If ' A special case is OrderPairs NAClass because that effectively has a combined 2 field display field. ' You will have to hard code to look for that NAClassName and create a default name for ' both first order and second order field names so the name will display correctly ' (look for the NAClass Name and NOT the layer name). Dim naClassDef As INAClassDefinition = activeCategory.NAClass.ClassDefinition If (naClassDef.Name = "OrderPairs") Then fieldIndex = row.Fields.FindField("SecondOrderName") If (fieldIndex >= 0) Then Dim secondName As String = CType(row.Value(fieldIndex), String) If (secondName.Length <= 0) Then autogenInt += 1 row.Value(fieldIndex) = "Item" & autogenInt End If End If End If row.Store() ' notify that the context has changed because we have added an item to a NAClass within it Dim contextEdit As INAContextEdit = CType(m_naEnv.NAWindow.ActiveAnalysis.Context, INAContextEdit) contextEdit.ContextChanged() ' refresh the NAWindow and the Screen Dim naLayer As INALayer = m_naWindow.ActiveAnalysis mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent) m_naWindow.UpdateContent(m_naWindow.ActiveCategory) End Sub End Class End Namespace