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

Building a map viewing application using the

ArcGIS Engine controls


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 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:

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 pressing the Tab key.
[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;
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.
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#]

privatevoid
MapViewer_Load(object
sender, System.EventArgs e)
{
//Load a pre-authored map
document into the
PageLayoutControl using
relative paths.
string fileName = @
"..\..\..\..\data\GulfOfStL
awrence\Gulf_of_St._Lawrenc
e.mxd";
if
(axPageLayoutControl1.Check
MxFile(fileName))
axPageLayoutControl1.LoadMx
File(fileName, "");
}
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#]

privatevoid
axPageLayoutControl1_OnPage
LayoutReplaced(object
sender,
IPageLayoutControlEvents_On
PageLayoutReplacedEvent e)
{
//Load the same preauthored map document into
the MapControl.
axMapControl1.LoadMxFile(ax
PageLayoutControl1.Document
Filename, null, null);

//Set the extent of the


MapControl to the full
extent of the data.
axMapControl1.Extent =
axMapControl1.FullExtent;
}

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#]

privatevoid
MapViewer_Load(object
sender, System.EventArgs e)
{
//Set buddy controls.
axTOCControl1.SetBuddyContr
ol(axPageLayoutControl1);
axToolbarControl1.SetBuddyC
ontrol(axPageLayoutControl1
);

//Load a pre-authored map


document into the
PageLayoutControl using
relative paths.

}
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#]

privatevoid
MapViewer_ResizeBegin(objec
t sender, EventArgs e)
{
//Suppress data redraw and
draw bitmap instead.
axMapControl1.SuppressResiz
eDrawing(true, 0);
axPageLayoutControl1.Suppre
ssResizeDrawing(true, 0);
}

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.
5.

In the Form_ResizeEnd event, enter the following code to stop drawing a stretchy bitmap
in the PageLayoutControl and MapControl:

[C#]

privatevoid
MapViewer_ResizeEnd(object
sender, EventArgs e)
{
//Stop bitmap draw and draw
data.
axMapControl1.SuppressResiz
eDrawing(false, 0);
axPageLayoutControl1.Suppre
ssResizeDrawing(false, 0);
}
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.

[C#]

In the Form_Load event add the following code before the set buddy controls code:

privatevoid
MapViewer_Load(object
sender, EventArgs e)
{
//Add generic commands.
axToolbarControl1.AddItem("
esriControls.ControlsOpenDo
cCommand", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsAddDat
aCommand", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add page layout
navigation commands.
axToolbarControl1.AddItem("
esriControls.ControlsPageZo
omInTool", - 1, - 1,
true, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsPageZo
omOutTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);

axToolbarControl1.AddItem("
esriControls.ControlsPagePa
nTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsPageZo
omWholePageCommand", 1, - 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add map navigation
commands.
axToolbarControl1.AddItem("
esriControls.ControlsMapZoo
mInTool", - 1, - 1,
true, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapZoo
mOutTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapPan
Tool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);

axToolbarControl1.AddItem("
esriControls.ControlsMapFul
lExtentCommand", - 1,
- 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZo
omToLastExtentBackCommand",
- 1, - 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZo
omToLastExtentForwardComman
d", - 1, - 1, false,
0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add map inquiry commands.
axToolbarControl1.AddItem("
esriControls.ControlsMapIde
ntifyTool", - 1, - 1,
true, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapFin
dCommand", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);

axToolbarControl1.AddItem("
esriControls.ControlsMapMea
sureTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);

//Set buddy controls.


}
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#]

publicpartialclass
MapViewer: Form
{
//The pop-up menu.
private IToolbarMenu
m_ToolbarMenu;
}

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#]

privatevoid
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.CommandPo
ol;
//Set the hook to the
PageLayoutControl.
m_ToolbarMenu.SetHook(axPag
eLayoutControl1);
//Add commands to the
ToolbarMenu.
m_ToolbarMenu.AddItem("esri
Controls.ControlsPageZoomIn
FixedCommand", - 1, -

1, false,
esriCommandStyles.esriComma
ndStyleIconAndText);
m_ToolbarMenu.AddItem("esri
Controls.ControlsPageZoomOu
tFixedCommand", - 1,
- 1, false,
esriCommandStyles.esriComma
ndStyleIconAndText);
m_ToolbarMenu.AddItem("esri
Controls.ControlsPageZoomWh
olePageCommand", - 1,
- 1, false,
esriCommandStyles.esriComma
ndStyleIconAndText);
m_ToolbarMenu.AddItem(
"esriControls.ControlsPageZ
oomPageToLastExtentBackComm
and", - 1, - 1,
true,
esriCommandStyles.esriComma
ndStyleIconAndText);
m_ToolbarMenu.AddItem(
"esriControls.ControlsPageZ
oomPageToLastExtentForwardC
ommand", - 1, - 1,
false,
esriCommandStyles.esriComma
ndStyleIconAndText);

//Set buddy controls.

}
Display the form in design mode, select
axPageLayoutControl1 from the Properties window,
and display the PageLayoutControl events. Doubleclick the OnMouseDown event to add an event
handler to the code window.
3.

In the PageLayoutControl_OnMouseDown event, add the following code:

[C#]

privatevoid
axPageLayoutControl1_OnMous
eDown(object sender,
IPageLayoutControlEvents_On
MouseDownEvent e)
{
//Pop-up the ToolbarMenu.
if (e.button == 2)
m_ToolbarMenu.PopupMenu(e.x
, e.y,
axPageLayoutControl1.hWnd);
}
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:

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#]

privatevoid
MapViewer_Load(object
sender, EventArgs e)
{
//Add map inquiry commands.

//Create a new
ToolbarPalette.

IToolbarPalette
toolbarPalette =
newToolbarPaletteClass();
//Add commands and tools to
the ToolbarPalette.
toolbarPalette.AddItem("esr
iControls.ControlsNewMarker
Tool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewLineTo
ol", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewCircle
Tool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewEllips
eTool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewRectan
gleTool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewPolygo
nTool", - 1, - 1);
//Add the ToolbarPalette to
the ToolbarControl.
axToolbarControl1.AddItem(t
oolbarPalette, 0, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);

//Add commands to the


ToolbarMenu.
}
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:

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.

[C#]

Add the following code to the beginning of the Form_Load event:

privatevoid
MapViewer_Load(object
sender, EventArgs e)
{
//Set label editing to
manual.
axTOCControl1.LabelEdit =
esriTOCControlEdit.esriTOCC
ontrolManual;
}
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#]

privatevoid
axTOCControl1_OnEndLabelEdi
t(object sender,
ITOCControlEvents_OnEndLabe
lEditEvent e)
{
//If the new label is an
empty string, prevent the
edit.
if (e.newLabel.Trim() ==
"")
e.canEdit = false;
}
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:

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#]

publicpartialclass
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_VisibleBou
ndsUpdatedEventHandler
visBoundsUpdatedE;
}

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#]

privatevoid
CreateOverviewSymbol()
{
//Get the IRGBColor
interface.

IRgbColor color =
newRgbColorClass();
//Set the color properties.
color.RGB = 255;
//Get the ILine symbol
interface.
ILineSymbol outline =
newSimpleLineSymbolClass();
//Set the line symbol
properties.
outline.Width = 1.5;
outline.Color = color;
//Get the IFillSymbol
interface.
ISimpleFillSymbol
simpleFillSymbol =
newSimpleFillSymbolClass();
//Set the fill symbol
properties.
simpleFillSymbol.Outline
= outline;
simpleFillSymbol.Style =
esriSimpleFillStyle.esriSFS
Hollow;
m_FillSymbol =
simpleFillSymbol;
}
Call the CreateOverviewSymbol function from the
beginning of the Form_Load event. See the following
code example:

[C#]

privatevoid
MapViewer_Load(object
sender, EventArgs e)
{
//Create the symbol used on
the MapControl.
CreateOverviewSymbol();
}
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#]

privatevoid
OnVisibleBoundsUpdated(IDis
playTransformation sender,
bool
sizeChanged)
{
//Set the extent to the new
visible extent.
m_Envelope =
sender.VisibleBounds;
//Refresh the MapControl's
foreground phase.
axMapControl1.ActiveView.Pa
rtialRefresh(esriViewDrawPh
ase.esriViewForeground,

null, null);
}
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#]

privatevoid
axPageLayoutControl1_OnPage
LayoutReplaced(object
sender,
IPageLayoutControlEvents_On
PageLayoutReplacedEvent e)
{
//Get the IActiveView of
the focus map in the
PageLayoutControl.
IActiveView activeView =
axPageLayoutControl1.Active
View.FocusMap as
IActiveView;
//Trap the ITranformEvents
of the PageLayoutControl's
focus map.
visBoundsUpdatedE = new
ITransformEvents_VisibleBou
ndsUpdatedEventHandler
(OnVisibleBoundsUpdated);

IDisplayTransformation
displayTransformation =
activeView.ScreenDisplay.Di
splayTransformation;
//Start listening to the
transform events interface.
m_transformEvents =
(ITransformEvents_Event)dis
playTransformation;
//Start listening to the
VisibleBoundsUpdated method
on ITransformEvents
interface.
m_transformEvents.VisibleBo
undsUpdated +=
visBoundsUpdatedE;
//Get the extent of the
focus map.
m_Envelope =
activeView.Extent;

//Load the same preauthored map document into


the MapControl.
}
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.
6.

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#]

privatevoid
axMapControl1_OnAfterDraw(o
bject sender,
IMapControlEvents2_OnAfterD
rawEvent e)
{
if (m_Envelope == null)
return ;

//If the foreground phase


has drawn.
esriViewDrawPhase
viewDrawPhase =
(esriViewDrawPhase)e.viewDr
awPhase;
if (viewDrawPhase ==
esriViewDrawPhase.esriViewF
oreground)
{
IGeometry geometry =
m_Envelope;
axMapControl1.DrawShape(geo
metry, ref m_FillSymbol);
}
}
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:

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;
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.
[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_AddDateToo
l";
try
{
string bitmapResourceName =
GetType().Name + ".bmp";
base.m_bitmap =
newBitmap(GetType(),
bitmapResourceName);
base.m_cursor =
newCursor(GetType(),
GetType().Name + ".cur");
}
catch (Exception ex)
{
System.Diagnostics.Trace.Wr
iteLine(ex.Message,
"Invalid Bitmap");
}
}
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#]

publicoverridevoid
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
= newTextElementClass();
//Create a text symbol.
ITextSymbol textSymbol =
newTextSymbolClass();
textSymbol.Size = 25;

//Set the text element


properties.
textElement.Symbol =
textSymbol;

textElement.Text =
DateTime.Now.ToShortDateStr
ing();

//Query interface (QI) for


IElement.
IElement element =
(IElement)textElement;
//Create a point.
IPoint point =
newPointClass();
point =
activeView.ScreenDisplay.Di
splayTransformation.ToMapPo
int(X, Y);
//Set the element's
geometry.
element.Geometry = point;

//Add the element to the


graphics container.
activeView.GraphicsContaine
r.AddElement(element, 0);
//Refresh the graphics.
activeView.PartialRefresh(e
sriViewDrawPhase.esriViewGr
aphics, null, null);
}

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#]

privatevoid
MapViewer_Load(object
sender, EventArgs e)
{
//Add map inquiry commands.

//Add custom AddDateTool.


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

//Create a new
ToolbarPalette.
}

Build and run the Controls project. See the following


screen shot:

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#]

publicpartialclass
MapViewer: Form
{

//The CustomizeDialog used


by the ToolbarControl.
private ICustomizeDialog
m_CustomizeDialog;
//The CustomizeDialog start
event.
private
ICustomizeDialogEvents_OnSt
artDialogEventHandler
startDialogE;
//The CustomizeDialog close
event.
private
ICustomizeDialogEvents_OnCl
oseDialogEventHandler
closeDialogE;
}
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#]

privatevoid
CreateCustomizeDialog()
{
//Create a new Customize
dialog box.
m_CustomizeDialog =
newCustomizeDialogClass();
//Set the title.
m_CustomizeDialog.DialogTit

le = "Customize
ToolbarControl Items";
//Show the Add from File
button.
m_CustomizeDialog.ShowAddFr
omFile = true;
//Set the ToolbarControl
that new items will be
added to.
m_CustomizeDialog.SetDouble
ClickDestination(axToolbarC
ontrol1);

//Set the Customize dialog


box events.
startDialogE = new
ICustomizeDialogEvents_OnSt
artDialogEventHandler
(OnStartDialog);
((ICustomizeDialogEvents_Ev
ent)m_CustomizeDialog).OnSt
artDialog +=
startDialogE;
closeDialogE = new
ICustomizeDialogEvents_OnCl
oseDialogEventHandler
(OnCloseDialog);
((ICustomizeDialogEvents_Ev

ent)m_CustomizeDialog).OnCl
oseDialog +=
closeDialogE;
}
Call the CreateCustomizeDialog function from the
beginning of the Form_Load event. See the following
code example:
[C#]

privatevoid
MapViewer_Load(object
sender, EventArgs e)
{
//Create the Customize
dialog box for the
ToolbarControl.
CreateCustomizeDialog();

//Create the symbol used on


the MapControl.
}
Add a check box to the form, name
it chkCustomize and give it the caption of Customize.
4.

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.

5.

Add the following code to the chkCustomize_CheckedChanged event:

[C#]

privatevoid
chkCustomize_CheckedChanged
(object sender, EventArgs
e)

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

ontrol1.hWnd)
EndIf
EndSub
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#]

privatevoid OnStartDialog()
{
axToolbarControl1.Customize
= true;
}

privatevoid OnCloseDialog()

{
axToolbarControl1.Customize
= false;
chkCustomize.Checked =
false;
}
Build and run the application. Check the
Customize control to put the ToolbarControl into
customize mode and to open the Customize dialog
box.
8.

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#]

privatevoid
SaveToolbarControlItems(str
ing filePath)
{
//Create a
MemoryBlobStream.
IBlobStream blobStream =
newMemoryBlobStreamClass();
//Get the IStream
interface.
IStream stream =
blobStream;
//Save the ToolbarControl
into the stream.
axToolbarControl1.SaveItems
(stream);
//Save the stream to a
file.
blobStream.SaveToFile(fileP
ath);
}

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#]

privatevoid
LoadToolbarControlItems(str
ing filePath)
{
//Create a
MemoryBlobStream.
IBlobStream blobStream =
newMemoryBlobStreamClass();
//Get the IStream
interface.
IStream stream =
blobStream;
//Load the stream from the
file.
blobStream.LoadFromFile(fil
ePath);
//Load the stream into the
ToolbarControl.
axToolbarControl1.LoadItems
(stream);
}
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#]

privatevoid
MapViewer_FormClosing(objec
t 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(fil
ePath);
}
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(file
Path))
LoadToolbarControlItems(fil
ePath);
else
{
//Add generic commands.
axToolbarControl1.AddItem("
esriControls.ControlsOpenDo
cCommand", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsAddDat
aCommand", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add page layout
navigation commands.
axToolbarControl1.AddItem("
esriControls.ControlsPageZo
omInTool", - 1, - 1,
true, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsPageZo
omOutTool", - 1, - 1,

false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsPagePa
nTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsPageZo
omWholePageCommand", 1, - 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add map navigation
commands.
axToolbarControl1.AddItem("
esriControls.ControlsMapZoo
mInTool", - 1, - 1,
true, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapZoo
mOutTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapPan
Tool", - 1, - 1,

false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapFul
lExtentCommand", - 1,
- 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZo
omToLastExtentBackCommand",
- 1, - 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem(
"esriControls.ControlsMapZo
omToLastExtentForwardComman
d", - 1, - 1, false,
0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add map inquiry commands.
axToolbarControl1.AddItem("
esriControls.ControlsMapIde
ntifyTool", - 1, - 1,
true, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapFin
dCommand", - 1, - 1,

false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
axToolbarControl1.AddItem("
esriControls.ControlsMapMea
sureTool", - 1, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
//Add custom AddDateTool.
axToolbarControl1.AddItem("
Commands.AddDateTool", 1, - 1, false, 0,
esriCommandStyles.esriComma
ndStyleIconAndText);

//Create a new
ToolbarPalette.
IToolbarPalette
toolbarPalette =
newToolbarPaletteClass();
//Add commands and tools to
the ToolbarPalette.
toolbarPalette.AddItem("esr
iControls.ControlsNewMarker
Tool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewLineTo
ol", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewCircle
Tool", - 1, - 1);

toolbarPalette.AddItem("esr
iControls.ControlsNewEllips
eTool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewRectan
gleTool", - 1, - 1);
toolbarPalette.AddItem("esr
iControls.ControlsNewPolygo
nTool", - 1, - 1);
//Add the ToolbarPalette to
the ToolbarControl.
axToolbarControl1.AddItem(t
oolbarPalette, 0, - 1,
false, 0,
esriCommandStyles.esriComma
ndStyleIconOnly);
}
Build and run the application and customize the
ToolbarControl.
6.

Stop running the application.

7.

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#]

privatevoid
printToolStripMenuItem_Clic
k(object sender, EventArgs
e)
{
//Exit if there is no
system default printer.
if
(axPageLayoutControl1.Print
er == null)
{
MessageBox.Show("Unable to
print!", "No default
printer");
return ;
}

//Set printer papers


orientation to that of the
page.
axPageLayoutControl1.Printe
r.Paper.Orientation =
axPageLayoutControl1.Page.O
rientation;
//Scale to the page.
axPageLayoutControl1.Page.P
ageToPrinterMapping =

esriPageToPrinterMapping.es
riPageMappingScale;
//Send the page layout to
the printer.
axPageLayoutControl1.PrintP
ageLayout();
}
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.

Вам также может понравиться