arcgis坐标系统转换,做一个医院地图寻路,已加入道路图,怎么自己绘制医院坐标地图??

ArcGIS&Engine10.0轻松入门级教程——创建一个ArcGIS&Engine桌面应用程序
这个例子将引导您创建第一个简单的地图显示程序,并添加基本的缩放和漫游功能。如果您之前没有接触过ArcGIS
Engine的开发,那么这个例子是您迈入ArcGIS
Engine二次开发大门的极好例子,如果您之前没有接触过C#.NET,也无需担心,这个例子将从零开始引导您一步一步完成任务。
1创建一个新的工程
首先打开Microsoft Visual Studio
2008,点击菜单栏中的“文件”—&“新建”—&“项目”,在弹出的对话框中选择新建一个Visual
C#的Windows应用程序,之后更改项目名称为“ZZUMap”,更改文件的路径为个人实习文件夹,点击“确定”即可。
选中项目“ZZUMap”中的窗体“Form1”,修改其Name属性为“MainForm”,Text属性为“ZZUMap”。
选择工具箱中的“菜单和工具栏|MenuStrip”,将其拖入窗体。
选择工具箱中的“ArcGIS Windows
Forms”节,将“ToolbarControl”控件拖入窗体,并将其属性中的Dock设置为Top。
选择工具箱中的“菜单和工具栏|StatusStrip”,将其拖入到窗体。
选择工具箱中的“容器|SplitContainer”容器拖入窗体,并将其属性中的Dock设置为Fill。
再将“容器|SplitContainer”容器拖入Panel1,设置为水平拆分方向,并将其属性中的Dock设置为Fill。
将TabControl控件拖入Panel1,将Alignment属性设置为Bottom,Dock属性设置为Fill。点击TabPages属性右边的按钮,弹出TabPage集合编辑器,将tabPage1的Name设置为tabPageLayer,Text设置为图层,将tabPage2的Name设置为tabPageProperty,Text设置为属性。
选择“图层”选项卡,拖入TOCControl控件,设置Dock属性为Fill。
选择“属性”选项卡,拖入PropertyGrid设置Dock属性为Fill。
拖入TabControl控件到第一个SplitContainer容器的Panel2,设置Dock属性为Fill。并上述类似的方法,将两个选项卡的Name和Text分别设置为:(tabPageMap、地图),(tabPageLayout,制版)。
选择“地图”选项卡,拖入MapControl控件,设置Dock属性为Fill。
选择“制版”选项卡,拖入PageLayoutControl控件,设置Dock属性为Fill。
将MapControl控件拖入第二个SplitContainer容器的Panel2,设置Dock属性为Fill。
最后将LicenseControl控件拖入到窗体的任意地方。
按F5编译运行还不能运行,因为就很可能是你的ArcEngine10.0没有许可,因为我的就是这个情况,所以会报错,重新授权下就OK了,解决方法:打开program.cs
把ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);
这句放到Application.SetCompatibleTextRenderingDefault(false);和Application.Run(new
Form1());之间。
通过以上步骤添加的控件还只是单独存在,而我们的程序需要各控件间协同工作,因此要进行控件绑定。
分别右击ToolbarControl、TOCControl控件,将Buddy设置为axMapControl1,如下图所示。
这样,工具条和图层控件就与地图控件关联了。
此时,工具条中还没有任何工具,添加的方法也很简单。右击ToolbarControl,选择“属性|Items”,点击Add,选择Commands选项卡中的Generic,双击Open、SaveAs、Redo、Undo即可将相应工具添加到工具条。
常见的工具有:
Map Navigation中的导航工具,Map Inquiry中的查询工具,Feature
Selection中的选择工具,你可以根据需要酌情添加工具,如下图。
目前为止运行程序界面如下:
在设计视图中,单击菜单栏,会出现“请在此处键入”的提示,单击提示就可以键入菜单名称,如“文件”,再单击“文件”,即可输入其下拉子菜单。
每创建一个菜单,请在其属性面板中设置 Name 属性,而且不要为中文,因此 Name
值将是此菜单响应函数的函数名的一部分,带中文的函数名,总是不好吧。我们将添加新建( New )、打开( Open )、添加数据(
AddData )、保存( Save )、另存为( SaveAs )、退出( Exit )这些菜单,()内为相应的 Name
你可以在属性面板中的 Text 属性中,把菜单名设置为中英文形式,如“打开 O pen ”,带下划线的
O 表示此项菜单的快捷键是字母 O ,设置方法是在相应字母前加上“ & ”字符,如“打开
&Open ”。但这种快捷键只在打开此下拉菜单时才有效,即当你单击“文件”菜单弹出下拉菜单时,按下字母
O 就可以定位到“打开”菜单。
还有一种在程序运行时都有效的全局快捷键,可以在属性面板中的“ ShortCutKeys
”中设置。
你还可以在属性面板中的 Image 属性中设置你喜欢的菜单图标。单击 Image
那一行右边的按钮,弹出如下菜单。选择“项目资源文件”,再单击导入就可以选择你的图标了。
最终效果如下所示。
注意,在解决方案面板中,选中刚才添加的所有图标,在其属性面板中将生成操作设置为“嵌入的资源”,这一点很重要!菜单的实现参考ArcEngine自带的模板MapControl
Application中的菜单实现。先新建一个类,命名为CreateNewDocument.cs,添加引用:
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
using ESRI.ArcGIS.SystemUI;
using System.Windows.F
在构造函数中继承类:
public class CreateNewDocument : BaseCommand;
然后将以下代码复制覆盖到类CreateNewDocument中
private IHookHelper m_hookHelper =
//constructor
public CreateNewDocument()
//update the base properties
base.m_category = ".NET Application";
base.m_caption = "NewDocument";
base.m_message = "Create a new map";
base.m_toolTip = "Create a new map";
base.m_name = "DotNetTemplate_NewDocumentCommand";
#region Overridden Class Methods
/// &summary&
/// Occurs when this command is created
/// &/summary&
/// &param name="hook"&Instance of
the application&/param&
public override void OnCreate(object hook)
if (m_hookHelper == null)
m_hookHelper = new HookHelperClass();
m_hookHelper.Hook =
/// &summary&
/// Occurs when this command is clicked
/// &/summary&
public override void OnClick()
IMapControl3 mapControl =
//get the MapControl from the hook in case the
container is a ToolbarControl
if (m_hookHelper.Hook is IToolbarControl)
mapControl =
(IMapControl3)((IToolbarControl)m_hookHelper.Hook).B
//In case the container is MapControl
else if (m_hookHelper.Hook is IMapControl3)
mapControl = (IMapControl3)m_hookHelper.H
MessageBox.Show("Active control must be MapControl!", "Warning",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
//check to see if there is an active edit session
and whether edits have been made
IEngineEditor engineEditor = new EngineEditorClass();
if ((engineEditor.EditState ==
esriEngineEditState.esriEngineStateEditing)
&& (engineEditor.HasEdits() ==
result = MessageBox.Show("Would you like to save your edits", "Save
Edits", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question);
switch (result)
case DialogResult.Cancel:
case DialogResult.No:
engineEditor.StopEditing(false);
case DialogResult.Yes:
engineEditor.StopEditing(true);
//allow the user to save the current document
DialogResult res = MessageBox.Show("Would you like to save the
current document?", "AoView", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (res == DialogResult.Yes)
//launch the save command
ICommand command = new ControlsSaveAsDocCommandClass();
command.OnCreate(m_hookHelper.Hook);
command.OnClick();
//create a new Map
IMap map = new MapClass();
map.Name = "Map";
//assign the new map to the MapControl
mapControl.DocumentFilename = string.E
mapControl.Map =
#endregion
然后定义指针和变量:
privE ate ESRI.ArcGIS.Controls.IMapControl4
m_mapControl =
private ESRI.ArcGIS.Controls.IPageLayoutControl3
m_pageLayoutControl =
private string m_mapDocumentName = string.
最后在菜单按钮的事件中填入以下代码:
private void AddData_Click(object sender, EventArgs
int currentLayerCount = this.axMapControl1.LayerC
ICommand pCommand = new
ControlsAddDataCommandClass();
pCommand.OnCreate(this.axMapControl1.Object);
pCommand.OnClick();
private void Save_Click(object sender, EventArgs
//execute Save Document command
if (m_mapControl.CheckMxFile(m_mapDocumentName))
//create a new instance of a MapDocument
IMapDocument mapDoc = new MapDocumentClass();
mapDoc.Open(m_mapDocumentName, string.Empty);
//Make sure that the MapDocument is not
if (mapDoc.get_IsReadOnly(m_mapDocumentName))
MessageBox.Show("Map document is read only!");
mapDoc.Close();
private void SavaAs_Click(object sender, EventArgs
//execute SaveAs Document command
ICommand command = new ControlsSaveAsDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
private void Open_Click(object sender, EventArgs
//execute Open Document command
ICommand command = new ControlsOpenDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
private void Exit_Click(object sender, EventArgs
//exit the application
Application.Exit();
private void New_Click(object sender, EventArgs
//execute New Document command
ICommand command = new CreateNewDocument();
command.OnCreate(m_mapControl.Object);
command.OnClick();
6PageLayout与MapControl联动
在ArcMap程序中,数据视图和布局视图中的数据改变是实时互动的,那是因为它们本来就是在处理同一份数据。将axMapControl1中的Map拷贝到axPageLayoutControl1代码如下:
private voidCopyAndOverwriteMap()
//Get IObjectCopy interface
IObjectCopy objectCopy =newObjectCopyClass();
//Get IUnknown interface (map to copy)
object toCopyMap = axMapControl1.M
//Get IUnknown interface (copied map)
object copiedMap = objectCopy.Copy(toCopyMap);
//Get IUnknown interface (map to overwrite)
object toOverwriteMap =
axPageLayoutControl1.ActiveView.FocusM
//Overwrite the PageLayoutControl's map
objectCopy.Overwrite(copiedMap,reftoOverwriteMap);
要实现axPageLayoutControl1中的数据与axMapControl1中的数据同步,需要在axMapControl1的以下事件中写入相应的代码:
voidaxMapControl1_OnMapReplaced(objectsender,
ESRI.ArcGIS.MapControl.IMapControlEvents2_OnMapReplacedEvent e)
CopyAndOverwriteMap();
voidaxMapControl1_OnAfterScreenDraw(objectsender,
ESRI.ArcGIS.MapControl.IMapControlEvents2_OnAfterScreenDrawEvent
//Get IActiveView interface
IActiveView activeView = (IActiveView)
axPageLayoutControl1.ActiveView.FocusM
//Get IDisplayTransformation interface
IDisplayTransformation displayTransformation =
activeView.ScreenDisplay.DisplayT
//Set the visible extent of the focus map
displayTransformation.VisibleBounds =
axMapControl1.E
axPageLayoutControl1.ActiveView.Refresh();
//根据MapControl的视图范围,确定PageLayoutControl的视图范围
CopyAndOverwriteMap();
voidaxMapControl1_OnViewRefreshed(objectsender,
ESRI.ArcGIS.MapControl.IMapControlEvents2_OnViewRefreshedEvent
//axTOCControl1.Update ();
CopyAndOverwriteMap();
运行但是axTOCControl控件图层不显示,这是因为还要设置SetBuddyControl,ToolBarControl控件中同样要设置,只需要在在主窗口Load函数中添加下面一句话就可以了
private void MainForm_Load(object sender, EventArgs
axTOCControl1.SetBuddyControl(axMapControl1);//ADD
axToolbarControl1.SetBuddyControl(m_mapControl);
7鹰眼的实现
鹰眼用来显示主窗体当前视图范围在全景视图中的位置,在ArcMap中使用一个线框在鹰眼视图中标识。当主视图中的视图范围改变时,鹰眼中的线框随之改变,当拖动鹰眼视图中的红线框时,主视图中的视图范围也随之改变。
下面开始实现鹰眼功能,添加using ESRI.ArcGIS.Carto、using
ESRI.ArcGIS.Geometry、
ESRI.ArcGIS.Display三个引用。首先在axMapControl1中视图范围改变时鹰眼窗体要做出对应的响应,即绘制线框并显示,在OnExtentUpdated事件中添加代码如下:
private void axMapControl1_OnExtentUpdated (object
ESRI.ArcGIS.Controls.IMapControlEvents2_OnExtentUpdatedEvent e)
//创建鹰眼中线框
IEnvelope pEnv = (IEnvelope)e.newE
IRectangleElement pRectangleEle = new
RectangleElementClass();
IElement pEle = pRectangleEle as IE
pEle.Geometry = pE
//设置线框的边线对象,包括颜色和线宽
IRgbColor pColor = new RgbColorClass();
pColor.Red = 255;
pColor.Green = 0;
pColor.Blue = 0;
pColor.Transparency = 255;
// 产生一个线符号对象
ILineSymbol pOutline = new
SimpleLineSymbolClass();
pOutline.Width = 2;
pOutline.Color = pC
// 设置颜色属性
pColor.Red = 255;
pColor.Green = 0;
pColor.Blue = 0;
pColor.Transparency = 0;
// 设置线框填充符号的属性
IFillSymbol pFillSymbol = new
SimpleFillSymbolClass();
pFillSymbol.Color = pC
pFillSymbol.Outline = pO
IFillShapeElement pFillShapeEle = pEle as
IFillShapeE
pFillShapeEle.Symbol = pFillS
// 得到鹰眼视图中的图形元素容器
IGraphicsContainer pGra = axMapControl2.Map as
IGraphicsC
IActiveView pAv = pGra as IActiveV
// 在绘制前,清除 axMapControl2 中的任何图形元素
pGra.DeleteAllElements();
// 鹰眼视图中添加线框
pGra.AddElement((IElement)pFillShapeEle, 0);
// 刷新鹰眼
pAv.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null,
当鼠标点击鹰眼窗体时,主窗体Extent随之改变。在axMapControl2的OnMouseDown事件中添加代码如下:
private void axMapControl2_OnMouseDown(object
sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent
if (this.axMapControl2.Map.LayerCount != 0)
// 按下鼠标左键移动矩形框
if (e.button == 1)
IPoint pPoint = new PointClass();
pPoint.PutCoords(e.mapX, e.mapY);
IEnvelope pEnvelope =
this.axMapControl1.E
pEnvelope.CenterAt(pPoint);
this.axMapControl1.Extent = pE
this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,
null, null);
// 按下鼠标右键绘制矩形框
else if (e.button == 2)
IEnvelope pEnvelop =
this.axMapControl2.TrackRectangle();
this.axMapControl1.Extent = pE
this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,
null, null);
当鼠标在鹰眼窗体移动时,主窗体Extent随之改变。在axMapControl2的OnMouseMove事件中添加代码如下:
private void axMapControl2_OnMouseMove(object
sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseMoveEvent
// 如果不是左键按下就直接返回
if (e.button != 1)
IPoint pPoint = new PointClass();
pPoint.PutCoords(e.mapX, e.mapY);
this.axMapControl1.CenterAt(pPoint);
this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,
null, null);
下面代码用于实现axMapControl2与axMapControl1的数据的同步更新,获取主视图中视图范围最大的图层作为鹰眼中的视图。这个更新由两部分组成,一个是对axMapControl1添加地图文档(mxd文件)的响应,通过axMapControl1的OnMapReplace事件实现,一个是对axMapControl1添加单个图层的响应,通过axMapControl1的OnFullExtentUpdated事件实现。我们获取主视图中的视图范围最大的图层写成一个独立的函数,方便调用。
private ILayer GetOverviewLayer(IMap map)
//获取主视图的第一个图层
ILayer pLayer = map.get_Layer(0);
//遍历其他图层,并比较视图范围的宽度,返回宽度最大的图层
ILayer pTempLayer =
for (int i = 1; i &
map.LayerCi++ )
pTempLayer = map.get_Layer(i);
if (pLayer.AreaOfInterest.Width &
pTempLayer.AreaOfInterest.Width)
pLayer = pTempL
然后在axMapControl1的OnMapReplaced事件中调用。
private void axMapControl1_OnMapReplaced(object
sender, IMapControlEvents2_OnMapReplacedEvent e)
//获取鹰眼图层
this.axMapControl2.AddLayer(this.GetOverviewLayer(this.axMapControl1.Map));
// 设置 MapControl 显示范围至数据的全局范围
this.axMapControl2.Extent =
this.axMapControl1.FullE
// 刷新鹰眼控件地图
this.axMapControl2.Refresh();
在axMapControl1的OnFullExtentUpdated添加代码,用于实现在主视图添加图层时,实现对鹰眼视图的更新。代码如下:
private void
axMapControl1_OnFullExtentUpdated(object sender,
ESRI.ArcGIS.Controls.IMapControlEvents2_OnFullExtentUpdatedEvent
//获取鹰眼图层
this.axMapControl2.AddLayer(this.GetOverviewLayer(this.axMapControl1.Map));
// 设置 MapControl 显示范围至数据的全局范围
this.axMapControl2.Extent =
this.axMapControl1.FullE
// 刷新鹰眼控件地图
this.axMapControl2.Refresh();
this.axMapControl2.Map = new MapClass();
// 添加主地图控件中的所有图层到鹰眼控件中
for (int i = 1; i &=
this.axMapControl1.LayerC i++)
this.axMapControl2.AddLayer(this.axMapControl1.get_Layer(this.axMapControl1.LayerCount
// 设置 MapControl 显示范围至数据的全局范围
this.axMapControl2.Extent =
this.axMapControl1.FullE
// 刷新鹰眼控件地图
this.axMapControl2.Refresh();
运行程序,添加地图数据,可以在主视图进行相关操作,鹰眼视图同步响应,在鹰眼视图可以移动红线框可以同步更新主视图的视图范围,在鹰眼视图单击右键拉框可以重新绘制红线框,效果如下:
8状态栏的实现
应用程序的状态栏一般用来显示程序的当前状态,当前所使用的工具。 GIS
应用程序一般也在状态栏显示当前光标的坐标、比例尺等信息。学习完本讲内容,您将学会状态栏编程的基本方法,并且能够在我们的程序的状态栏中添加且显示以下信息:
当前所用工具信息
当前比例尺
在设计视图中,点击窗体中的状态栏,在其属性面板中找到“ Items ”项,单击其右边的按钮,在下拉框中选择“ StatusLabel
”,单击“添加按钮”,依次添加四个 StatusLabel ,依次修改属性参数如下表所示:
Spring 属性
MessageLabel
当前所用工具信息
ScaleLabel
当前比例尺
CoordinateLabel
设置好之后如下图所示:
Spring 属性表示可以按状态栏剩余空间自动伸缩。所以加入 Blank
项目,只是为了占个位子,以达到 ScaleLabel 和 CoordinateLabel 项目右对齐而 MessageLabel
项目左对齐的目的。
首先添加 axToolbarControl1 的 OnMouseMove 事件 (
相信大家看了以上的教程,已经知道怎么添加事件了吧,还不知道的建议再温习下前几讲的内容 ) 。在其事件响应函数代码如下:
private void axToolbarControl1_OnMouseMove(object
sender, IToolbarControlEvents_OnMouseMoveEvent e)
// 取得鼠标所在工具的索引号
int index = axToolbarControl1.HitTest(e.x, e.y,
if (index != -1)
// 取得鼠标所在工具的 ToolbarItem
IToolbarItem toolbarItem =
axToolbarControl1.GetItem(index);
// 设置状态栏信息
MessageLabel.Text =
MessageLabel.Text = " 就绪 ";
添加 axMapControl1 的 OnMouseMove 事件,其代码如下:
private void axMapControl1_OnMouseMove(object
sender, IMapControlEvents2_OnMouseMoveEvent e)
// 显示当前比例尺
ScaleLabel.Text = " 比例尺 1:" +
((long)this.axMapControl1.MapScale).ToString();
显示当前坐标也是 axMapControl1 的 OnMouseMove 事件中响应,故只要在
axMapControl1_OnMouseMove 函数中添加如下代码即可:
// 显示当前坐标
CoordinateLabel.Text = " 当前坐标 X = " + e.mapX.ToString() + " Y = " +
e.mapY.ToString() + " " + this.axMapControl1.MapU
按 F5 编译运行,可以看到,我们的程序已经能够正常工作了。但是细心的你可能会发现,当前坐标的后面的坐标单位为“
esriUnknownUnits ”或“ esriMeters ”之类,即系统在正常单位的前面加上了“ esri
”,追求完美的我们自然看得不舒服。那就进行简单的替换吧。
首先定义个全局坐标单位变量 sMapUnits ,如下所示:
private string sMapU
再 Form1_Load 函数中进行初始化:
sMapUnits = "Unknown";
添加 axMapControl1 控件的 OnMouseMove
事件,在事件响应函数中进行坐标单位替换,并将this.axMapControl1.MapUnits替换为sMapUnits,代码如下:
esriUnits mapUnits = axMapControl1.MapU
switch (mapUnits)
case esriUnits.esriCentimeters:
sMapUnits = "Centimeters";
case esriUnits.esriDecimalDegrees:
sMapUnits = "Decimal Degrees";
case esriUnits.esriDecimeters:
sMapUnits = "Decimeters";
case esriUnits.esriFeet:
sMapUnits = "Feet";
case esriUnits.esriInches:
sMapUnits = "Inches";
case esriUnits.esriKilometers:
sMapUnits = "Kilometers";
case esriUnits.esriMeters:
sMapUnits = "Meters";
case esriUnits.esriMiles:
sMapUnits = "Miles";
case esriUnits.esriMillimeters:
sMapUnits = "Millimeters";
case esriUnits.esriNauticalMiles:
sMapUnits = "NauticalMiles";
case esriUnits.esriPoints:
sMapUnits = "Points";
case esriUnits.esriUnknownUnits:
sMapUnits = "Unknown";
case esriUnits.esriYards:
sMapUnits = "Yards";
按 F5 编译运行程序。如果你足够细心的话,相信你已经成功了!
9右键的实现
在AE开发中,右键菜单有两种实现方式,一是使用VS2005自带的ContextMenuStrip控件,二是用AE封装的IToolbarMenu接口。相比较而言,后者更为简单实用,本文采用后者的实现方法。由于在TOCControl控件右键菜单上要查询属性表,所以先新建一个普通类,命名为FrmAttribute,并添加以下代码:
public DataGridView GetDataGrid
return dataGridView1;
在Form1类里面添加如下变量的定义:
//右键菜单
private ITOCControl2 m_tocC
private IToolbarMenu m_menuM
private IToolbarMenu m_menuL
private FrmAttribute frmOpenAttributeT
当然,添加菜单项之前,必须实现相应命令或工具。这里的命令或工具可以AE内置的也可以是自定义的。AE内置了许多可以直接调用的常用命令和工具,如ControlsAddDataCommandClass,在ESRI.ArcGIS.Controls命名空间中,大家可以对象浏览器中查看。当然,这里也可以直接调用AE内置的菜单,如ControlsFeatureSelectionMenu。另外,本讲也实现三自定义命令,以做示范。它们分别为图层可视控制命令(用于控制图层显示与否)、移除图层和放大到整个图层命令。实现方法也很简单,就是右击ZZUMap项目,选择“添加|类”,选择C#普通的类模板,用以下代码覆盖系统自己生成的所有代码。
LayerSelectable类代码:
using System.Collections.G
using System.T
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
using ESRI.ArcGIS.SystemUI;
namespace ZZUMap
public sealed class LayerSelectable : BaseCommand,
ICommandSubType
private IMapControl3 m_mapC
private long m_subT
public LayerSelectable()
public override void OnClick()
IFeatureLayer layer =
(IFeatureLayer)m_mapControl.CustomP
if (m_subType == 1) layer.Selectable =
if (m_subType == 2) layer.Selectable =
public override void OnCreate(object hook)
m_mapControl = (IMapControl3)
public override bool Enabled
ILayer layer = (ILayer)m_mapControl.CustomP
if (layer is IFeatureLayer)
IFeatureLayer featureLayer = (IFeatureLayer)
if (m_subType == 1) return !featureLayer.S
else return featureLayer.S
public int GetCount()
public void SetSubType(int SubType)
m_subType = SubT
public override string Caption
if (m_subType == 1) return "图层可选";
else return "图层不可选";
LayerVisibility类代码
using System.Collections.G
using System.T
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
using ESRI.ArcGIS.SystemUI;
namespace ZZUMap
public sealed class LayerVisibility : BaseCommand,
ICommandSubType
private IHookHelper m_hookHelper = new HookHelperClass();
private long m_subT
public LayerVisibility()
public override void OnClick()
for (int i = 0; i &=
m_hookHelper.FocusMap.LayerCount - 1; i++)
if (m_subType == 1) m_hookHelper.FocusMap.get_Layer(i).Visible =
if (m_subType == 2) m_hookHelper.FocusMap.get_Layer(i).Visible =
m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,
null, null);
public override void OnCreate(object hook)
m_hookHelper.Hook =
public int GetCount()
public void SetSubType(int SubType)
m_subType = SubT
public override string Caption
if (m_subType == 1) return "Turn All Layers On";
else return "Turn All Layers Off";
public override bool Enabled
bool enabled =
if (m_subType == 1)
for (i = 0; i &= m_hookHelper.FocusMap.LayerCount -
if (m_hookHelper.ActiveView.FocusMap.get_Layer(i).Visible ==
for (i = 0; i &= m_hookHelper.FocusMap.LayerCount -
if (m_hookHelper.ActiveView.FocusMap.get_Layer(i).Visible ==
OpenAttributeTable类代码:
using System.Collections.G
using System.T
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
using ESRI.ArcGIS.CartoUI;
using System.D
using System.C
using ESRI.ArcGIS.G
using System.IO;
using ESRI.ArcGIS.GeoDatabaseUI;
using ESRI.ArcGIS.D
using System.Windows.F
namespace ZZUMap
public class OpenAttributeTable : BaseCommand
private IMapControl3 m_mapC
private IHookHelper m_hookHelper = new HookHelperClass();
private FrmAttribute frmOpenAttributeT
public OpenAttributeTable()
base.m_category = ""; //localizable text
base.m_caption = " 打开属性表"; //localizable text
base.m_message = "This should work in
ArcMap/MapControl/PageLayoutControl"; //localizable text
base.m_toolTip = ""; //localizable text
base.m_name = ""; //unique id, non-localizable (e.g.
"MyCategory_MyCommand")
#region Overriden Class Methods
public override void OnClick()
frmOpenAttributeTable = new FrmAttribute();
DataGridView dataG
dataGrid = frmOpenAttributeTable.GetDataG
frmOpenAttributeTable.Show();
frmOpenAttributeTable.TopMost =
base.OnClick();
IFeatureLayer pFeatLyr =
(IFeatureLayer)m_mapControl.CustomP
//查询ILayerFields接口
ILayerFields pFeatLyrFields = (ILayerFields)pFeatL
IFeatureClass pFeatCls = pFeatLyr.FeatureC
frmOpenAttributeTable.Text = pFeatLyr.Name + "--属性表";
DataSet myDataset = new DataSet("Test");
DataTable pTable = new DataTable(pFeatLyr.Name);
for (int n = 0; n & pFeatLyrFields.FieldCount - 1;
DataColumn pTableCol = new
DataColumn(pFeatLyrFields.get_Field(n).Name);
pTable.Columns.Add(pTableCol);
pTableCol =
IFeatureCursor pFeatCursor = pFeatCls.Search(null, false);
IFeature pFeat = pFeatCursor.NextFeature();
while (pFeat != null)
DataRow pTableRow = pTable.NewRow();
for (int i = 0; i & pFeatLyrFields.FieldCount - 1;
if (pFeatLyrFields.FindField(pFeatCls.ShapeFieldName) == i)
pTableRow[i] = pFeatCls.ShapeType.ToString();
pTableRow[i] = pFeat.get_Value(i).ToString();
pTable.Rows.Add(pTableRow);
pFeat = pFeatCursor.NextFeature();
myDataset.Tables.Add(pTable);
dataGrid.DataSource = myD
dataGrid.DataMember = pFeatLyr.N
#endregion
public override void OnCreate(object hook)
m_mapControl = (IMapControl3)
throw new NotImplementedException();
RemoveLayer类代码:
using System.Collections.G
using System.T
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
namespace ZZUMap
public sealed class RemoveLayer : BaseCommand
private IMapControl3 m_
public RemoveLayer()
base.m_caption = "移除图层";
public override void OnCreate(object hook)
m_mapcontrol = (IMapControl3)
throw new NotImplementedException();
public override void OnClick()
////base.OnClick();
ILayer layer = (ILayer)m_mapcontrol.CustomP
m_mapcontrol.Map.DeleteLayer(layer);
ScaleThresholds类代码:
using System.Collections.G
using System.T
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
using ESRI.ArcGIS.SystemUI;
namespace ZZUMap
public class ScaleThresholds : BaseCommand,
ICommandSubType
private IMapControl3 m_mapC
private long m_subT
public ScaleThresholds()
public override void OnClick()
ILayer layer = (ILayer)m_mapControl.CustomP
if (m_subType == 1) layer.MaximumScale =
m_mapControl.MapS
if (m_subType == 2) layer.MinimumScale =
m_mapControl.MapS
if (m_subType == 3)
layer.MaximumScale = 0;
layer.MinimumScale = 0;
m_mapControl.Refresh(esriViewDrawPhase.esriViewGeography, null,
public override void OnCreate(object hook)
m_mapControl = (IMapControl3)
public int GetCount()
public void SetSubType(int SubType)
m_subType = SubT
public override string Caption
if (m_subType == 1) return "图层最大尺寸";
else if (m_subType == 2) return "图层最小尺寸";
else return "删除图层比例阈值";
public override bool Enabled
bool enabled =
ILayer layer = (ILayer)m_mapControl.CustomP
if (m_subType == 3)
if ((layer.MaximumScale == 0) & (layer.MinimumScale
== 0)) enabled =
ZoomToLayer类代码:
using System.Collections.G
using System.T
using ESRI.ArcGIS.ADF.BaseC
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
namespace ZZUMap
public sealed class ZoomToLayer : BaseCommand
private IMapControl3 m_mapC
public ZoomToLayer()
base.m_caption = "全屏缩放";
public override void OnClick()
ILayer layer = (ILayer)m_mapControl.CustomP
m_mapControl.Extent = layer.AreaOfI
public override void OnCreate(object hook)
m_mapControl = (IMapControl3)
在Form1_Load函数进行初始化,即菜单的创建:
//右键菜单
private ITOCControl2 m_tocControl =
private IMapControl3 m_mapControl =
private FrmAttribute frmOpenAttributeTable =
private ToolbarMenuClass m_menuMap =
private ToolbarMenuClass m_menuLayer =
&&private void
mainfrm_Load(object sender, EventArgs e)
&&&&&&&&&&&&m_tocControl
= (ITOCControl2)TOC.O
&&&&&&&&&&&
m_mapControl = (IMapControl3)Maplayer.O
&&&&&&&&&&&
frmOpenAttributeTable = new FrmAttribute();
&&&&&&&&&&&
m_menuMap = new ToolbarMenuClass();
&&&&&&&&&&&
m_menuMap.AddItem(new LayerVisibility(), 1, 0, false,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuMap.AddItem(new LayerVisibility(), 2, 1, false,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuMap.AddSubMenu("esriControls.ControlsFeatureSelectionMenu",
&&&&&&&&&&&
m_menuLayer = new ToolbarMenuClass();
&&&&&&&&&&&
m_menuLayer.AddItem(new RemoveLayer(), -1, 0, false,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.AddItem(new ScaleThresholds(), 1, 1, true,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.AddItem(new ScaleThresholds(), 2, 2, false,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.AddItem(new ScaleThresholds(), 3, 3, false,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.AddItem(new LayerSelectable(), 1, 4, true,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.AddItem(new LayerSelectable(), 2, 5, false,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.AddItem(new ZoomToLayer(), -1, 6, true,
esriCommandStyles.esriCommandStyleTextOnly);
&&&&&&&&&&&
m_menuLayer.SetHook(m_mapControl);
&&&&&&&&&&&
m_menuMap.SetHook(m_mapControl);
这样就完成了TOCControl控件的右键菜单功能,接下来做地图右键菜单功能的开发。先添加一个contextMenuStrip控件,如下图添加子菜单:
各个菜单函数如下:
private void 全图ToolStripMenuItem_Click(object
sender, EventArgs e)
ICommand pCommand = new ControlsMapFullExtentCommandClass();
pCommand.OnCreate(this.axMapControl1.Object);
pCommand.OnClick();
private void 前一视图ToolStripMenuItem_Click(object
sender, EventArgs e)
ICommand pCommand = new
ControlsMapZoomToLastExtentBackCommandClass();
pCommand.OnCreate(this.axMapControl1.Object);
pCommand.OnClick();
private void 后一视图ToolStripMenuItem_Click(object
sender, EventArgs e)
ICommand pCommand = new
ControlsMapZoomToLastExtentForwardCommandClass();
pCommand.OnCreate(this.axMapControl1.Object);
pCommand.OnClick();
private void 局部放大ToolStripMenuItem_Click(object
sender, EventArgs e)
ICommand pCommand = new ControlsMapZoomInFixedCommandClass();
pCommand.OnCreate(this.axMapControl1.Object);
pCommand.OnClick();
private void 局部缩小ToolStripMenuItem_Click(object
sender, EventArgs e)
ICommand pCommand = new
ControlsMapZoomOutFixedCommandClass();
pCommand.OnCreate(this.axMapControl1.Object);
pCommand.OnClick();
private void 居中ToolStripMenuItem_Click(object
sender, EventArgs e)
this.axMapControl1.CenterAt(this.mapRightClickPoint);
private void 选择要素ToolStripMenuItem_Click(object
sender, EventArgs e)
IMap pMap = this.axMapControl1.M
ISelectionEnvironment pSelectionEnvironment = new
SelectionEnvironmentClass();
pSelectionEnvironment.LinearSearchDistance =
this.axMapControl1.ActiveView.Extent.Width / 200;
pSelectionEnvironment.PointSearchDistance =
this.axMapControl1.ActiveView.Extent.Width / 200;
pMap.SelectByShape(this.mapRightClickPoint as IGeometry, null,
this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection,
null, null);
private void 识别ToolStripMenuItem_Click(object
sender, EventArgs e)
最后在地图的MouseDown事件中添加响应事件,代码如下:
private void axMapControl1_OnMouseDown(object
sender, IMapControlEvents2_OnMouseDownEvent e)
if (e.button == 2)
this.contextMenuStrip1.Show(this.axMapControl1 as Control, new
System.Drawing.Point(e.x, e.y));
这样就完成了地图右键功能的开发。
10符号选择器的实现
新建Winodws窗体,命名为SymbolSelectorFrm,修改窗体的Text属性为“选择符号”。并添加SymboloryControl、PictureBox、Button、Label、NumericUpDown、GroupBox、ColorDialog、OpenFileDialog、ContextMenuStrip控件。控件布局如下所示:
设置相应控件的相关属性,如下表所示(空则不用修改):
在解决方案资源管理器中添加ArcGIS
Engine的ESRI.ArcGIS.Geodatabase引用,在SymbolSelectorFrm.cs文件中添加如下引用代码:
using ESRI.ArcGIS.C
using ESRI.ArcGIS.D
using ESRI.ArcGIS.esriS
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.C
using ESRI.ArcGIS.G
修改SymbolSelectorFrm的构造函数,传入图层和图例接口。代码如下:
/// &summary&
/// 构造函数,初始化全局变量
/// &/summary&
/// &param
name="tempLegendClass"&TOC图例&/param&
/// &param
name="tempLayer"&图层&/param&
public SymbolSelectorFrm(ILegendClass tempLegendClass, ILayer
tempLayer)
InitializeComponent();
this.pLegendClass = tempLegendC
this.pLayer = tempL
添加SymbolControl的SymbologyStyleClass设置函数SetFeatureClassStyle(),代码如下:
/// &summary&
初始化SymbologyControl的StyleClass,图层如果已有符号,则把符号添加到SymbologyControl中的第一个符号,并选中
/// &/summary&
/// &param
name="symbologyStyleClass"&&/param&
private void SetFeatureClassStyle(esriSymbologyStyleClass
symbologyStyleClass)
this.axSymbologyControl.StyleClass = symbologyStyleC
ISymbologyStyleClass pSymbologyStyleClass =
this.axSymbologyControl.GetStyleClass(symbologyStyleClass);
if (this.pLegendClass != null)
IStyleGalleryItem currentStyleGalleryItem = new
ServerStyleGalleryItem();
currentStyleGalleryItem.Name = "当前符号";
currentStyleGalleryItem.Item = pLegendClass.S
pSymbologyStyleClass.AddItem(currentStyleGalleryItem,0);
this.pStyleGalleryItem = currentStyleGalleryI
pSymbologyStyleClass.SelectItem(0);
添加注册表读取函数ReadRegistry(),此函数从注册表中读取ArcGIS的安装路径,代码如下:
/// &summary&
/// 从注册表中取得指定软件的路径
/// &/summary&
/// &param
name="sKey"&&/param&
&returns&&/returns&
private string ReadRegistry(string sKey)
//Open the subkey for reading
Microsoft.Win32.RegistryKey rk =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey);
if (rk == null) return "";
// Get the data from a specified item in the key.
return (string)rk.GetValue("InstallDir");
添加SymbolSelectorFrm的Load事件。根据图层类型为SymbologyControl导入相应的符号样式文件,如点、线、面,并设置控件的可视性。代码如下:
private void SymbolSelectorFrm_Load(object sender,
EventArgs e)
//-----------------------------------------------------------------------------------
//取得ArcGIS安装路径
//string sInstall = ReadRegistry("SOFTWARE\\ESRI\\ArcGIS License
Manager 10.0");
//载入ESRI.ServerStyle文件到SymbologyControl
this.axSymbologyControl.LoadStyleFile(sInstall + "");
//-----------------------------------------------------------------------------------
this.axSymbologyControl.LoadStyleFile("D:\\Program
Files\\ArcGIS\\Engine10.0\\Styles\\ESRI.ServerStyle");//这个地方有点问题,如果用以上代码也能获取到路径名,但是经调试发现执行会调用mapcontrol的onafterdraw函数(以前用于地图联动),而进入循环,无法调出符号选择器,故改为这段代码。望高手解决。
//确定图层的类型(点线面),设置好SymbologyControl的StyleClass,设置好各控件的可见性(visible)
IGeoFeatureLayer pGeoFeatureLayer = (IGeoFeatureLayer)pL
switch (((IFeatureLayer)pLayer).FeatureClass.ShapeType)
case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint:
this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassMarkerSymbols);
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:
this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassLineSymbols);
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon:
this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassFillSymbols);
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryMultiPatch:
this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassFillSymbols);
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
this.Close();
双击确定按钮和取消按钮,分别添加如下代码:
/// &summary&
/// 确定按钮
/// &/summary&
/// &param
name="sender"&&/param&
/// &param
name="e"&&/param&
private void btnOK_Click(object sender, EventArgs e)
//取得选定的符号
this.pSymbol = (ISymbol)pStyleGalleryItem.I
//更新预览图像
this.pSymbolImage = this.ptbPreview.I
//关闭窗体
this.Close();
private void btnCancel_Click(object sender,
EventArgs e)
this.Close();
为了操作上的方便,我们添加SymbologyControl的DoubleClick事件,当双击符号时同按下确定按钮一样,选定符号并关闭符号选择器窗体。代码如下:
private void
axSymbologyControl_OnDoubleClick(object sender,
ISymbologyControlEvents_OnDoubleClickEvent e)
this.btnOK.PerformClick();
再添加符号预览函数,当用户选定某一符号时,符号可以显示在PictureBox控件中,方便预览,函数代码如下:
/// &summary&
/// 把选中并设置好的符号在picturebox控件中预览
/// &/summary&
private void PreviewImage()
stdole.IPictureDisp picture =
this.axSymbologyControl.GetStyleClass(this.axSymbologyControl.StyleClass).PreviewItem(pStyleGalleryItem,
this.ptbPreview.Width, this.ptbPreview.Height);
System.Drawing.Image image = System.Drawing.Image.FromHbitmap(new
System.IntPtr(picture.Handle));
this.ptbPreview.Image =
当SymbologyControl的样式改变时,需要重新设置符号参数调整控件的可视性,故要添加SymbologyControl的OnStyleClassChanged事件,事件代码与Load事件类似,如下:
/// &summary&
/// 当样式(Style)改变时,重新设置符号类型和控件的可视性
/// &/summary&
/// &param
name="sender"&&/param&
/// &param
name="e"&&/param&
private void axSymbologyControl_OnStyleClassChanged(object sender,
ESRI.ArcGIS.Controls.ISymbologyControlEvents_OnStyleClassChangedEvent
switch ((esriSymbologyStyleClass)(e.symbologyStyleClass))
case esriSymbologyStyleClass.esriStyleClassMarkerSymbols:
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
case esriSymbologyStyleClass.esriStyleClassLineSymbols:
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
case esriSymbologyStyleClass.esriStyleClassFillSymbols:
this.lblAngle.Visible =
this.nudAngle.Visible =
this.lblSize.Visible =
this.nudSize.Visible =
this.lblWidth.Visible =
this.nudWidth.Visible =
this.lblOutlineColor.Visible =
this.btnOutlineColor.Visible =
通过以上操作,本符号选择器雏形已经完成,我们可以3sdnMap主窗体中调用并进行测试。如果您已经完成“直接调用ArcMap中的符号选择器”这一节,请注释axTOCControl_OnDoubleClick事件响应函数里的代码,并添加如下代码。如果您是直接学习自定义符号选择器这一节的,请先添加axTOCControl1控件的OnDoubleClick事件,再添加如下事件响应函数代码:
/// &summary&
/// 双击TOCControl控件时触发的事件
/// &/summary&
/// &param
name="sender"&&/param&
/// &param
name="e"&&/param&
private void axTOCControl1_OnDoubleClick(object sender,
ITOCControlEvents_OnDoubleClickEvent e)
esriTOCControlItem itemType =
esriTOCControlItem.esriTOCControlItemN
IBasicMap basicMap =
ILayer layer =
object unk =
object data =
axTOCControl1.HitTest(e.x, e.y, ref itemType, ref basicMap, ref
layer, ref unk, ref data);
if (e.button == 1)
if (itemType ==
esriTOCControlItem.esriTOCControlItemLegendClass)
//取得图例
ILegendClass pLegendClass =
((ILegendGroup)unk).get_Class((int)data);
//创建符号选择器SymbolSelector实例
SymbolSelectorFrm SymbolSelectorFrm = new
SymbolSelectorFrm(pLegendClass, layer);
if (SymbolSelectorFrm.ShowDialog() == DialogResult.OK)
//局部更新主Map控件
m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,
null, null);
//设置新的符号
pLegendClass.Symbol = SymbolSelectorFrm.pS
//更新主Map控件和图层控件
this.axMapControl1.ActiveView.Refresh();
this.axTOCControl1.Refresh();
按F5编译运行,相信你已经看到自己新手打造的符号选择器已经出现在眼前了,但还有些功能没实现。当然,它还比较简陋,下面我们将一起把它做得更完美些。在地图整饰中,符号参数的调整是必须的功能。下面我们将实现符号颜色、外框颜色、线宽、角度等参数的调整。添加SymbologyControl的OnItemSelected事件,此事件在鼠标选中符号时触发,此时显示出选定符号的初始参数,事件响应函数代码如下:
/// &summary&
/// 选中符号时触发的事件
/// &/summary&
/// &param
name="sender"&&/param&
/// &param
name="e"&&/param&
private void axSymbologyControl_OnItemSelected(object sender,
ESRI.ArcGIS.Controls.ISymbologyControlEvents_OnItemSelectedEvent
pStyleGalleryItem = (IStyleGalleryItem)e.styleGalleryI
switch (this.axSymbologyControl.StyleClass)
case esriSymbologyStyleClass.esriStyleClassMarkerSymbols:
this.ConvertIRgbColorToColor(((IMarkerSymbol)pStyleGalleryItem.Item).Color
as IRgbColor);
//设置点符号角度和大小初始值
this.nudAngle.Value =
(decimal)((IMarkerSymbol)this.pStyleGalleryItem.Item).A
this.nudSize.Value =
(decimal)((IMarkerSymbol)this.pStyleGalleryItem.Item).S
case esriSymbologyStyleClass.esriStyleClassLineSymbols:
this.ConvertIRgbColorToColor(((ILineSymbol)pStyleGalleryItem.Item).Color
as IRgbColor);
//设置线宽初始值
this.nudWidth.Value =
(decimal)((ILineSymbol)this.pStyleGalleryItem.Item).W
case esriSymbologyStyleClass.esriStyleClassFillSymbols:
this.ConvertIRgbColorToColor(((IFillSymbol)pStyleGalleryItem.Item).Color
as IRgbColor);
this.btnOutlineColor.BackColor =
this.ConvertIRgbColorToColor(((IFillSymbol)pStyleGalleryItem.Item).Outline.Color
as IRgbColor);
//设置外框线宽度初始值
this.nudWidth.Value =
(decimal)((IFillSymbol)this.pStyleGalleryItem.Item).Outline.W
color = Color.B
//设置按钮背景色
this.btnColor.BackColor =
//预览符号
this.PreviewImage();
调整点符号的大小。添加nudSize控件的ValueChanged事件,即在控件的值改变时响应此事件,然后重新设置点符号的大小。代码如下:
private void nudSize_ValueChanged(object sender,
EventArgs e)
((IMarkerSymbol)this.pStyleGalleryItem.Item).Size =
(double)this.nudSize.V
this.PreviewImage();
调整点符号的角度,添加nudAngle控件的ValueChanged事件,以重新设置点符号的角度。代码如下:
private void nudAngle_ValueChanged(object sender,
EventArgs e)
((IMarkerSymbol)this.pStyleGalleryItem.Item).Angle =
(double)this.nudAngle.V
this.PreviewImage();
调整线符号和面符号的线宽,添加nudWidth控件的ValueChanged事件,以重新设置线符号的线宽和面符号的外框线的线宽。代码如下:
private void nudWidth_ValueChanged(object sender,
EventArgs e)
switch (this.axSymbologyControl.StyleClass)
case esriSymbologyStyleClass.esriStyleClassLineSymbols:
((ILineSymbol)this.pStyleGalleryItem.Item).Width =
Convert.ToDouble(this.nudWidth.Value);
case esriSymbologyStyleClass.esriStyleClassFillSymbols:
//取得面符号的轮廓线符号
ILineSymbol pLineSymbol =
((IFillSymbol)this.pStyleGalleryItem.Item).O
pLineSymbol.Width = Convert.ToDouble(this.nudWidth.Value);
((IFillSymbol)this.pStyleGalleryItem.Item).Outline =
this.PreviewImage();
颜色转换,在ArcGIS
Engine中,颜色由IRgbColor接口实现,而在.NET框架中,颜色则由Color结构表示。故在调整颜色参数之前,我们必须完成以上两种不同颜色表示方式的转换。关于这两种颜色结构的具体信息,请大家自行查阅相关资料。下面添加两个颜色转换函数。
ArcGIS Engine中的IRgbColor接口转换至.NET中的Color结构的函数:
/// &summary&
/// 将ArcGIS Engine中的IRgbColor接口转换至.NET中的Color结构
/// &/summary&
/// &param
name="pRgbColor"&IRgbColor&/param&
&returns&.NET中的System.Drawing.Color结构表示ARGB颜色&/returns&
public Color ConvertIRgbColorToColor(IRgbColor pRgbColor)
return ColorTranslator.FromOle(pRgbColor.RGB);
.NET中的Color结构转换至于ArcGIS Engine中的IColor接口的函数:
/// &summary&
/// 将.NET中的Color结构转换至于ArcGIS Engine中的IColor接口
/// &/summary&
/// &param
name="color"&.NET中的System.Drawing.Color结构表示ARGB颜色&/param&
&returns&IColor&/returns&
public IColor ConvertColorToIColor(Color color)
IColor pColor = new RgbColorClass();
pColor.RGB = color.B * 65536 + color.G * 256 + color.R;
调整所有符号的颜色。选择颜色时,我们调用.NET的颜色对话框ColorDialog,选定颜色后,修改颜色按钮的背景色为选定的颜色,以方便预览。双击btnColor按钮,添加如下代码:
private void btnColor_Click(object sender,
EventArgs e)
//调用系统颜色对话框
if (this.colorDialog.ShowDialog() == DialogResult.OK)
//将颜色按钮的背景颜色设置为用户选定的颜色
this.btnColor.BackColor = this.colorDialog.C
//设置符号颜色为用户选定的颜色
switch (this.axSymbologyControl.StyleClass)
case esriSymbologyStyleClass.esriStyleClassMarkerSymbols:
((IMarkerSymbol)this.pStyleGalleryItem.Item).Color =
this.ConvertColorToIColor(this.colorDialog.Color);
case esriSymbologyStyleClass.esriStyleClassLineSymbols:
((ILineSymbol)this.pStyleGalleryItem.Item).Color =
this.ConvertColorToIColor(this.colorDialog.Color);
case esriSymbologyStyleClass.esriStyleClassFillSymbols:
((IFillSymbol)this.pStyleGalleryItem.Item).Color =
this.ConvertColorToIColor(this.colorDialog.Color);
//更新符号预览
this.PreviewImage();
调整面符号的外框线颜色。同上一步类似,双击btnOutlineColor按钮,添加如下代码:
private void btnOutlineColor_Click(object sender,
EventArgs e)
if (this.colorDialog.ShowDialog() == DialogResult.OK)
//取得面符号中的外框线符号
ILineSymbol pLineSymbol =
((IFillSymbol)this.pStyleGalleryItem.Item).O
//设置外框线颜色
pLineSymbol.Color =
this.ConvertColorToIColor(this.colorDialog.Color);
//重新设置面符号中的外框线符号
((IFillSymbol)this.pStyleGalleryItem.Item).Outline =
//设置按钮背景颜色
this.btnOutlineColor.BackColor = this.colorDialog.C
//更新符号预览
this.PreviewImage();
至此,你可以编译运行程序,看看效果如何,是不是感觉很不错了?我们已经能够修改符号的参数,自定义符号了。但是,SymbologyControl默认加载的是ESRI.ServerStyle文件的样式,用过ArcMap的你可能已经注意到,ArcMap中的Symbol
Selector有一个“More Symbols”按钮,可以加载其它的符号和ServerStyle文件。
还记得我们在开始的时候添加了ContextMenuStrip控件吗?现在它终于派上用场了。我们要实现的功能是:单击“更多符号”弹出菜单(ContextMenu),菜单中列出了ArcGIS自带的其它符号,勾选相应的菜单项就可以在SymbologyControl中增加相应的符号。在菜单的最后一项是“添加符号”,选择这一项时,将弹出打开文件对话框,我们可以由此选择其它的ServerStyle文件,以加载更多的符号。
定义全局变量,在SymbolSelectorFrm中定义如下全局变量,用于判断菜单是否已经初始化。
//菜单是否已经初始化标志
bool contextMenuMoreSymbolInitiated =
双击“更多符号”按钮,添加Click事件。在此事件响应函数中,我们要完成ServerStyle文件的读取,将其文件名作为菜单项名称生成菜单并显示菜单。代码如下:
/// &summary&
/// “更多符号”按下时触发的事件
/// &/summary&
/// &param
name="sender"&&/param&
/// &param
name="e"&&/param&
private void btnMoreSymbol_Click(object sender, EventArgs e)
if (this.contextMenuMoreSymbolInitiated == false)
//string sInstall =
ReadRegistry("SOFTWARE\\ESRI\\CoreRuntime");
//string path = System.bine(sInstall, "Styles");
string sInstall = "";
string path = System.bine(sInstall, "D:\\Program
Files\\ArcGIS\\Engine10.0\\Styles");
//取得菜单项数量
string[] styleNames = System.IO.Directory.GetFiles(path,
"*.ServerStyle");
ToolStripMenuItem[] symbolContextMenuItem = new
ToolStripMenuItem[styleNames.Length + 1];
//循环添加其它符号菜单项到菜单
for (int i = 0; i & styleNames.L i++)
symbolContextMenuItem[i] = new ToolStripMenuItem();
symbolContextMenuItem[i].CheckOnClick =
symbolContextMenuItem[i].Text =
System.IO.Path.GetFileNameWithoutExtension(styleNames[i]);
if (symbolContextMenuItem[i].Text == "ESRI")
symbolContextMenuItem[i].Checked =
symbolContextMenuItem[i].Name = styleNames[i];
//添加“更多符号”菜单项到菜单最后一项
symbolContextMenuItem[styleNames.Length] = new
ToolStripMenuItem();
symbolContextMenuItem[styleNames.Length].Text = "添加符号";
symbolContextMenuItem[styleNames.Length].Name =
"AddMoreSymbol";
//添加所有的菜单项到菜单
this.contextMenuStrip.Items.AddRange(symbolContextMenuItem);
this.contextMenuMoreSymbolInitiated =
//显示菜单
this.contextMenuStrip.Show(this.btnMoreSymbol.Location);
添加contextMenuStripMoreSymbol控件的ItemClicked事件。单击某一菜单项时响应ItemClicked事件,将选中的ServerStyle文件导入到SymbologyControl中并刷新。当用户单击“添加符号”菜单项时,弹出打开文件对话框,供用户选择其它的ServerStyle文件。代码如下:
/// &summary&
/// “更多符号”按钮弹出的菜单项单击事件
/// &/summary&
/// &param
name="sender"&&/param&
/// &param
name="e"&&/param&
private void contextMenuStrip_ItemClicked(object sender,
ToolStripItemClickedEventArgs e)
ToolStripMenuItem pToolStripMenuItem =
(ToolStripMenuItem)e.ClickedI
//如果单击的是“添加符号”
if (pToolStripMenuItem.Name == "AddMoreSymbol")
//弹出打开文件对话框
if (this.openFileDialog.ShowDialog() == DialogResult.OK)
//导入style file到SymbologyControl
this.axSymbologyControl.LoadStyleFile(this.openFileDialog.FileName);
//刷新axSymbologyControl控件
this.axSymbologyControl.Refresh();
else//如果是其它选项
if (pToolStripMenuItem.Checked == false)
this.axSymbologyControl.LoadStyleFile(pToolStripMenuItem.Name);
this.axSymbologyControl.Refresh();
this.axSymbologyControl.RemoveFile(pToolStripMenuItem.Name);
this.axSymbologyControl.Refresh();
相信你已经盼这一步很久了吧,按照惯例,按下F5吧!大功造成。
11图层文本标注
这一讲给大家讲解图层标注的实现方法。图层标注实现起来并不复杂,本例仅做一个简单示范,只加载AE的样式库,标注选定的字段,旨在抛砖引玉。更高级的功能,如自定义样式和修改样式,由读者自己实现。主要思路:加载图层字段
&& 加载文本样式 -& 设置文本样式。实现过程:创建标注设置窗体
-& 创建图层标注的Command -&
添加Command到图层右键菜单。
添加一个Windows窗体,命名为LabelLayerFrm.cs。添加控件如下:
为LabelLayerFrm类添加两个成员变量:
public ILayer pL
private IStyleGalleryItem pStyleGalleryI
重载一个构造函数:
public LabelLayerFrm(ILayer layer)
InitializeComponent();
添加成员函数ReadRegistry,用于从注册表中读取ArcGIS的安装路径。
/// &summary&
/// 读取注册表中的制定软件的路径
/// &/summary&
/// &param
name="sKey"&&/param&
&returns&&/returns&
private string ReadRegistry(string sKey)
//Open the subkey for reading
Microsoft.Win32.RegistryKey rk =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey, true);
if (rk == null) return "";
// Get the data from a specified item in the key.
return (string)rk.GetValue("InstallDir");
添加LabelLayerFrm窗体的Load事件,以加载图层字段到下拉模型,加载文本样式到SymbologyControl控件。
private void LabelLayerFrm_Load(object sender,
EventArgs e)
//加载图层字段
ITable pTable = pLayer as IT
IField pField =
for (int i = 0; i & pTable.Fields.FieldC
pField = pTable.Fields.get_Field(i);
cbbField.Items.Add(pField.AliasName);
cbbField.SelectedIndex = 0;
//获得ArcGIS的安装路径
//string sInstall =
ReadRegistry("SOFTWARE\\ESRI\\CoreRuntime");
//加载ESRI.ServerStyle 样式文件到SymbologyControl
this.axSymbologyControl.LoadStyleFile("D:\\Program
Files\\ArcGIS\\Engine10.0\\Styles\\ESRI.ServerStyle");
this.axSymbologyControl.GetStyleClass(esriSymbologyStyleClass.esriStyleClassTextSymbols).SelectItem(0);//这个地方有错误,SelectItem选择后不能调出涂层文本标注框
//this.axSymbologyControl.GetStyleClass(esriSymbologyStyleClass.esriStyleClassTextSymbols);//改成这句也不行,能调出对话框但是样式选择,后面代码就不能正确执行
//综上问题还是不能解决,楼主能力有限,姑且认为上一行的代码正确,只是为AE的bug
添加axSymbologyControl1控件的OnItemSelected事件,以设置选定的样式。
private void axSymbologyControl1_OnItemSelected
(object sender, ISymbologyControlEvents_OnItemSelectedEvent e)
pStyleGalleryItem =
(IStyleGalleryItem)e.styleGalleryI
添加确定按扭的Click事件,为选定图层中的选定的字段以选定的样式标注。
private void btnOK_Click(object sender, EventArgs
IGeoFeatureLayer pGeoFeatureLayer = pLayer as
IGeoFeatureL
pGeoFeatureLayer.AnnotationProperties.Clear();//必须执行,因为里面有一个默认的
IBasicOverposterLayerProperties pBasic = new
BasicOverposterLayerPropertiesClass();
ILabelEngineLayerProperties pLableEngine = new
LabelEngineLayerPropertiesClass();
ITextSymbol pTextSymbol = new
TextSymbolClass();
pTextSymbol =
(ITextSymbol)pStyleGalleryItem.I
//你可以在这里修改样式的颜色和字体等属性,本文从略
//pTextSymbol.Color
//pTextSymbol.Font
string pLable = "[" + (string)cbbField
.SelectedItem + "]";
pLableEngine.Expression = pL
pLableEngine.IsExpressionSimple =
pBasic.NumLabelsOption =
esriBasicNumLabelsOption.esriOneLabelPerS
pLableEngine.BasicOverposterLayerProperties =
pLableEngine.Symbol = pTextS
pGeoFeatureLayer.AnnotationProperties.Add(pLableEngine as
IAnnotateLayerProperties);
pGeoFeatureLayer.DisplayAnnotation =
至此,标注设置窗体已经完成,如果你编译通不过,看看是不是忘了添加相关引用了。
创建一个新类,以ArcGIS的BaseCommand为模板,命名为LabelLayerCmd.cs。注意:在新建Base
Command模板时,会弹出一个对话框让我们选择模板适用对象,这时我们要选择MapControl、PageLayoutControl,即选择第二项或者倒数第二项。添加LabelLayerCmd类的成员变量。
private ILayer pLayer =
IMapControl3 pM
修改默认构造函数如下:
public LabelLayerCmd(ILayer lyr,IMapControl3
// TODO: Define values for the public
properties
base.m_category = ""; //localizable text
base.m_caption = "标注"; //localizable text
base.m_message = "标注"; //localizable text
base.m_toolTip = "标注"; //localizable text
base.m_name = "标注"; //unique id, non-localizable
(e.g. "MyCategory_MyCommand")
// TODO: change bitmap name if necessary
string bitmapResourceName = GetType().Name +
base.m_bitmap = new Bitmap(GetType(),
bitmapResourceName);
catch (Exception ex)
System.Diagnostics.Trace.WriteLine(ex.Message,
"Invalid Bitmap");
修改OnClick函数为:
/// &summary&
/// Occurs when this command is clicked
/// &/summary&
public override void OnClick()
// TODO: Add LabelLayerCmd.OnClick
implementation
LabelLayerFrm labelLyrFrm = new
LabelLayerFrm(pLayer);
labelLyrFrm.ShowDialog();
pMap.Refresh(esriViewDrawPhase.esriViewGraphics,
null, null);
回到主窗体类,找到axTOCControl1_OnMouseDown事件响应函数,修改如下代码片断:
//弹出右键菜单
if (item ==
esriTOCControlItem.esriTOCControlItemMap)
m_menuMap.PopupMenu(e.x, e.y,
m_tocControl.hWnd);
if (item ==
esriTOCControlItem.esriTOCControlItemLayer)
m_menuLayer.AddItem(new OpenAttributeTable(layer),
-1, 2, true , esriCommandStyles.esriCommandStyleTextOnly);
//动态添加图层标注的Command到图层右键菜单
m_menuLayer.AddItem(new LabelLayerCmd(layer,
m_mapControl), -1, 3, false,
esriCommandStyles.esriCommandStyleTextOnly);
//弹出图层右键菜单
m_menuLayer.PopupMenu(e.x, e.y,
m_tocControl.hWnd);
//移除菜单项
m_menuLayer.Remove(3);
m_menuLayer.Remove(2);
至此,已经完成图层文本标注,编译运行吧。
22:5247人阅读(1)
GIS中的查询分析功能是非常重要的,本节将实现这些功能。
3.1属性及空间查询
在Forms文件夹右击点击“添加”—&“Windows窗体”,添加两个窗体,分别用于空间查询和属性查询,参数设置如下表。
窗体名称(Name)
SpatialQueryForm
用于空间查询参数设置
AttributeQueryForm
用于属性查询参数设置
同时在主窗体上的菜单项上添加一二级菜单。
查询(menuQuery)
……属性查询(menuAttributeQuery)
……空间查询(menuSpatialQuery)
实现属性查询,首先打开“属性查询”窗体的设计器。添加三个Label控件,两个ComboBox,两个Button和一个TextBox。各控件属性设置如下:
名称(Name)
选择图层:
字段名称:
查找内容:
MapControl中的图层名称
cboLayer选中图层的所有字段名称
输入的查询对象名称
取消查询按钮
界面效果如下:
进入窗体的代码编辑界面,首先添加三个引用:
using ESRI.ArcGIS.C
using ESRI.ArcGIS.C
using ESRI.ArcGIS.G
然后定义两个成员变量,一个用于存储地图数据,一个用于存储当前选中图层,如下
//地图数据
private AxMapControl mMapC
//选中图层
private IFeatureLayer mFeatureL
然后修改其构造函数,构造函数中添加一个参数MapControl,用于获取MapControl中的数据,如下所示:
public AttributeQueryForm(AxMapControl
mapControl)
InitializeComponent();
this.mMapControl = mapC
在窗体的Load事件中添加代码,用于初始化cboLayer,获取MapControl中的图层名称,如下:
//MapControl中没有图层时返回
if (this.mMapControl.LayerCount &=
//获取MapControl中的全部图层名称,并加入ComboBox
//图层名称
string strLayerN
for (int i = 0; i &
this.mMapControl.LayerC i++)
pLayer = this.mMapControl.get_Layer(i);
strLayerName = pLayer.N
//图层名称加入cboLayer
this.cboLayer.Items.Add(strLayerName);
//默认显示第一个选项
this.cboLayer.SelectedIndex = 0;
在CboLayer的SelectedIndexChanged事件中添加代码,当选中图层发生变化时,cboField中的字段名称重新获取,代码如下:
//获取cboLayer中选中的图层
mFeatureLayer =
mMapControl.get_Layer(cboLayer.SelectedIndex) as IFeatureL
IFeatureClass pFeatureClass =
mFeatureLayer.FeatureC
//字段名称
string strFldN
for (int i = 0; i &
pFeatureClass.Fields.FieldCi++ )
strFldName =
pFeatureClass.Fields.get_Field(i).N
//图层名称加入cboField
this.cboField.Items.Add(strFldName);
//默认显示第一个选项
this.cboField.SelectedIndex = 0;
查找按钮添加事件:
private void button1_Click(object sender, EventArgs
//定义图层,要素游标,查询过滤器,要素
IFeatureCursor pFeatureC
IQueryFilter pQueryF
IFeature pF
IEnvelope pE
pEnv = mMapControl.ActiveView.E
pPoint = new PointClass();
pPoint.X = pEnv.XMin + pEnv.Width / 2;
pPoint.Y = pEnv.YMin + pEnv.Height / 2;
if (this.mMapControl.LayerCount &= 0)
//获取图层
mFeatureLayer = mMapControl.get_Layer(cboLayer.SelectedIndex) as
//清除上次查询结果
this.mMapControl.Map.ClearSelection();
this.mMapControl.ActiveView.Refresh();
//pQueryFilter的实例化
pQueryFilter = new QueryFilterClass();
//设置查询过滤条件
pQueryFilter.WhereClause = cboField.Text + "=" +
txtValue.T
pFeatureCursor = mFeatureLayer.Search(pQueryFilter, true);
//获取查询到的要素
pFeature = pFeatureCursor.NextFeature();
//判断是否获取到要素
if (pFeature != null)
//选择要素
this.mMapControl.Map.SelectFeature(mFeatureLayer, pFeature);
//放大到要素
pFeature.Shape.Envelope.CenterAt(pPoint);
this.mMapControl.Extent = pFeature.Shape.E
//没有得到pFeature的提示
MessageBox.Show("没有找到相关要素!", "提示");
取消按钮添加事件:
private void btnCancel_Click(object sender,
EventArgs e)
this.Close();
点击运行,这样就实现了属性查询的功能。运行效果如下图:
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 arcgis导入坐标点 的文章

 

随机推荐