ArcGIS Engine二次开发——基础篇

更新时间:2024-05-06 03:36:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

ArcGIS Engine二次开发——基础篇

ArcGIS Engine二次开发

——基础篇

ArcGIS Engine二次开发——基础篇

1 ArcGIS Engine二次开发——基础篇

1.1 第一个简单的ArcGIS Engine地图显示程序

这个例子将引导您创建第一个简单的地图显示程序,并添加基本的缩放和漫游功能。如果您之前没有接触过ArcGIS Engine的开发,那么这个例子是您迈入ArcGIS Engine二次开发大门的极好例子,将从零开始引导您一步一步完成任务。

1.1.1 创建一个新的工程

首先打开Microsoft Visual Studio 2005,点击菜单栏中的“文件”—>“新建”—>“项目”,在弹出的对话框中选择新建一个Visual C#的Windows应用程序,之后更改项目名称为“地图浏览”,更改文件的路径为个人实习文件夹,点击“确定”即可。

图 1新建项目对话框

选中项目“地图浏览”中的窗体“Form1”,修改其Name属性为“MainForm”,Text属性为“地图浏览”,

ArcGIS Engine二次开发——基础篇

图 2窗体命名

1.1.2 添加控件及引用

点击编译器最左侧的“工具箱”(不存在时可通过“视图”“工具箱”打开),在弹出的选择项中找到“ArcGIS Windows Forms”项,单击其中的MapControl,之后在Form1的空白处单击鼠标左键不放并拖拽鼠标,直到调整MapControl到合适的大小再松开鼠标(您也可以直接在工具箱中双击MapControl,该控件则会自动加入到Form1中)。用同样的方法,再将LicenseControl添加到Form1中。

图 3 打开工具箱

ArcGIS Engine二次开发——基础篇

图 4工具箱

如果您在工具箱中找不到MapControl,则请依次尝试以下两种解决方案。首先单击工具栏,待工具箱弹出之后,在工具箱的任意位置上单击鼠标右键,从弹出菜单中选择“重置工具箱”。如果这一步操作之后仍然无法看到MapControl,则在工具箱的任意位置上单击鼠标右键,找到“常规”选项卡,然后在“常规”选项卡上单击鼠标右键,在弹出菜单中单击“选择项(I)…”,在弹出的对话框中选择“.NET Framework组件”,找到“LicenseControl”和“MapControl”,将这两项前的复选框打上勾,最后点击确定即可(如果在“.NET Framework组件”这个面板中找不到这两项,则选择“COM 组件”面板,在“ESRI LicenseControl”和“ESRI MapControl”前面打勾)。

ArcGIS Engine二次开发——基础篇

图 5重置工具箱

图 6选择项

ArcGIS Engine二次开发——基础篇

不到这个图层则自动退出。

//获取图层

pFeatureLayer = this.axMapControl1.Map.get_Layer(0) as IFeatureLayer; //如果图层名称不是states,程序退出 if (pFeatureLayer.Name != \ bou2_4p \) return;

//清除上次查询结果

this.axMapControl1.Map.ClearSelection();

下面部分是生成一个新的查询器,选择条件(WhereClause)就是检索是否有与用户输

入相符的州,并将结果从查询得到的pCursor中读取出来。

//pQueryFilter的实例化

pQueryFilter = new QueryFilterClass(); //设置查询过滤条件

pQueryFilter.WhereClause = \ + txtStateName.Text + \; //查询

pFeatureCursor = pFeatureLayer.Search(pQueryFilter, true); //获取查询到的要素

pFeature = pFeatureCursor.NextFeature();

下面部分是一个判断语句,若查询得到的结果为空,则刷新地图,弹出对话框通知用户没有查询到结果,并退出程序。如果查询得到的结果不为空,则将这个结果加入地图的选择集,并将地图的显示范围定为查询结果的外轮廓,这样得到的州将高亮显示同时居中放大到屏幕中心。

//判断是否获取到要素

if (pFeature!=null) {

//选择要素

this.axMapControl1.Map.SelectFeature(pFeatureLayer, pFeature); //放大到要素

this.axMapControl1.Extent = pFeature.Shape.Envelope; } else {

//没有得到pFeature的提示

MessageBox.Show(\没有找到名为\ + txtStateName.Text + \的省\, \提示\); }

1.2.3 小结

