Вы находитесь на странице: 1из 23

Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Building a map viewing application using the ArcGIS Engine controls

This document was published with ArcGIS 9.3.


A 9.2 version also exists.
Summary
The goal of this walkthrough is to demonstrate and familiarize you with the steps required to develop and deploy a geographic
information system (GIS) application using the standard ArcGIS Engine controls in the Microsoft Visual Studio .NET application
programming interface (API). The scenario uses the LicenseControl, MapControl, PageLayoutControl, TOCControl, ToolbarControl,
SymbologyControl and Control commands in the Microsoft Visual Studio .NET development environment.

Click here to get the sample associated with this walkthrough.

Development licensing Deployment licensing

Engine Developer Kit Engine Runtime


ArcView
ArcEditor
ArcInfo

Additional Requirements

While no experience with other ESRI software is required, previous experience with ArcObjects and a basic understanding of
ArcGIS applications, such as ArcMap and ArcCatalog are recommended.
Access to the sample data and code that comes with this scenario.

In this topic
Project description
Concepts
Design
Implementation
Loading the ArcGIS Engine controls
Embedding the ArcGIS Engine controls in a container
License initialization using the LicenseControl
Loading map documents into MapControl and PageLayoutControl
Setting the ToolbarControl and TOCControl buddy controls
Handling form resize
Adding commands to the ToolbarControl
Creating a pop-up menu for the PageLayoutControl
Creating a palette of tools
Managing label editing in the TOCControl
Drawing shapes on the MapControl
Creating a custom tool
Customizing the ToolbarControl
Saving and loading ToolbarControl items
Printing the page layout
Deployment
Additional resources

Project description
This document demonstrates the steps required to create a GIS application for viewing pre-authored ESRI map documents (*.mxd).

Concepts
This scenario is implemented using the Microsoft Visual Studio .NET development environment and uses the ESRI interop assemblies to host
the ArcGIS Engine controls inside .NET Windows controls in a .NET form. These interoperability assemblies act as a bridge between the
unmanaged code of the Component Object Model (COM) and the managed .NET code. Any references to the members of the COM ArcGIS
Engine controls are routed to the interop assemblies and forwarded to the actual COM object. Likewise, responses from the COM object are
routed to the interop assembly and forwarded to the .NET application. Each ArcGIS Engine control has events, properties, and methods that
can be accessed once embedded within a container, such as a .NET form. The objects and functionality in each control can be combined with
other ESRI ArcObjects and custom controls to create customized end user applications.

The scenario has been written in both C# and Visual Basic .NET. Many developers will feel more comfortable with Visual Basic .NET, as the
code looks familiar to Visual Basic 6.0, while the syntax of the C# programming language will be familiar to Java and C++ programmers.
Whichever development environment you use, your future success with the ArcGIS Engine controls depends on your skill in both the
programming environment and ArcObjects.

The MapControl, PageLayoutControl, TOCControl and ToolbarControl are used in this scenario to provide the user interface of the application,
and the LicenseControl is used to configure the application with an appropriate license. The ArcGIS Engine controls are used in conjunction
with other ArcObjects and control commands by the developer to create a GIS map viewing application.

Design
The scenario has been designed to highlight how the ArcGIS Engine controls interact with each other and to expose a part of each ArcGIS

1 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Engine control's object model to the developer.

Each .NET ArcGIS Engine control has a set of property pages that can be accessed once the control is embedded in a .NET form. These
property pages provide shortcuts to a selection of a control's properties and methods and allow a developer to build an application without
writing any code. This scenario does not use the property pages but rather builds up the application programmatically.

The ArcGIS Engine controls and libraries used in this scenario are as follows:
ESRI.ArcGIS.ADF
ESRI.ArcGIS.AxControls
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Controls
ESRI.ArcGIS.Display
ESRI.ArcGIS.Geometry
ESRI.ArcGIS.Output
ESRI.ArcGIS.System
ESRI.ArcGIS.SystemUI

The ESRI.ArcGIS.AxControls .NET Framework component represents each control that is hosted in a .NET form, while the
ESRI.ArcGIS.Controls assembly contains the object and interfaces from inside each control's type library.

Implementation
The following implementation provides you with all the necessary code to successfully complete the scenario. It does not provide step-by-step
instructions to develop applications in Microsoft Visual Studio .NET, as it assumes that you already have a working knowledge of the
development environment.

Loading the ArcGIS Engine controls


Before you start programming your application, the ArcGIS Engine controls and the other ArcGIS Engine assembly references that the
application will use should be loaded into the development environment.
1. Start Visual Studio .NET and create either a new Visual C# or Visual Basic Windows Application project from the New Project
dialog box.
2. Name the project Controls and browse to a location to save the project.
3. In the Toolbox click ArcGIS Windows Forms to display the ArcGIS Engine controls. If there is no ArcGIS Windows Forms,
right-click the Toolbox and click Choose Items from the context menu.
4. In the Choose Toolbox Items dialog box, click the .NET Framework Components tab and check AxLicenseControl, AxMapControl,
AxPageLayoutControl, AxTOCControl, and AxToolbarControl, then click OK. The controls will now appear in the Toolbox. See the
following screen shot:

5. Click the Project menu and click Add ArcGIS Reference.


6. In the Add ArcGIS Reference dialog box, double-click ESRI.ArcGIS.ADF, ESRI.ArcGIS.Carto, ESRI.ArcGIS.Display,
ESRI.ArcGIS.Geometry, ESRI.ArcGIS.Output, ESRI.ArcGIS.System, and ESRI.ArcGIS.SystemUI to select them, then click Finish.
See the following screen shot:

2 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

The ESRI .NET assemblies will be used to instantiate and make calls on the objects in the ESRI object libraries from your C# or
VB.NET project using the COM interoperability services provided by the .NET Framework.

Embedding the ArcGIS Engine controls in a container


Before you can access each control's properties, methods, and events, each control needs embedding in a .NET container. Once the controls
are embedded in the form, they will shape the application's user interface.
1. Rename the .NET form from Form1 to MapViewer.
2. Open the .NET form in design mode.
3. Double-click MenuStrip under Menus & Toolbars in the Toolbox.
4. Double-click LicenseControl under ArcGIS Windows Forms in the Toolbox to add a LicenseControl onto the form.
5. Repeat to add the MapControl, PageLayoutControl, TOCControl, and ToolbarControl.
6. Resize and reposition each control on the form as shown in the following screen shot:

7. Double-click the form to display the form's code window. Add using directives or import statements in the following code
example to the top of the code window:

In .NET a variable is fully-qualified using a namespace. Namespaces are a concept in .NET that allow objects to be organized
hierarchically, regardless of the assembly they are defined in. To make code simpler and more readable, the directives act as
shortcuts when referencing items specified in namespaces.

If you start by typing ESRI., the autocompletion feature of IntelliSense allows you to complete the next section of code by

3 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

pressing the Tab key.

Remember that C# is case sensitive. By default, when the project is created, C# will add some using directives to some of the
system namespaces.

