2 使用ArcGIS Engine控件编程
在ESRI.ArcGIS.Controls命名空间中包含了可用于快速构建GIS独立应用程序的控件,如MapControl、PageLayoutControl、TOCControl和ToolbarControl等。其中MapControl和PageLayoutControl对应ArcMap桌面应用程序的“数据”和“布局”视图。前者封装了Map对象,用于地图数据的显示和分析,后者封装了PageLayout对象,用于地图的修饰和整理,以便生成一幅成品地图。这两个控件均实现了IMxdContents接口,可以读取和写入地图文档(MapDocument)。
TOCControl和ToolbarControl控件分别对应ArcMap中的“Table of Contents”和各种工具条。这两个控件都需要一个“伙伴控件”协同工作,而伙伴控件则可以是MapControl、PageLayoutControl、SceneControl或GlobeControl。TOCControl用交互树视图的方式来显示伙伴控件的地图、图层和符号体系内容,并保持其内容与伙伴控件同步。而ToolbarControl则可以驻留操作其伙伴控件的命令、工具和菜单。
在Visual Studio.NET环境中使用ArcGIS Engine开发GIS应用程序,需要使用ESRI interop程序集(Interop Assemblies),它为ArcGIS控件提供了能够位于.NET窗体上的控件,这些控件当被拖放在窗体上,生成具体的实例对象时,均有带有前缀“ax”。如axMapControl1,axPageLayoutControl1等。
本章将详细介绍MapControl、PageLayoutControl、TOCControl和ToolbarControl四个常用控件,并在C#.NET开发平台上,结合GIS软件开发的基本需求进行讲述。
2.1 MapControl控件
MapControl控件对应于ArcMap中的数据视图,它封装了Map对象,并提供了相应的属性、方法、事件,可以实现: (1)地图显示;
(2)地图的放大、缩小和漫游; (3)生成点、线、面等图形元素;
(4)识别地图上选中的元素,进行属性查询; (5)标注地图元素等。
该控件能够实现ArcMap能够完成的绝大部分任务。该控件实现的主要接口包括IMapControlDefault、IMapControl2、IMapControl3、IMapControl4和事件接口IMapControlEvents2、IMxdContents、ITOCBuddyEvents。
2.1.1 主要接口
?IMapControlDefault接口
IMapControlDefault接口是MapControl的缺省接口,是代表控件最新版本的接口。一般的开发环境自动使用这个接口定义的属性和方法。在C#开发平台上,当用户将该控件拖放到窗体上时,会自动生成一个名为axMapControl1的对象,该对象可以直接使用缺省接口对应的属性和方法。该控件当前最新版本的接口为IMapControl4。定义该接口的变量,并进行实例化的方法如下:
IMapControlDefault pMapcontrol;
pMapcontrol = axMapControl1.Object as IMapControlDefault;
?IMapControl2接口
该接口是所有与MapControl相关任务的出发点,包括设置控件外观、设置Map对象及控件的显示属性,添加、管理数据层,在控件上绘制图形并返回Geometry等。该接口定义
了控制控件外观界面的各种属性,如Apperaance、BorderStyle和BackColor。它定义了AddLayer、AddLayerFromFile、AddshapeFile、CenterAt、ClearLayers、DeleteLayer、LoadMxFile、MoveLayerTo、Pan、ReadMxMaps等添加、移动、删除、清楚图层的方法,TrackLine、TrackPolygon、TrackRectangle和TrackCircle等让程序员可以直接在控件上获得Geometry对象的方法,外还提供了DrawShape和DrawText让程序员可以在控件上绘制图形的方法。
?IMapControl3接口
该接口在继承IMapControl2的基础上,增加了以下属性和方法: 1)CustomProperty:设置自定义控件属性;
2)DoucumentFilename:返回加入MapControl中地图文档的文件名; 3)DocumentMap:返回MapControl最后装入Map的名称;
4)KeyIntercept:返回或设置MapControl截取的键盘按键信息,按键信息类型如表2.1所示。
5)Object:返回潜在的MapControl控件。 6)ShowMap Tips、TipDelay、TipStyle
7)SuppressResizeDrawing():控件尺寸发生变化时,阻止数据实时重绘。
表2.1 esriKeyIntercept可能取值
枚举值 EsriKeyInterceptNone EsriKeyInterceptArrowKeys EsriKeyInterceptAlt EsriKeyInterceptTab EsriKeyInterceptEnter 0 1 2 4 8 Value 功能描述 没有截取鼠标按键 截取了箭头按键 截取了Alt按键 截取了Tab按键 截取了回车按键 ?IMapControl4接口
该接口在IMapControl接口的基础上,增加了两个属性,分别是AutoKeyboardScrolling和AutoMouseWheel。
?IMapControlEvents2 接口
该接口为事件接口,它定义了MapControl能够处理的全部事件。 如OnMouseDown、OnMouseMove、OnAfterDraw、OnExtentUpdated等。这些事件,在实际GIS软件开发中经常用到,如AfterScreenDraw是绘屏结束后触发的事件,OnExtentUpdate是地图的Extent属性发生变化时触发的事件等。
2.1.2 用MapControl控件加载地理数据
?用MapControl加载shape格式文件
用MapControl控件的AddShapeFile方法可以加载shape格式文件,该方法包括两个参数,分别是文件路径和不带扩展名的文件名。调用格式如下:
axMapControl1.AddShapeFile(strFilePath, strFilename);
也可以利用工作空间工厂打开Shape文件。基本思路是,利用工作空间工厂抽象类的IWorkspaceFactory接口定义接口变量pWorkspaceFactory,再利用其子类
ShapefileWorkspaceFactory对应的组件类ShapefileWorkspaceFactoryClass对
pWorkspaceFactory进行实例化。利用IWorkspace接口定义工作空间变量pWorkspace,利用pWorkspaceFactory的OpenFromFile方法打开工作空间,对其进行实例化。该方法包含两个参数,第一参数为需要打开工作空间(数据库,即shape格式的文件)的路径。接下来利用IFeatureWorkspace接口定义接口变量pFeatureWorkspace,对该变量利用接口跳转的方式进
行实例化:
pFeatureWorkspace=pWorkspace as IFeatureWorkspace;
利用IFeatureClass接口定义变量pFeatureClass,并对该变量利用pFeatureWorkspace的OpneFeatureClass方法进行实例化,该方法包含的参数是需要打开的shape文件名。定义数据集对象、特征图层对象,定义特征图层的特征数据类及特征图层的名称,再定义图层,最后将图层添加到MapControl的Map对象上,就能显示所选择的shape格式文件,具体代码如下所示。
string WorkSpacePath =System.IO.Path.GetDirectoryName(strFileName); strShapeFileName=System.IO.Path.GetFileName(strFileName);
IWorkspaceFactory pWorkspaceFactory=new ShapefileWorkspaceFactoryClass(); IWorkspace pWorkspace=pWorkspaceFactory.OpenFromFile(WorkSpacePath,0); IFeatureWorkspace pFeatureWorkspace=pWorkspace as IFeatureWorkspace;
IFeatureClass pFeatureClass=pFeatureWorkspace.OpenFeatureClass(strShapeFileName); IDataset pDataset=pFeatureClass as IDataset; IFeatureLayer pFeatureLayer=new FeatureLayerClass(); pFeatureLayer.FeatureClass=pFeatureClass; pFeatureLayer.Name=pDataset.Name; ILayer pLayer=pFeatureLayer as ILayer; axMapControl1.Map.AddLayer(pLayer);
在上述两种方式中,到底哪种方式显示图形的效率高,需要进行测试。
?用MapControl加载MXD格式文件
MapControl控件可以“链接”或“包含”地图文档,若为链接文档,控件将保存对地图文档的引用,以后任何对文档的修改都会出现在控件上,若为“包含文档”,则控件会复制当前的文档状态,而不会受到后来修改的影响。 在AE编程中,可以直接使用MapControl的LoadMxFile方法载入地图文档。在进行加载时,一般需通过MapControl提供的方法CheckMxFile()检查所选文件是否是合法的MXD文档,若合法则调用MapControl提供的LoadMxFile方法打开文档。
if (axMapControl1.CheckMxFile(strFileName))//strFileName是用户所选地图文档文件 {
//加载MXD文档
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerHourglass; axMapControl1.LoadMxFile(strFileName, 0, Type.Missing);
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerDefault; } else {
MessageBox.Show(\所选文件不是地图文档文件!\信息提示\
return;
}
若要加载某个地图文档中的特定地图,则需要先进行判断满足特定条件的地图,然后才加载地图文档文件。如下面的实例代码所示:
if (axMapControl1.CheckMxFile(strFileName))//strFileName为地图文档文件 {
//是Mxd文档文件 IArray pArray;
pArray = axMapControl1.ReadMxMaps(strFileName, Type.Missing); IMap pMap;
for (int i = 0; i < pArray.Count; i++) {
//QI接口跳转
pMap = pArray.get_Element(i) as IMap; if (pMap.Name == \ {
//加载文档对象中特定的Map对象
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerHourglass; axMapControl1.LoadMxFile(strFileName, 0, Type.Missing);
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerDefault; } } } else {
MessageBox.Show(\所选文件不是地图文档文件!\信息提示\
return;
}
?用MapControl加载栅格格式文件
利用MapControl控件也可以加载诸如*.bmp、*.tif、*.jpg等各种栅格格式的文件,加载栅格格式文件,需要引入ESRI.ArcGIS.DataSourcesRaster命名空间。具体思路如下:利用工作空间工厂抽象类定义接口变量,利用工作空间工厂的子类RasterWorkspaceFactory对用的组件类RasterWorkspaceFactoryClass实例化工作空间工厂变量。接下来定义工作空间变量,并进行实例化,再定义栅格工作空间,并进行实例化,接下来定义栅格数据集,利用所选栅格数据文件进行实例化,并判断该文件是否具有金字塔,若没有则创建金字塔,以提高大数据量图像的显示效率。在此基础上定义栅格数据、栅格数据层和数据层,并完成向MapControl空间中添加数据层数据,具体实现代码参与以下实例:
string pathName = System.IO.Path.GetDirectoryName(strFileName);//strFileName是栅格数据文件
string fileName = System.IO.Path.GetFileName(strFileName);
IWorkspaceFactory pWSF;
pWSF = new RasterWorkspaceFactoryClass(); IWorkspace pWS;
pWS = pWSF.OpenFromFile(pathName, 0); IRasterWorkspace pRWS;
pRWS = pWS as IRasterWorkspace; IRasterDataset pRasterDataset;
pRasterDataset = pRWS.OpenRasterDataset(fileName ); //影像金字塔判断与创建
IRasterPyramid pRasPyrmid;
pRasPyrmid = pRasterDataset as IRasterPyramid; if (pRasPyrmid != null) {
if (!(pRasPyrmid.Present))
{
pRasPyrmid.Create();
//在进度条中说明正在创建金字塔 }
}
IRaster pRaster;
pRaster = pRasterDataset.CreateDefaultRaster(); IRasterLayer pRasterLayer;
pRasterLayer = new RasterLayerClass(); pRasterLayer.CreateFromRaster(pRaster); ILayer pLayer = pRasterLayer as ILayer; //向axMapControl1控件中添加栅格图层 axMapControl1.AddLayer(pLayer, 0);
通过上面的讲述,可以体会MapControl控件的AddLayer方法、AddShapeFile方法、AddLayerFromFile方法等。另外,该控件还包括DeleteLayer和MoveLayerTo等方法。其它方法请查看MapControl的对象模型图,各种方法的具体使用请参阅ESRI ArcGIS Engine开发帮助文档。
IMapDocument接口定义了操作和管理文档对象的方法和属性。MapDocument类能够封装地图文档文件,如mxd、mxt和pmf等,它也可以封装一个图层文件(*.lyr)。使用这个对象可以获取和更新一个文档的内容,设置文档文件的属性以及读、写和保存一个文档文件。下面举例说明打开、保存、另存一个文档文件,主要代码如下:
//打开文档文件
IMapDocument pMapDocument;//定义接口变量
pMapDocument = new MapDocumentClass();//实例化地图文档对象 //将数据加载入pMapDocument并与map控件联系起来
pMapDocument.Open(strFileName, \);//strFileName是用户选择的文档文件 for (int i = 0; i < pMapDocument.MapCount; i++) {
//遍历所有可能的Map对象
axMapControl1.Map = pMapDocument.get_Map(i); }
//刷新地图
axMapControl1.Refresh();
//保存文档文件
//判断文档是否为只读文档
if (pMapDocument.get_IsReadOnly(pMapDocument.DocumentFilename) == true) {
MessageBox.Show(\此地图文档为只读文档!\, \信息提示\); return;