这一部分中,我们接触到了基本的属性查询。但是在这个例子中,我们不能实现对属性表中任意属性字段的查询(在这个程序中,我们只能查询省名——NAME,而不能对别的字段进行查询),而且这个查询不支持模糊查询。为了使查询变的更加丰富,更加人性化,

ArcGIS Engine二次开发——基础篇

请您参考IQueryFilter接口中WhereClause属性的设置方法,拓展WhereClause可以得到许多有趣的结果。在书写代码的过程中,对任何有疑问的地方,或者您想要拓展的位置,都可以在帮助系统中查询相关的接口和属性,查看最原始的定义,帮助系统中的解释和定义对于您熟悉ArcObjects,熟悉ArcGIS Engine的二次开发以及后续的工作都是十分重要的,请一定不要忽视这个环节。如果您已经尝试了一些变化,或者对本小节的内容比较熟悉了,则可以进入下一小节的学习。

1.3 空间查询

上一小节我们已经学习了如何进行属性查询,在这一小节中,我们将继续学习GIS中的另一种查询方式——空间查询,其中有点查询、线查询、矩形查询、圆查询。本节我们将空间查询的方法抽象为一个独立的函数,这个函数中我们将根据不同的空间查询方式,返回查询得到的一个或多个要素的名称并在地图上高亮显示。

1.3.1 添加控件

新建一个C#.Net工程,向工程中添加控件,如下图所示:

图 31 窗体布局

其中包括MapControl,4个Button,一个TextBox。属性设置如下:

窗体及控件属性设置

类型 Form TextBox Button Button Button Name MainForm txtTips btnPointQuery btnLineQuery btnRectQuery Text 空间查询 点查询 线查询 矩形查询 用途 主窗体 点查询 线查询 矩形查询 请在地图上选取地物! 系统操作提示 ArcGIS Engine二次开发——基础篇

Button

btnCircleQuery 圆查询 圆查询 通过在控件属性中添加地图的方法,向Mapcontrol中添加例子数据。(例子数据是位于China文件夹下的bou2_4p)如下图所示:

图 9添加数据

下面我们在MainForm的代码页添加空间查询的函数。本例中我们需要添加ESRI.ArcGIS.Carto、ESRI.ArcGIS.Geometry、ESRI.ArcGIS.Geodatabase、ESRI.ArcGIS.Controls四个个命名空间。

我们仍然需要上节中的ConvertPixelToMapUnits(IActiveView activeView,double pixelUnits)函数,请自行添加。

1.3.2 添加代码

先在类中添加一个公共函数,用来根据屏幕像素计算实际的地理距离。

///

/// 根据屏幕像素计算实际的地理距离 ///

/// /// ///

private double ConvertPixelToMapUnits(IActiveView activeView,double pixelUnits) {

double realWorldDiaplayExtent; int pixelExtent; double sizeOfOnePixel; double mapUnits;

//获取设备中视图显示宽度,即像素个数

pixelExtent=activeView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right- activeView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left; //获取地图坐标系中地图显示范围 realWorldDiaplayExtent =

activeView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width; //每个像素大小代表的实际距离

sizeOfOnePixel = realWorldDiaplayExtent / pixelExtent; //地理距离

mapUnits = pixelUnits * sizeOfOnePixel;

return mapUnits;

ArcGIS Engine二次开发——基础篇

}

然后添加空间查询的方法,空间查询函数代码如下:

///

/// 空间查询 ///

/// /// /// /// 查询得到的要素名称

private string QuerySpatial(AxMapControl mapControl, IGeometry geometry, string fieldName) {

//本例添加一个图层进行查询,多个图层时返回 if (mapControl.LayerCount > 1) return null;

//清除已有选择

mapControl.Map.ClearSelection();

//查询得到的要素名称 string strNames=null;

IFeatureLayer pFeatureLayer; IFeatureClass pFeatureClass; //获取图层和要素类,为空时返回

pFeatureLayer = mapControl.Map.get_Layer(0) as IFeatureLayer; pFeatureClass = pFeatureLayer.FeatureClass; if (pFeatureClass == null) return null;

//初始化空间过滤器 ISpatialFilter pSpatialFilter;

pSpatialFilter = new SpatialFilterClass(); pSpatialFilter.Geometry = geometry; //根据图层类型选择缓冲方式 switch (pFeatureClass.ShapeType) {

case esriGeometryType.esriGeometryPoint:

pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; break;

case esriGeometryType.esriGeometryPolyline:

pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses; break;

case esriGeometryType.esriGeometryPolygon:

ArcGIS Engine二次开发——基础篇

pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; break; }