[C#]

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.esriSystem;

[VB.NET]

Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Controls
Imports ESRI.ArcGIS.Display
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.esriSystem

License initialization using the LicenseControl


To successfully deploy this application on another machine, the application must configure a license. First, it must check that a product license
is available and second, it must initialize the product license. If this license configuration fails, the application cannot run. License
configuration can be performed either by using the LicenseControl or by programmatically using the AoInitialize object. For the purpose of this
application, the LicenseControl will be used to handle license configuration.

When developing a stand-alone executable using ArcObjects, it is the responsibility of the application to check and configure the
licensing options. A license can be configured using either the LicenseControl or the AoInitialize class and the IAoInitialize
interface it implements, that is designed to support license configuration. License initialization must be performed at application
start time, before any ArcObjects functionality is accessed. Failure to do so will result in application errors.

1. Open the .NET form in design mode.


2. Right-click the LicenseControl and click ActiveX-Properties to open the LicenseControl property pages.
3. Under Products, select the ArcGIS Engine check box and select Shutdown this application if the selected licenses are not available
check box, then click OK. See the following screen shot:

The LicenseControl will appear on a form at design time so that it can be selected and its property pages viewed. However, at
run time the LicenseControl is invisible so its position on the form is irrelevant.

This application can be initialized with an ArcGIS Engine license but you may optionally initialize the application with a higher
product license. For example, if you select the ArcGIS Engine license and the ArcView license check boxes, the LicenseControl
will initially try to initialize the application with an ArcGIS Engine license (the lower license). If that license is not available, the
LicenseControl will try to initialize the application with an ArcView license (the next higher level license selected). If no product
licenses are available, then the application will fail to initialize.

In this application the LicenseControl will handle license initialization failure. If the application cannot be initialized with an
ArcGIS Engine product license, a License Failure dialog box appears before the application is automatically shut down.
Alternatively, a developer can handle license initialization failure using the ILicenseControl interface members to obtain
information on the nature of the failure before the application is programmatically shut down.

Loading map documents into the PageLayoutControl and MapControl


Individual data layers or pre-authored map documents can be loaded into the MapControl and PageLayoutControl. You can either load the
sample map document that is provided or you can load your own map document. Later, you will add a command to browse to a map
document.
1. Select the Form_Load event and enter the code in the following code example (you may need to alter the relative path to the map
document or substitute the file name if you are using your own map document):

[C#]

private void MapViewer_Load(object sender, System.EventArgs e)


{
//Load a pre-authored map document into the PageLayoutControl using relative paths.
string fileName = @
"..\..\..\..\data\GulfOfStLawrence\Gulf_of_St._Lawrence.mxd";

4 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

if (axPageLayoutControl1.CheckMxFile(fileName))
axPageLayoutControl1.LoadMxFile(fileName, "");
}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Load a pre-authored map document into the PageLayoutControl using realative paths.
Dim sFileName As String = "..\..\..\..\data\GulfOfStLawrence\Gulf_of_St._Lawrence.mxd"
If AxPageLayoutControl1.CheckMxFile(sFileName) Then
AxPageLayoutControl1.LoadMxFile(sFileName)
End If
End Sub

2. Display the form in design mode and select axPageLayoutControl1 from the Properties window and display the PageLayoutControl
events. Double-click the OnPageLayoutReplaced event to add an event handler to the code window. See the following screen shot:

3. In the PageLayoutControl_OnPageLayoutReplaced event, enter the following code to load the same map document into the
MapControl. The OnPageLayoutReplaced event will be triggered whenever a document is loaded into the PageLayoutControl.

[C#]

private void axPageLayoutControl1_OnPageLayoutReplaced(object sender,


IPageLayoutControlEvents_OnPageLayoutReplacedEvent e)
{
//Load the same pre-authored map document into the MapControl.
axMapControl1.LoadMxFile(axPageLayoutControl1.DocumentFilename, null, null);
//Set the extent of the MapControl to the full extent of the data.
axMapControl1.Extent = axMapControl1.FullExtent;
}

[VB.NET]

Private Sub AxPageLayoutControl1_OnPageLayoutReplaced(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.IPageLayoutControlEve


'Load the same pre-authored map document into the MapControl.
AxMapControl1.LoadMxFile(AxPageLayoutControl1.DocumentFilename)
'Set the extent of the MapControl to the full extent of the data.
AxMapControl1.Extent = AxMapControl1.FullExtent
End Sub

Setting the TOCControl and ToolbarControl buddy controls


For the purpose of this application, the TOCControl and ToolbarControl will work in conjunction with the PageLayoutControl, rather than the
MapControl. To do this, the PageLayoutControl must be set as the buddy control. The TOCControl uses the buddy control's ActiveView to
populate itself with maps, layers, and symbols, while any command, tool, menu or palette items present on the ToolbarControl will interact
with the buddy control's display.
1. In the Form_Load event, type the following code before the load document code:

[C#]

private void MapViewer_Load(object sender, System.EventArgs e)


{
//Set buddy controls.
axTOCControl1.SetBuddyControl(axPageLayoutControl1);
axToolbarControl1.SetBuddyControl(axPageLayoutControl1);

//Load a pre-authored map document into the PageLayoutControl using relative paths.
}

[VB.NET]

5 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Set buddy controls.
AxTOCControl1.SetBuddyControl(AxPageLayoutControl1)
AxToolbarControl1.SetBuddyControl(AxPageLayoutControl1)

'Load a pre-authored map document into the PageLayoutControl using realative paths.
End Sub

2. Build and run the application. The map document is loaded into the PageLayoutControl and the TOCControl lists the data layers in
the map document. Use the TOCControl to toggle layer visibility by selecting and deselecting the check boxes. By default, the
focus map of the map document is loaded into the MapControl. At this point, the ToolbarControl is empty because no commands
have been added to it. Try resizing the form and note that the controls do not change size. See the following screen shot:

Handling form resize


When the form is resized at run time, the PageLayoutControl and MapControl do not automatically resize. To resize the controls so that they
always fill the extent of the form, you must anchor the controls to the form. If the PageLayoutControl or MapControl contain a lot of data,
redrawing this data while the form is resized can be costly. To increase performance, you can suppress the data redraw until the resizing is
complete. During the resize a stretched bitmap will be drawn instead.
1. Display the form in design mode and select axPageLayoutControl1 from the Properties window. Click the Anchor property and
anchor the PageLayoutControl to the top, left, bottom, and right of the form. See the following screen shot:

2. Repeat to anchor the MapControl to the top, left, and bottom of the form. See the following screen shot:

3. Display the form in design mode and select the form from the Properties window and display the form events. Double-click
the ResizeBegin event to add an event handler to the code window.
4. In the Form_ResizeBegin event, enter the following code to draw a stretchy bitmap in the PageLayoutControl and MapControl
whenever the form is resized:

[C#]

private void MapViewer_ResizeBegin(object sender, EventArgs e)


{
//Suppress data redraw and draw bitmap instead.
axMapControl1.SuppressResizeDrawing(true, 0);
axPageLayoutControl1.SuppressResizeDrawing(true, 0);
}

[VB.NET]

Private Sub MapViewer_ResizeBegin(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ResizeBegin


'Suppress data redraw and draw bitmap instead.

6 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

AxMapControl1.SuppressResizeDrawing(True, 0)
AxPageLayoutControl1.SuppressResizeDrawing(True, 0)
End Sub

5. Display the form in design mode and select the form from the Properties window and display the form events. Double-click
the ResizeEnd event to add an event handler to the code window.
6. In the Form_ResizeEnd event, enter the following code to stop drawing a stretchy bitmap in the PageLayoutControl and
MapControl:

[C#]

private void MapViewer_ResizeEnd(object sender, EventArgs e)


{
//Stop bitmap draw and draw data.
axMapControl1.SuppressResizeDrawing(false, 0);
axPageLayoutControl1.SuppressResizeDrawing(false, 0);
}

[VB.NET]

Private Sub MapViewer_ResizeEnd(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ResizeEnd


'Stop bitmap draw and draw data.
AxMapControl1.SuppressResizeDrawing(False, 0)
AxPageLayoutControl1.SuppressResizeDrawing(False, 0)
End Sub

7. Build and run the application, then try to resize the form.

Adding commands to the ToolbarControl


ArcGIS Engine comes with more than 230 commands and tools that work directly with the MapControl, PageLayoutControl, and ToolbarControl.
These commands and tools provide you with a lot of frequently used GIS functionality for map navigation, map inquiry, graphics management,
and feature selection. In addition, there are commands and tools to work with the ArcGIS Engine extensions. You will now add some of these
commands and tools to your application to work with the PageLayoutControl.
1. In the Form_Load event add the following code before the set buddy controls code:

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Add generic commands.
axToolbarControl1.AddItem("esriControls.ControlsOpenDocCommand", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsAddDataCommand", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
//Add page layout navigation commands.
axToolbarControl1.AddItem("esriControls.ControlsPageZoomInTool", - 1, - 1,
true, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsPageZoomOutTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsPagePanTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsPageZoomWholePageCommand", -
1, - 1, false, 0, esriCommandStyles.esriCommandStyleIconOnly);
//Add map navigation commands.
axToolbarControl1.AddItem("esriControls.ControlsMapZoomInTool", - 1, - 1,
true, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapZoomOutTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapPanTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapFullExtentCommand", - 1,
- 1, false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZoomToLastExtentBackCommand", - 1, - 1, false, 0,
esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZoomToLastExtentForwardCommand", - 1, - 1, false,
0, esriCommandStyles.esriCommandStyleIconOnly);
//Add map inquiry commands.
axToolbarControl1.AddItem("esriControls.ControlsMapIdentifyTool", - 1, - 1,
true, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapFindCommand", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapMeasureTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);

//Set buddy controls.


}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Add generic commands.
AxToolbarControl1.AddItem("esriControls.ControlsOpenDocCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsAddDataCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
'Add page layout navigation commands.
AxToolbarControl1.AddItem("esriControls.ControlsPageZoomInTool", -1, -1, True, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsPageZoomOutTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsPagePanTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsPageZoomWholePageCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnl
'Add map navigation commands.

7 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

AxToolbarControl1.AddItem("esriControls.ControlsMapZoomInTool", -1, -1, True, 0, esriCommandStyles.esriCommandStyleIconOnly)


AxToolbarControl1.AddItem("esriControls.ControlsMapZoomOutTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapPanTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapFullExtentCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapZoomToLastExtentBackCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleI
AxToolbarControl1.AddItem("esriControls.ControlsMapZoomToLastExtentForwardCommand", -1, -1, False, 0, esriCommandStyles.esriCommandSty
'Add map inquiry commands.
AxToolbarControl1.AddItem("esriControls.ControlsMapIdentifyTool", -1, -1, True, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapFindCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapMeasureTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)

'Set buddy controls.


End Sub

2. Build and run the application. The ToolbarControl now contains ArcGIS Engine commands and tools that you can use to navigate
the map document loaded into the PageLayoutControl. Use the page layout commands to navigate around the actual page layout
and the map commands to navigate around the data present in the data frames. Use the open document command to browse and
load map documents and the add data command to browse and load data layers. See the following screen shot:

Creating a pop-up menu for the PageLayoutControl


In addition to adding ArcGIS Engine commands to the ToolbarControl to work with the buddy control (as in the previous step), you can also
create pop-up menus and palettes from the ArcGIS Engine commands. You will add to your application, a pop-up menu that works with the
PageLayoutControl. The pop-up menu will appear when you right-click the display area of the PageLayoutControl.
1. Add the following member variable to the class:

[C#]

public partial class MapViewer: Form


{
//The pop-up menu.
private IToolbarMenu m_ToolbarMenu;
}

[VB.NET]

Public Class MapViewer


'The pop-up menu.
Private m_pToolbarMenu As IToolbarMenu
End Class

2. Add the following code to the Form_Load event after the code, add the commands to the ToolbarControl but before the set buddy
controls code.

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Add map inquiry commands.

//Create a new ToolbarMenu.


m_ToolbarMenu = new ToolbarMenuClass();
//Share the ToolbarControl's command pool.
m_ToolbarMenu.CommandPool = axToolbarControl1.CommandPool;
//Set the hook to the PageLayoutControl.
m_ToolbarMenu.SetHook(axPageLayoutControl1);
//Add commands to the ToolbarMenu.

8 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

m_ToolbarMenu.AddItem("esriControls.ControlsPageZoomInFixedCommand", - 1, -
1, false, esriCommandStyles.esriCommandStyleIconAndText);
m_ToolbarMenu.AddItem("esriControls.ControlsPageZoomOutFixedCommand", - 1,
- 1, false, esriCommandStyles.esriCommandStyleIconAndText);
m_ToolbarMenu.AddItem("esriControls.ControlsPageZoomWholePageCommand", - 1,
- 1, false, esriCommandStyles.esriCommandStyleIconAndText);
m_ToolbarMenu.AddItem(
"esriControls.ControlsPageZoomPageToLastExtentBackCommand", - 1, - 1,
true, esriCommandStyles.esriCommandStyleIconAndText);
m_ToolbarMenu.AddItem(
"esriControls.ControlsPageZoomPageToLastExtentForwardCommand", - 1, - 1,
false, esriCommandStyles.esriCommandStyleIconAndText);

//Set buddy controls.


}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Add map inquiry commands.

'Create a new ToolbarMenu.


m_pToolbarMenu = New ToolbarMenuClass()
'Share the ToolbarControl's command pool.
m_pToolbarMenu.CommandPool = AxToolbarControl1.CommandPool
'Set the hook to the PageLayoutControl
m_pToolbarMenu.SetHook(AxPageLayoutControl1)
'Add commands to the ToolbarMenu.
m_pToolbarMenu.AddItem("esriControls.ControlsPageZoomInFixedCommand", -1, -1, False, esriCommandStyles.esriCommandStyleIconAndText)
m_pToolbarMenu.AddItem("esriControls.ControlsPageZoomOutFixedCommand", -1, -1, False, esriCommandStyles.esriCommandStyleIconAndText)
m_pToolbarMenu.AddItem("esriControls.ControlsPageZoomWholePageCommand", -1, -1, False, esriCommandStyles.esriCommandStyleIconAndText)
m_pToolbarMenu.AddItem("esriControls.ControlsPageZoomPageToLastExtentBackCommand", -1, -1, True, esriCommandStyles.esriCommandStyleIco
m_pToolbarMenu.AddItem("esriControls.ControlsPageZoomPageToLastExtentForwardCommand", -1, -1, False, esriCommandStyles.esriCommandStyl

'Set buddy controls.


End Sub

3. Display the form in design mode, select axPageLayoutControl1 from the Properties window, and display the PageLayoutControl
events. Double-click the OnMouseDown event to add an event handler to the code window.
4. In the PageLayoutControl_OnMouseDown event, add the following code:

[C#]

private void axPageLayoutControl1_OnMouseDown(object sender,


IPageLayoutControlEvents_OnMouseDownEvent e)
{
//Pop-up the ToolbarMenu.
if (e.button == 2)
m_ToolbarMenu.PopupMenu(e.x, e.y, axPageLayoutControl1.hWnd);
}

[VB.NET]

Private Sub AxPageLayoutControl1_OnMouseDown(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.IPageLayoutControlEvents_OnMou


'Pop-up the ToolbarMenu.
If e.button = 2 Then
m_pToolbarMenu.PopupMenu(e.x, e.y, AxPageLayoutControl1.hWnd)
End If
End Sub

5. Build and run the application. Right-click the PageLayoutControl's display area to show the pop-up menu and navigate around the
page layout. See the following screen shot:

9 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Creating a palette of tools


In addition to creating stand-alone pop-up menus and palettes to work with a control (as in the previous step), menus and palettes can be
added to a ToolbarControl. You will create a palette containing some ArcGIS Engine commands and add it to the ToolbarControl.
1. Add the following code to the Form_Load event before the add commands to the ToolbarMenu code.

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Add map inquiry commands.

//Create a new ToolbarPalette.


IToolbarPalette toolbarPalette = new ToolbarPaletteClass();
//Add commands and tools to the ToolbarPalette.
toolbarPalette.AddItem("esriControls.ControlsNewMarkerTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewLineTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewCircleTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewEllipseTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewRectangleTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewPolygonTool", - 1, - 1);
//Add the ToolbarPalette to the ToolbarControl.
axToolbarControl1.AddItem(toolbarPalette, 0, - 1, false, 0,
esriCommandStyles.esriCommandStyleIconOnly);

//Add commands to the ToolbarMenu.


}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Add map inquiry commands

'Create a new ToolbarPalette.


Dim pToolbarPalette As IToolbarPalette = New ToolbarPaletteClass()
'Add commands and tools to the ToolbarPalette.
pToolbarPalette.AddItem("esriControls.ControlsNewMarkerTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewLineTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewCircleTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewEllipseTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewRectangleTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewPolygonTool", -1, -1)
'Add the ToolbarPalette to the ToolbarControl.
AxToolbarControl1.AddItem(pToolbarPalette, 0, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)

'Add commands to the ToolbarMenu.


End Sub

2. Build and run the application. Use the palette on the ToolbarControl to add graphic elements to the PageLayoutControl's display.
See the following screen shot:

10 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Managing label editing in the TOCControl


By default, the TOCControl allows users to automatically toggle the visibility of layers and to change the map and layer names that appear in
the table of contents. You will add code to prevent users from editing a name and replacing it with an empty string.
1. Add the following code to the beginning of the Form_Load event:

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Set label editing to manual.
axTOCControl1.LabelEdit = esriTOCControlEdit.esriTOCControlManual;
}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Set label editing to manual.
AxTOCControl1.LabelEdit = esriTOCControlEdit.esriTOCControlManual
End Sub

2. Display the form in design mode, select axTOCControl1 from the Properties window, and display the TOCControl events.
Double-click OnEndLabelEdit to add an event handler to the code window.
3. Add the following code to the TOCControl_OnEndLabelEdit event:

[C#]

private void axTOCControl1_OnEndLabelEdit(object sender,


ITOCControlEvents_OnEndLabelEditEvent e)
{
//If the new label is an empty string, prevent the edit.
if (e.newLabel.Trim() == "")
e.canEdit = false;
}

[VB.NET]

Private Sub AxTOCControl1_OnEndLabelEdit(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.ITOCControlEvents_OnEndLabelEditEv


'If the new label is an empty string, prevent the edit.
If e.newLabel.Trim = "" Then e.canEdit = False
End Sub

4. Build and run the application. To edit a map, layer, heading, or legend class label in the TOCControl, click it once, then click it a
second time to invoke label editing. Try replacing the label with an empty string. You can press the Esc key at any time during
the edit to cancel it. See the following screen shot:

11 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Drawing shapes on the MapControl


You will now use the MapControl as an overview window and draw on its display the current extent of the focus map in the PageLayoutControl.
As you navigate around the data in the data frame of the PageLayoutControl, you will see the MapControl overview window update.
1. Add the following member variables to the class below the pop-up menu variable:

[C#]

public partial class MapViewer: Form


{
//The envelope drawn on the MapControl.
private IEnvelope m_Envelope;
//The symbol used to draw the envelope on the MapControl.
private Object m_FillSymbol;
//The PageLayoutControl's focus map events.
private ITransformEvents_Event m_transformEvents;
private ITransformEvents_VisibleBoundsUpdatedEventHandler visBoundsUpdatedE;
}

[VB.NET]

Public Class MapViewer

'The envelope drawn on the MapControl.


Private m_pEnvelope As IEnvelope
'The symbol used to draw the envelope on the MapControl.
Private m_pFillSymbol As ISimpleFillSymbol
'The PageLayoutControl's focus map events.
Private m_pTransformEvents As ITransformEvents_Event
Private visBoundsUpdatedE As ITransformEvents_VisibleBoundsUpdatedEventHandler
End Class

The variable declared as visBoundsUpdatedE is a delegate. A delegate is a class that can hold a reference to a specific method
and link it to a specific event. The linking process between the event and the method is sometimes known in .NET as wiring.

2. Create a new function called CreateOverviewSymbol. This is where you will create the symbol used in the MapControl to represent
the extent of the data in the focus map of the PageLayoutControl. Add the following code to the function:

[C#]

private void CreateOverviewSymbol()


{
//Get the IRGBColor interface.
IRgbColor color = new RgbColorClass();
//Set the color properties.
color.RGB = 255;
//Get the ILine symbol interface.
ILineSymbol outline = new SimpleLineSymbolClass();
//Set the line symbol properties.
outline.Width = 1.5;
outline.Color = color;
//Get the IFillSymbol interface.
ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbolClass();
//Set the fill symbol properties.
simpleFillSymbol.Outline = outline;
simpleFillSymbol.Style = esriSimpleFillStyle.esriSFSHollow;
m_FillSymbol = simpleFillSymbol;

12 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

[VB.NET]

Private Sub CreateOverviewSymbol()


'Get the IRGBColor interface.
Dim pColor As IRgbColor
pColor = New RgbColorClass
'Set the color properties.
pColor.RGB = RGB(255, 0, 0)
'Get the ILine symbol interface.
Dim pOutline As ILineSymbol
pOutline = New SimpleLineSymbolClass
'Set the line symbol properties.
pOutline.Width = 1.5
pOutline.Color = pColor
'Get the ISimpleFillSymbol interface.
m_pFillSymbol = New SimpleFillSymbolClass
'Set the fill symbol properties.
m_pFillSymbol.Outline = pOutline
m_pFillSymbol.Style = esriSimpleFillStyle.esriSFSHollow
End Sub

3. Call the CreateOverviewSymbol function from the beginning of the Form_Load event. See the following code example:

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Create the symbol used on the MapControl.
CreateOverviewSymbol();
}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Create the symbol used on the MapControl.
CreateOverviewSymbol()
End Sub

4. Add the following OnVisibleBoundsUpdated function. This function will be linked to an event raised when the extent of the map is
changed, and is used to set the envelope to the new visible bounds of the map. By refreshing the MapControl, you force it to
redraw the shape on its display.

[C#]

private void OnVisibleBoundsUpdated(IDisplayTransformation sender, bool


sizeChanged)
{
//Set the extent to the new visible extent.
m_Envelope = sender.VisibleBounds;
//Refresh the MapControl's foreground phase.
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewForeground,
null, null);
}

[VB.NET]

Private Sub OnVisibleBoundsUpdated(ByVal sender As IDisplayTransformation, ByVal sizeChanged As Boolean)


'Set the extent to the new visible extent.
m_pEnvelope = sender.VisibleBounds
'Refresh the MapControl's foreground phase.
AxMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewForeground, Nothing, Nothing)
End Sub

5. The default event interface of the PageLayoutControl is the IPageLayoutControlEvents. These events do not tell you when the
extent of the map in a data frame changes. To enable this functionality, use the ITransformEvents interface of the
PageLayoutControl's focus map. Add the following code to the PageLayoutControl_OnPageLayoutReplaced event handler before
the load document code:

[C#]

private void axPageLayoutControl1_OnPageLayoutReplaced(object sender,


IPageLayoutControlEvents_OnPageLayoutReplacedEvent e)
{
//Get the IActiveView of the focus map in the PageLayoutControl.
IActiveView activeView = axPageLayoutControl1.ActiveView.FocusMap as
IActiveView;
//Trap the ITranformEvents of the PageLayoutControl's focus map.
visBoundsUpdatedE = new ITransformEvents_VisibleBoundsUpdatedEventHandler
(OnVisibleBoundsUpdated);
IDisplayTransformation displayTransformation =
activeView.ScreenDisplay.DisplayTransformation;
//Start listening to the transform events interface.
m_transformEvents = (ITransformEvents_Event)displayTransformation;
//Start listening to the VisibleBoundsUpdated method on ITransformEvents interface.
m_transformEvents.VisibleBoundsUpdated += visBoundsUpdatedE;
//Get the extent of the focus map.
m_Envelope = activeView.Extent;

//Load the same pre-authored map document into the MapControl.

13 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

[VB.NET]

Private Sub AxPageLayoutControl1_OnPageLayoutReplaced(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.IPageLayoutControlEve


'Get the IActiveView of the focus map in the PageLayoutControl.
Dim activeView As IActiveView = AxPageLayoutControl1.ActiveView.FocusMap
'Trap the ITranformEvents of the PageLayoutControl's focus map.
visBoundsUpdatedE = New ITransformEvents_VisibleBoundsUpdatedEventHandler(AddressOf OnVisibleBoundsUpdated)
'Start listening to the transform events interface.
m_pTransformEvents = activeView.ScreenDisplay.DisplayTransformation
'Start listening to the VisibleBoundsUpdated method on ITransformEvents interface.
AddHandler (m_pTransformEvents.VisibleBoundsUpdated), visBoundsUpdatedE
'Get the extent of the focus map.
m_pEnvelope = activeView.Extent

'Load the same pre-authored map document into the MapControl.


End Sub

6. Display the form in design mode and select axMapControl1 from the Properties window and display the MapControl events.
Double-click OnAfterDraw to add an event handler to the code window.
7. Add the following code to the MapControl_OnAfterDraw event handler to draw an envelope using the symbol you created
previously onto the MapControl's display:

[C#]

private void axMapControl1_OnAfterDraw(object sender,


IMapControlEvents2_OnAfterDrawEvent e)
{
if (m_Envelope == null)
return ;

//If the foreground phase has drawn.


esriViewDrawPhase viewDrawPhase = (esriViewDrawPhase)e.viewDrawPhase;
if (viewDrawPhase == esriViewDrawPhase.esriViewForeground)
{
IGeometry geometry = m_Envelope;
axMapControl1.DrawShape(geometry, ref m_FillSymbol);
}
}

[VB.NET]

Private Sub AxMapControl1_OnAfterDraw(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.IMapControlEvents2_OnAfterDrawEvent)


If m_pEnvelope Is Nothing Then Exit Sub

'If the foreground phase has drawn.


Dim pViewDrawPhase As esriViewDrawPhase
pViewDrawPhase = e.viewDrawPhase
If pViewDrawPhase = esriViewDrawPhase.esriViewForeground Then
'Draw the shape on the MapControl
AxMapControl1.DrawShape(m_pEnvelope, m_pFillSymbol)
End If
End Sub

8. Build and run the application. Use the map navigation tools that you added previously to change the extent of the focus map in
the PageLayoutControl. The new extent is drawn on the MapControl. See the following screen shot:

14 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Navigating around the focus map using the map navigation tools will change the extent of the focus map in the
PageLayoutControl and cause the MapControl to update. Navigating around the page layout with the page layout navigation tools
will change the extent of the page layout (not the extent of the focus map in the PageLayoutControl), so the MapControl will not
update.

Creating a custom tool


Creating custom commands and tools to work with the MapControl and PageLayoutControl is very similar to creating commands for the ESRI
ArcMap application that you may have done previously. You will create a custom tool that adds a text element containing today's date to the
PageLayoutControl at the location of a mouse click. However, you will create the command to work with the MapControl and ToolbarControl, as
well as the PageLayoutControl.
1. Choose Add, then New Project from the File menu.
2. Choose the Class Library template from the ArcGIS Engine project types. Name the project Commands and click OK.
3. In the ArcGIS Project Wizard, double-click ESRI.ArcGIS.Carto, ESRI.ArcGIS.Display, and ESRI.ArcGIS.Geometry to add them to
the selected assemblies, then click Finish.
4. Delete Class1 from the Commands project.
5. Choose Add New Item from the Project menu to add a new item to the Commands project.
6. Choose the Base Tool template from the ArcGIS Engine category in the Add New Item dialog box.
7. Name the tool AddDateTool and click Add to add it to the project.
8. Click the ArcMap, MapControl, or PageLayoutControl Tool from the ArcGIS New Item Wizard Options dialog box and click OK.

The AddDateTool class inherits from the ESRI BaseTool abstract class. Abstract classes are classes that cannot be instantiated
and frequently contain only partial implementation code or no implementation at all. They are closely related to interfaces;
however, they differ significantly from interfaces in that a class may implement any number of interfaces but it can inherit from
only one abstract class. Inheriting the ESRI BaseCommand and BaseTool abstract classes will allow you to create commands and
tools more quickly and simply than directly implementing the esriSystemUI ICommand and ITool interfaces.

The sealed class modifier in C# and the NotInheritable modifier in VB.NEt states that a class cannot be inherited from. As this
class is not designed for this purpose, it is prudent to add this modifier to prevent other classes from inheriting this class.

9. Add the following additional using directives or import statements to the class:

[C#]

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;

[VB.NET]

Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Display
Imports ESRI.ArcGIS.Geometry

10. Update the code in the AddDateTool class constructor as shown in the following code example:

The class constructor is a method that is called when the class is created. It can be used to set up members of the class. In C#
the constructor method has the same name as the class. It differs from other methods in that it has no return type.

Instead of implementing the Bitmap, Caption, Category, Name, Message, and ToolTip methods individually, you can set the
values that should be returned from these methods and rely on the BaseTool class to provide the implementation for these
methods. The other members will be left to return the default values as implemented by the BaseTool class.

15 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

[C#]

public AddDateTool()
{
base.m_category = "CustomMapViewer";
base.m_caption = "Add Date";
base.m_message = "Adds a date element to the active view";
base.m_toolTip = "Add Date";
base.m_name = "CustomMapViewer_AddDateTool";
try
{
string bitmapResourceName = GetType().Name + ".bmp";
base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
base.m_cursor = new Cursor(GetType(), GetType().Name + ".cur");
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
}
}

[VB.NET]

Public Sub New()


MyBase.New()
MyBase.m_category = "CustomMapViewer"
MyBase.m_caption = "Add Date"
MyBase.m_message = "Adds a date element to the active view"
MyBase.m_toolTip = "Add Date"
MyBase.m_name = "CustomMapViewer_AddDateTool"
Try
Dim bitmapResourceName As String = Me.GetType().Name + ".bmp"
MyBase.m_bitmap = New Bitmap(Me.GetType(), bitmapResourceName)
MyBase.m_cursor = New Cursor(Me.GetType(), Me.GetType().Name + ".cur")
Catch ex As Exception
System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap")
End Try
End Sub

11. Navigate to the overridden OnCreate method and look at the code.

The ICommand.OnCreate method is passed a handle or hook to the application that the command will work with. In this case, it
can be a MapControl, PageLayoutControl, ToolbarControl, or the ArcMap application. Rather than adding code into the
OnCreate method to determine the type of hook that is being passed to the command, the HookHelper is used to handle this. A
command or tool needs to know how to handle the hook it gets passed, so a check is needed to determine the type of ArcGIS
Engine control that has been passed. The HookHelper is used to hold the hook and return the ActiveView regardless of the type
of hook (in this case a MapControl, PageLayoutControl, ToolbarControl, or ArcMap).

12. Navigate to the overridden OnMouseDown event and add the following code:

[C#]

public override void OnMouseDown(int Button, int Shift, int X, int Y)


{
//Get the active view.
IActiveView activeView = m_hookHelper.ActiveView;

//Create a new text element.


ITextElement textElement = new TextElementClass();
//Create a text symbol.
ITextSymbol textSymbol = new TextSymbolClass();
textSymbol.Size = 25;

//Set the text element properties.


textElement.Symbol = textSymbol;
textElement.Text = DateTime.Now.ToShortDateString();

//Query interface (QI) for IElement.


IElement element = (IElement)textElement;
//Create a point.
IPoint point = new PointClass();
point = activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);
//Set the element's geometry.
element.Geometry = point;

//Add the element to the graphics container.


activeView.GraphicsContainer.AddElement(element, 0);
//Refresh the graphics.
activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
}

[VB.NET]

Public Overrides Sub OnMouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Integer, ByVal Y As Integer)
'Get the active view.
Dim pActiveView As IActiveView = m_hookHelper.ActiveView

'Create a new text element.


Dim pTextElement As ITextElement = New TextElementClass
'Create a text symbol.
Dim pTextSymbol As ITextSymbol = New TextSymbolClass
pTextSymbol.Size = 25

'Set the text element properties.


pTextElement.Symbol = pTextSymbol

16 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

pTextElement.Text = Date.Now.ToShortDateString

'Query interface (QI) for IElement.


Dim pElement As IElement
pElement = pTextElement
'Create a point.
Dim pPoint As IPoint
pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y)
'Set the element's geometry.
pElement.Geometry = pPoint

'Add the element to the graphics container.


pActiveView.GraphicsContainer.AddElement(pTextElement, 0)
'Refresh the graphics.
pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing)
End Sub

ArcGIS Engine expects a custom command or tool to be a COM class; therefore, the .NET class you have created must be
exposed as a COM class by creating a COM callable wrapper for it. The BaseTool has already provided the attributes and globally
unique identifiers (GUIDs) required by COM in the class.

The Commands project properties have also been automatically amended to set Register for COM Interop to true. Setting the
Register for COM Interop property to true will invoke the Assembly Registration tool (Regasm.exe). This will add the information
about the class to the registry that a COM client would expect to find.

Visual Studio .NET provides the ability to specify functions that execute when an assembly exposed for COM interop is registered
and unregistered on a system. This allows you to register your class in a component category that the Customize dialog box will
look for. The BaseTool has already provided these COM Registration Functions in the class and will register the tool with the ESRI
Controls Commands and ESRI Mx Commands component categories. The ComVisible attribute is set to false to ensure that this
method cannot be called directly by a COM client. It does not affect the method being called when the assembly is registered
with COM.

13. Build the Commands project.


14. In the Controls Windows Application project that you created at the beginning of this scenario, add the following code before the
ToolbarPalette code:

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Add map inquiry commands.

//Add custom AddDateTool.


axToolbarControl1.AddItem("Commands.AddDateTool", - 1, - 1, false, 0,
esriCommandStyles.esriCommandStyleIconAndText);

//Create a new ToolbarPalette.


}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Add map inquiry commands.

'Add custom AddDateTool.


AxToolbarControl1.AddItem("Commands.AddDateTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconAndText)

'Create a new ToolbarPalette.


End Sub

15. Build and run the Controls project. See the following screen shot:

17 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Customizing the ToolbarControl


In addition to adding ArcGIS Engine commands and tools to the ToolbarControl in the Form_Load event, you can also add them by
customizing the ToolbarControl at run time using the CustomizeDialog. To do this, you will place the ToolbarControl in customize mode and
display the CustomizeDialog.
1. Add the following member variables to the class:

[C#]

public partial class MapViewer: Form


{
//The CustomizeDialog used by the ToolbarControl.
private ICustomizeDialog m_CustomizeDialog;
//The CustomizeDialog start event.
private ICustomizeDialogEvents_OnStartDialogEventHandler startDialogE;
//The CustomizeDialog close event.
private ICustomizeDialogEvents_OnCloseDialogEventHandler closeDialogE;
}

[VB.NET]

Public Class MapViewer


'The CustomizeDialog used by the ToolbarControl.
Private m_pCustomizeDialog As ICustomizeDialog
'The CustomizeDialog start event.
Private startDialogE As ICustomizeDialogEvents_OnStartDialogEventHandler
'The CustomizeDialog close event.
Private closeDialogE As ICustomizeDialogEvents_OnCloseDialogEventHandler
End Class

2. Create a new function called CreateCustomizeDialog. This is where you will create the Customize dialog box by adding the
following code to the function:

[C#]

private void CreateCustomizeDialog()


{
//Create a new Customize dialog box.
m_CustomizeDialog = new CustomizeDialogClass();
//Set the title.
m_CustomizeDialog.DialogTitle = "Customize ToolbarControl Items";
//Show the Add from File button.
m_CustomizeDialog.ShowAddFromFile = true;
//Set the ToolbarControl that new items will be added to.
m_CustomizeDialog.SetDoubleClickDestination(axToolbarControl1);

//Set the Customize dialog box events.


startDialogE = new ICustomizeDialogEvents_OnStartDialogEventHandler
(OnStartDialog);
((ICustomizeDialogEvents_Event)m_CustomizeDialog).OnStartDialog +=
startDialogE;
closeDialogE = new ICustomizeDialogEvents_OnCloseDialogEventHandler
(OnCloseDialog);
((ICustomizeDialogEvents_Event)m_CustomizeDialog).OnCloseDialog +=
closeDialogE;
}

18 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

[VB.NET]

Private Sub CreateCustomizeDialog()


'Create a new Customize dialog box.
m_pCustomizeDialog = New CustomizeDialogClass()
'Set the title.
m_pCustomizeDialog.DialogTitle = "Customize ToolbarControl Items"
'Show the Add from File button.
m_pCustomizeDialog.ShowAddFromFile = True
'Set the ToolbarControl that new items will be added to.
m_pCustomizeDialog.SetDoubleClickDestination(AxToolbarControl1)

'Set the Customize dialog box events.


startDialogE = New ICustomizeDialogEvents_OnStartDialogEventHandler(AddressOf OnStartDialog)
AddHandler CType(m_pCustomizeDialog, ICustomizeDialogEvents_Event).OnStartDialog, startDialogE
closeDialogE = New ICustomizeDialogEvents_OnCloseDialogEventHandler(AddressOf OnCloseDialog)
AddHandler CType(m_pCustomizeDialog, ICustomizeDialogEvents_Event).OnCloseDialog, closeDialogE
End Sub

3. Call the CreateCustomizeDialog function from the beginning of the Form_Load event. See the following code example:

[C#]

private void MapViewer_Load(object sender, EventArgs e)


{
//Create the Customize dialog box for the ToolbarControl.
CreateCustomizeDialog();

//Create the symbol used on the MapControl.


}

[VB.NET]

Private Sub MapViewer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'Create the Customize dialog box for the ToolbarControl.
CreateCustomizeDialog()

'Create the symbol used on the MapControl.


End Sub

4. Add a check box to the form, name it chkCustomize and give it the caption of Customize.
5. Display the form in design mode and select chkCustomize from the Properties window and display the chkCustomize events.
Double-click CheckedChanged to add an event handler to the code window.
6. Add the following code to the chkCustomize_CheckedChanged event:

[C#]

private void chkCustomize_CheckedChanged(object sender, EventArgs e)


{
//Show or hide the Customize dialog box.
if (chkCustomize.Checked == false)
m_CustomizeDialog.CloseDialog();
else
m_CustomizeDialog.StartDialog(axToolbarControl1.hWnd);
}

[VB.NET]

Private Sub chkCustomize_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkCustomize.CheckedChanged


'Show or hide the Customize dialog box.
If chkCustomize.Checked = False Then
m_pCustomizeDialog.CloseDialog()
Else
m_pCustomizeDialog.StartDialog(AxToolbarControl1.hWnd)
End If
End Sub

7. Add the following OnStartDialog and OnCloseDialog event handlers. These functions will be wired to events raised whenever the
Customize dialog box is opened or closed.

[C#]

private void OnStartDialog()


{
axToolbarControl1.Customize = true;
}

private void OnCloseDialog()


{
axToolbarControl1.Customize = false;
chkCustomize.Checked = false;
}

[VB.NET]

Private Sub OnStartDialog()


AxToolbarControl1.Customize = True
End Sub

19 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

Private Sub OnCloseDialog()


AxToolbarControl1.Customize = False
chkCustomize.Checked = False
End Sub

8. Build and run the application. Check the Customize control to put the ToolbarControl into customize mode and to open the
Customize dialog box.
9. On the Commands tab select the Graphic Element category and double-click the Select Elements command to add it to the
ToolbarControl. Right-click an item on the ToolbarControl to adjust its appearance in terms of style and grouping. See the
following screen shot:

10. Stop customizing the application. Use the select tool to move the text element containing today's date.
Saving and loading ToolbarControl items
The contents of a ToolbarControl can be persisted into a user's profile when an application exits to preserve any customizations made to the
ToolbarControl by the end user. An application can load the persisted contents back into the ToolbarControl at application start time. You will
persist the contents of the ToolbarControl into a file located in the same directory as the applications executing assembly.
1. Create a new function called SaveToolbarControlItems. This is where you will persist the contents of the ToolbarControl by adding
the following code to the function:

[C#]

private void SaveToolbarControlItems(string filePath)


{
//Create a MemoryBlobStream.
IBlobStream blobStream = new MemoryBlobStreamClass();
//Get the IStream interface.
IStream stream = blobStream;
//Save the ToolbarControl into the stream.
axToolbarControl1.SaveItems(stream);
//Save the stream to a file.
blobStream.SaveToFile(filePath);
}

[VB.NET]

Private Sub SaveToolbarControlItems(ByVal filePath)


'Create a MemoryBlobStream.
Dim blobStream As IBlobStream
blobStream = New MemoryBlobStreamClass
'Get the IStream interface.
Dim stream As IStream
stream = blobStream
'Save the ToolbarControl into the stream.
AxToolbarControl1.SaveItems(stream)
'Save the stream to a file.
blobStream.SaveToFile(filePath)
End Sub

2. Create a new function called LoadToolbarControlItems. This is where you will load the persisted contents back into the
ToolbarControl by adding the following code to the function:

[C#]

private void LoadToolbarControlItems(string filePath)


{
//Create a MemoryBlobStream.

20 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

IBlobStream blobStream = new MemoryBlobStreamClass();


//Get the IStream interface.
IStream stream = blobStream;
//Load the stream from the file.
blobStream.LoadFromFile(filePath);
//Load the stream into the ToolbarControl.
axToolbarControl1.LoadItems(stream);
}

[VB.NET]

Private Sub LoadToolbarControlItems(ByVal filePath)


'Create a MemoryBlobStream.
Dim blobStream As IBlobStream
blobStream = New MemoryBlobStreamClass
'Get the IStream interface.
Dim stream As IStream
stream = blobStream
'Load the stream from the file.
blobStream.LoadFromFile(filePath)
'Load the stream into the ToolbarControl.
AxToolbarControl1.LoadItems(stream)
End Sub

3. Display the form in design mode and select the form from the Properties window and display the form events. Double-click
the FormClosing event to add an event handler to the code window.
4. In the FormClosing event, enter the following code to persist the contents of the ToolbarControl into a file at the same location as
the executing assembly. You may need to substitute "Controls.exe" with the name of your executable.

[C#]

private void MapViewer_FormClosing(object sender, FormClosingEventArgs e)


{
//Get file name to persist the ToolbarControl.
String filePath = System.Reflection.Assembly.GetExecutingAssembly()
.Location.Replace("Controls.exe", "") + @"\PersistedItems.txt";
//Persist ToolbarControl contents.
SaveToolbarControlItems(filePath);
}

[VB.NET]

Private Sub MapViewer_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.Form


'Get file name to persist the ToolbarControl.
Dim filePath As String
filePath = System.Reflection.Assembly.GetExecutingAssembly.Location.Replace("Controls.exe", "") & "\PersistedItems.txt"
'Persist ToolbarControl contents.
SaveToolbarControlItems(filePath)
End Sub

5. Update the code to add items to the ToolbarControl in the Form_Load event as shown in the following code (you may need to
substitute "Controls.exe" with the name of your executable):

[C#]

//Get file name used to persist the ToolbarControl.


String filePath = System.Reflection.Assembly.GetExecutingAssembly()
.Location.Replace("Controls.exe", "") + @"\PersistedItems.txt";
if (System.IO.File.Exists(filePath))
LoadToolbarControlItems(filePath);
else
{
//Add generic commands.
axToolbarControl1.AddItem("esriControls.ControlsOpenDocCommand", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsAddDataCommand", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
//Add page layout navigation commands.
axToolbarControl1.AddItem("esriControls.ControlsPageZoomInTool", - 1, - 1,
true, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsPageZoomOutTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsPagePanTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsPageZoomWholePageCommand", -
1, - 1, false, 0, esriCommandStyles.esriCommandStyleIconOnly);
//Add map navigation commands.
axToolbarControl1.AddItem("esriControls.ControlsMapZoomInTool", - 1, - 1,
true, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapZoomOutTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapPanTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapFullExtentCommand", - 1,
- 1, false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZoomToLastExtentBackCommand", - 1, - 1, false, 0,
esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZoomToLastExtentForwardCommand", - 1, - 1, false,
0, esriCommandStyles.esriCommandStyleIconOnly);
//Add map inquiry commands.
axToolbarControl1.AddItem("esriControls.ControlsMapIdentifyTool", - 1, - 1,

21 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

true, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapFindCommand", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
axToolbarControl1.AddItem("esriControls.ControlsMapMeasureTool", - 1, - 1,
false, 0, esriCommandStyles.esriCommandStyleIconOnly);
//Add custom AddDateTool.
axToolbarControl1.AddItem("Commands.AddDateTool", - 1, - 1, false, 0,
esriCommandStyles.esriCommandStyleIconAndText);

//Create a new ToolbarPalette.


IToolbarPalette toolbarPalette = new ToolbarPaletteClass();
//Add commands and tools to the ToolbarPalette.
toolbarPalette.AddItem("esriControls.ControlsNewMarkerTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewLineTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewCircleTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewEllipseTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewRectangleTool", - 1, - 1);
toolbarPalette.AddItem("esriControls.ControlsNewPolygonTool", - 1, - 1);
//Add the ToolbarPalette to the ToolbarControl.
axToolbarControl1.AddItem(toolbarPalette, 0, - 1, false, 0,
esriCommandStyles.esriCommandStyleIconOnly);
}

[VB.NET]

'Get file name used to persist the ToolbarControl.


Dim filePath As String
filePath = System.Reflection.Assembly.GetExecutingAssembly.Location.Replace("Controls.exe", "") & "\PersistedItems.txt"
If System.IO.File.Exists(filePath) Then
LoadToolbarControlItems(filePath)
Else
'Add generic commands.
AxToolbarControl1.AddItem("esriControls.ControlsOpenDocCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsAddDataCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
'Add page layout navigation commands.
AxToolbarControl1.AddItem("esriControls.ControlsPageZoomInTool", -1, -1, True, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsPageZoomOutTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsPagePanTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsPageZoomWholePageCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnl
'Add map navigation commands.
AxToolbarControl1.AddItem("esriControls.ControlsMapZoomInTool", -1, -1, True, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapZoomOutTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapPanTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapFullExtentCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapZoomToLastExtentBackCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleI
AxToolbarControl1.AddItem("esriControls.ControlsMapZoomToLastExtentForwardCommand", -1, -1, False, 0, esriCommandStyles.esriCommandSty
'Add map inquiry commands.
AxToolbarControl1.AddItem("esriControls.ControlsMapIdentifyTool", -1, -1, True, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapFindCommand", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
AxToolbarControl1.AddItem("esriControls.ControlsMapMeasureTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
'Add custom AddDateTool.
AxToolbarControl1.AddItem("Commands.AddDateTool", -1, -1, False, 0, esriCommandStyles.esriCommandStyleIconAndText)

'Create a new ToolbarPalette.


Dim pToolbarPalette As IToolbarPalette = New ToolbarPaletteClass()
'Add commands and tools to the ToolbarPalette.
pToolbarPalette.AddItem("esriControls.ControlsNewMarkerTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewLineTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewCircleTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewEllipseTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewRectangleTool", -1, -1)
pToolbarPalette.AddItem("esriControls.ControlsNewPolygonTool", -1, -1)
'Add the ToolbarPalette to the ToolbarControl.
AxToolbarControl1.AddItem(pToolbarPalette, 0, -1, False, 0, esriCommandStyles.esriCommandStyleIconOnly)
End If

6. Build and run the application and customize the ToolbarControl.


7. Stop running the application.
8. Restart the application. The customizations you made to the ToolbarControl will be reflected in the application.
Printing the page layout
The PageLayoutControl encapsulates the page layout that manages the page that can be sent to any available printer. You will add code to
allow users to send output to the system default printer.
1. Display the form in design mode and select MenuStrip control on the form.
2. Click Type Here and type File to create a File menu.
3. On the File menu click Type Here and type Print… to create a menu item.
4. Double click the Print… menu item to add an event handler to the code window.
5. In the PrintToolStripMenuItem_Click event, enter the following code to send the page to the printer:

[C#]

private void printToolStripMenuItem_Click(object sender, EventArgs e)


{
//Exit if there is no system default printer.
if (axPageLayoutControl1.Printer == null)
{
MessageBox.Show("Unable to print!", "No default printer");
return ;
}

//Set printer papers orientation to that of the page.


axPageLayoutControl1.Printer.Paper.Orientation =
axPageLayoutControl1.Page.Orientation;

22 of 23 2010-3-13 4:07
Building a map viewing application using the ArcGIS Engi... http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/7...

//Scale to the page.


axPageLayoutControl1.Page.PageToPrinterMapping =
esriPageToPrinterMapping.esriPageMappingScale;
//Send the page layout to the printer.
axPageLayoutControl1.PrintPageLayout();
}

[VB.NET]

Private Sub PrintToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintToolStripMenuItem.Click


'Exit if there is no system default printer.
If AxPageLayoutControl1.Printer Is Nothing Then
MessageBox.Show("Unable to print!", "No default printer")
Exit Sub
End If

'Set printer papers orientation to that of the page.


AxPageLayoutControl1.Printer.Paper.Orientation = AxPageLayoutControl1.Page.Orientation
'Scale to the page.
AxPageLayoutControl1.Page.PageToPrinterMapping = esriPageToPrinterMapping.esriPageMappingScale
'Send the page layout to the printer.
AxPageLayoutControl1.PrintPageLayout()
End Sub

6. Build and run the application. Use the Print… menu item to send output to the printer. See the following screen shot:

Deployment
To successfully deploy this application on a user's machine:
The application's executable and the .dll and .tlb files containing the custom command will need to be deployed on the user's
machine. The Assembly Registration tool (RegAsm.exe) must be used to add information about the custom class to the registry.
The user's machine will need an installation of the ArcGIS Engine Runtime and a standard ArcGIS Engine license.
The user's machine will need an installation of the Microsoft .NET Framework 2.0.

Additional resources
The following resources may help you understand and apply the concepts and techniques presented in this scenario:
Additional documentation is available in the ArcGIS Engine SDK for the Microsoft .NET Framework. This includes component help,
object model diagrams, and samples to help you get started.
ESRI Developer Network (EDN) Web site provides the most up-to-date information for ArcGIS developers including updated
samples and technical documents. See http://edn.esri.com.
ESRI online discussion forums provide invaluable assistance from other ArcGIS developers. See http://support.esri.com and click
the User Forums tab.
Microsoft documentation is also available for the Visual Studio .NET development environment. See http://msdn.com.

See Also:
How to write your first MapControl application

23 of 23 2010-3-13 4:07