//定义空间过滤器的空间字段

pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;

IQueryFilter pQueryFilter; IFeatureCursor pFeatureCursor; IFeature pFeature; //利用要素过滤器查询要素

pQueryFilter = pSpatialFilter as IQueryFilter;

pFeatureCursor = pFeatureLayer.Search(pQueryFilter, true); pFeature = pFeatureCursor.NextFeature();

int fieldIndex;

while (pFeature != null) {

//选择指定要素

fieldIndex = pFeature.Fields.FindField(fieldName); //获取要素名称

strNames = strNames + pFeature.get_Value(fieldIndex) + \;\; //高亮选中要素

mapControl.Map.SelectFeature((ILayer)pFeatureLayer, pFeature); mapControl.ActiveView.Refresh(); pFeature = pFeatureCursor.NextFeature(); }

return strNames; }

定义鼠标标记的成员变量mMouseFlag。在设计页面双击点查询按钮,进入点击按钮响应事件填写如下代码。

private void btnPointQuery_Click(object sender, EventArgs e) {

mMouseFlag = 1;

this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; }

相应的线查询、矩形查询、圆查询添加同样的代码,但nMouseFlag得值要有所改变。 线查询:nMouseFlag=2 矩形查询:nMouseFlag=3 圆查询:nMouseFlag=4

ArcGIS Engine二次开发——基础篇

为MapControl控件添加OnMouseDown事件,填入以下代码

private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e) {

//记录查询到的要素名称

string strNames = \查询到的要素为:\; //查询的字段名称

string strFieldName=\; //点查询

if (mMouseFlag == 1) {

IActiveView pActiveView; IPoint pPoint; double length; //获取视图范围

pActiveView = this.axMapControl1.ActiveView; //获取鼠标点击屏幕坐标

pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y); //屏幕距离转换为地图距离

length = ConvertPixelToMapUnits(pActiveView, 2);

ITopologicalOperator pTopoOperator; IGeometry pGeoBuffer; //根据缓冲半径生成空间过滤器

pTopoOperator = pPoint as ITopologicalOperator; pGeoBuffer = pTopoOperator.Buffer(length);

strNames = strNames + QuerySpatial(this.axMapControl1, pGeoBuffer, strFieldName);

}

else if (mMouseFlag==2)//线查询 {

strNames = strNames+QuerySpatial(this.axMapControl1, this.axMapControl1.TrackLine(), strFieldName); }

else if (mMouseFlag==3)//矩形查询 {

strNames = strNames + QuerySpatial(this.axMapControl1, this.axMapControl1.TrackRectangle(), strFieldName); }

else if (mMouseFlag==4)//圆查询 {

strNames = strNames + QuerySpatial(this.axMapControl1, this.axMapControl1.TrackCircle(), strFieldName); }

ArcGIS Engine二次开发——基础篇

else {

strNames = \未得到空间要素!\; }

//提示框显示提示

this.txtTips.Text =strNames; }

注释:

距离转换函数请参看程序注释。

Button的Click事件中是将nMouseFlag设置为1,并将鼠标在MapControl上的形状改变为十字丝状。

//获取视图范围

pActiveView = this.axMapControl1.ActiveView; //获取鼠标点击屏幕坐标

pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y); //屏幕距离转换为地图距离

length = ConvertPixelToMapUnits(pActiveView, 2);

上述代码是在MapControl的OnMouseDown事件中,当您单击鼠标左键的时候,获取点击位置的屏幕坐标,并将屏幕上的两个像素大小的距离转换成地图上的距离,作为查询的缓存半径。

//根据缓冲半径生成空间过滤器

pTopoOperator = pPoint as ITopologicalOperator; pGeoBuffer = pTopoOperator.Buffer(length); pSpatialFilter = new SpatialFilterClass(); pSpatialFilter.Geometry = pGeoBuffer;

上述代码是以鼠标的点击位置,以缓冲距离length为半径,生成一个缓冲区。

pSpatialFilter = new SpatialFilterClass(); pSpatialFilter.Geometry = pGeoBuffer; //根据图层类型选择缓冲方式 switch (pFeatureClass.ShapeType) {

case esriGeometryType.esriGeometryPoint:

pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; break;

case esriGeometryType.esriGeometryPolyline:

pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses; break;

ArcGIS Engine二次开发——基础篇

case esriGeometryType.esriGeometryPolygon:

pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; break; }

//定义空间过滤器的空间字段

pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;

上述代码是设置pSpatialFilter的各项参数,供后续查询,包括空间查询的几何形状(之前生成的缓冲区),空间查询的方式(相交,包含等)以及Shape字段。

fieldIndex = pFeature.Fields.FindField(\);

MessageBox.Show(\查找到“\ + pFeature.get_Value(fieldIndex) + \, \提示\);

这两句代码是找出“NAME”所在的列数,并将其显示出来。

点击运行,运行效果如下图所示:

图 10 线查询运行效果

仔细研读代码,您会发现,在这部分中我们并没有用到什么新的知识,只是在结构上做了调整,应为空间查询都是需要使用一个IGeometry对象进行空间求交进行查询的。所以我们将公共的代码放在公共的模块中进行调用。有心的同学可能发现,我们为了判断用户在MapControl上的操作,我们引入了一个全局变量nMouseFlag,程序中多一个全局变量,对程序的结构的封闭性就有所破坏,能不能去掉这个全局变量而是Mapcontrol自主判断是哪个功能进行操作呢?答案是肯定的,我们可以使用BaseCommand和BaseTool来完成这个工作,详细的用法在3.4和3.5小节将会介绍。

ArcGIS Engine二次开发——基础篇

1.3.3 小结

在这一小节中,我们学习了如何进行简单的空间查询。空间查询不仅包括点查询,还包括线查询,矩形查询,多边形查询等(为了实现这些功能,可以参考MapControl中的TrackRectangle等方法)。对于这一小节的代码,强烈建议您参看帮助系统中对相关接口的解释和定义,以进一步熟悉接口的使用,这对后面的学习以及掌握ArcGIS Engine二次开发是极有好处的。如果您对这一部分比较熟悉了,可以进入下一小节。在第四章中,我们介绍了控件命令(Control Commands),并提到ArcGIS Engine允许用户自定义开发一些控件命令,在下两小节中,我们将具体学习如何开发。

1.4 BaseCommand开发实例

在这一小节和下一小节中中,我们将学习ArcEngine中基于BaseCommand和BaseTool的功能开发步骤。基于BaseCommand的功能实现与Button的功能类似,是当鼠标点击按钮的时候,MapControl控件会对其中的命令做出相应响应而无需额外的操作,如ArcMap中的居中放大FixedZoomIn,全图FullExtent等。

在这一小节中,我们将基于BaseCommand制作一个“固定比例尺放大”的按钮,当鼠标单击按钮时,地图将居中放大一倍。

1.4.1 添加控件

如果上一小节的程序已经关闭,则重新打开,同时保证MapControl控件中加载了至少一个图层。在主窗体(MapViewForm)中添加一个Button,将其Name属性改为btnFixedZoomIn,Text属性更改为“居中放大”。

1.4.2 添加BaseCommand

点击菜单栏上的“项目”—>“添加类”,弹出以下对话框。

图 11添加新项对话框

如上图所示,在类别中选择ArcGIS项,在右侧的模板中选择“BaseCommand”项,并在名称中将其更改为“FixedZoomIn”,点击添加,出现如下对话框。

ArcGIS Engine二次开发——基础篇

图 12类别选择向导

我们这个命令是用于MapControl控件的,所以在选择项中选择“ArcMap,MapControl or PageLayoutControl Command”或者“MapControl or PageLayoutControl Command”,这里我们选择后者,点击OK。

1.4.3 添加代码

双击解决方案资源管理器中的FixedZoomIn.cs项,进入该类的代码编写界面。首先按照前几节介绍过的方法,加入引用“ESRI.ArcGIS.Geometry”,并在该类的最上方添加如下代码:

using ESRI.ArcGIS.Carto;

using ESRI.ArcGIS.Geometry;

将 base.m_caption、base.m_toolTip 更改为“居中放大”,将base.m_name 更改为“FixedZoomIn”。之后在OnClick()函数中添加如下代码:

public override void OnClick() {

// TODO: Add FixedZoomIn.OnClick implementation //获取当前视图范围

IActiveView pActiveView = m_hookHelper.ActiveView; IEnvelope pEnvelope = pActiveView.Extent; //扩大视图范围并刷新视图 pEnvelope.Expand(0.5, 0.5, true); pActiveView.Extent = pEnvelope; pActiveView.Refresh(); }

本文来源:https://www.bwwdw.com/article/9qvg.html

Top