为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > ArcGIS-Engine二次开发——基础篇Word版

ArcGIS-Engine二次开发——基础篇Word版

2021-03-29 7页 doc 1MB 26阅读

用户头像 机构认证

夕夕资料

拥有专业强大的教研实力和完善的师资团队,专注为用户提供合同简历、论文写作、PPT设计、计划书、策划案、各类模板等,同时素材和资料部分来自网络,仅供参考.

举报
ArcGIS-Engine二次开发——基础篇Word版ArcGISEngine二次开发——基础篇1ArcGISEngine二次开发——基础篇1.1第一个简单的ArcGISEngine地图显示程序这个例子将引导您创建第一个简单的地图显示程序,并添加基本的缩放和漫游功能。如果您之前没有接触过ArcGISEngine的开发,那么这个例子是您迈入ArcGISEngine二次开发大门的极好例子,将从零开始引导您一步一步完成任务。1.1.1创建一个新的工程首先打开MicrosoftVisualStudio2005,点击菜单栏中的“文件”—>“新建”—>“项目”,在弹出的对话框中选择新建一个V...
ArcGIS-Engine二次开发——基础篇Word版
ArcGISEngine二次开发——基础篇1ArcGISEngine二次开发——基础篇1.1第一个简单的ArcGISEngine地图显示程序这个例子将引导您创建第一个简单的地图显示程序,并添加基本的缩放和漫游功能。如果您之前没有接触过ArcGISEngine的开发,那么这个例子是您迈入ArcGISEngine二次开发大门的极好例子,将从零开始引导您一步一步完成任务。1.1.1创建一个新的工程首先打开MicrosoftVisualStudio2005,点击菜单栏中的“文件”—>“新建”—>“项目”,在弹出的对话框中选择新建一个VisualC#的Windows应用程序,之后更改项目名称为“地图浏览”,更改文件的路径为个人实习文件夹,点击“确定”即可。图1新建项目对话框选中项目“地图浏览”中的窗体“Form1”,修改其Name属性为“MainForm”,Text属性为“地图浏览”,图2窗体命名1.1.2添加控件及引用点击编译器最左侧的“工具箱”(不存在时可通过“视图”“工具箱”打开),在弹出的选择项中找到“ArcGISWindowsForms”项,单击其中的MapControl,之后在Form1的空白处单击鼠标左键不放并拖拽鼠标,直到调整MapControl到合适的大小再松开鼠标(您也可以直接在工具箱中双击MapControl,该控件则会自动加入到Form1中)。用同样的方法,再将LicenseControl添加到Form1中。图3打开工具箱图4工具箱如果您在工具箱中找不到MapControl,则请依次尝试以下两种解决方案。首先单击工具栏,待工具箱弹出之后,在工具箱的任意位置上单击鼠标右键,从弹出菜单中选择“重置工具箱”。如果这一步操作之后仍然无法看到MapControl,则在工具箱的任意位置上单击鼠标右键,找到“常规”选项卡,然后在“常规”选项卡上单击鼠标右键,在弹出菜单中单击“选择项(I)…”,在弹出的对话框中选择“.NETFramework组件”,找到“LicenseControl”和“MapControl”,将这两项前的复选框打上勾,最后点击确定即可(如果在“.NETFramework组件”这个面板中找不到这两项,则选择“COM组件”面板,在“ESRILicenseControl”和“ESRIMapControl”前面打勾)。图5重置工具箱图6选择项图7选择工具箱项图8选择工具箱项添加好MapControl和LicenseControl之后,调整Form1和MapControl的位置与大小,如下图所示:图9窗体布局1.1.3添加地图在MapControl上单击鼠标右键,选择“属性”,则会弹出MapControl的属性设置面板,在之前也介绍过,通过这个面板可以完成许多简单的工作。如图所示,点击“Map”面板,之后点击按钮,在弹出的对话框中选择路径为“……\GIS与开发\例子数据\China”,再在此路径下选择“bou2_4p”,点击“Open”。之后在MapControl的属性页上点击“确定”即可。图10“Map”面板至此,我们已经完成了一个最简单的地图显示程序。.点击“启动调试”按钮(或者在“调试”菜单下选择相应命令,或者按键盘的F5键),可以得到如下的运行结果。图11初次运行结果1.1.4添加代码我们没有书写任何代码,就得到了一个最简单的地图显示程序。但这个程序还不能与用户交互,下一步我们需要添加一些代码,让程序能响应用户的鼠标,完成放大和全图显示的功能。选中MapControl控件,单击属性窗口中的事件按钮,可以看到MapControl控件能够响应的所有事件(关于每个事件的详细使用方法等请参见帮助系统),我们可以通过双击对应事件进入代码编辑界面,这里我们选择“OnMouseDown”事件(注:控件的“OnMouseDown”事件也可以通过双击控件直接进入到代码编辑界面),下一步就需要在这个事件中添加响应鼠标的相关代码。图12MapControl控件支持的所有方法请您在axMapControl1的OnMouseDown事件中添加代码,如下所示:privatevoidaxMapControl1_OnMouseDown(objectsender,ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvente){if(e.button==1)this.axMapControl1.Extent=this.axMapControl1.TrackRectangle();elseif(e.button==2)this.axMapControl1.Extent=this.axMapControl1.FullExtent;}再次运行程序,鼠标左键在地图上拉框可以实现地图的放大功能,而右键单击地图则会还原地图的全图显示。图23任意比例尺放大功能如果将代码替换如下,则能实现左键放大,右键漫游的功能。privatevoidaxMapControl1_OnMouseDown(objectsender,ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvente){if(e.button==1)//e.button==1表示按下鼠标左键this.axMapControl1.Extent=this.axMapControl1.TrackRectangle();//表示在地图上拖拽一个矩形elseif(e.button==2)//e.button==2表示按下鼠标右键this.axMapControl1.Pan();//表示漫游}//e.button==4表示按下鼠标中键注释:代码中根据e中包含的“button”值来判断鼠标的单击操作是来自何处,若button值为1,则为鼠标左键,2代表鼠标右键,4代表鼠标中键。当判断得到是鼠标左键单击时,执行“this.axMapControl1.Extent=this.axMapControl1.TrackRectangle();”该语句调用了“TrackRectangle()”方法,这个方法是在地图上拖拽出一个矩形,之后将这个矩形赋值给当前地图的显示区域(Extent),这样就实现了地图的放大功能。类似的,若鼠标右键单击,则将全图范围赋值给当前的显示范围,实现了地图的全图显示功能。1.1.5小结通过这个例子,我们制作出了一个最简单的地图浏览程序AEMapView,并能响应一些基本的鼠标操作。在MapControl的属性页中,其实还有许多内容您可以尝试,例如在“General”面板中可以直接加入地图文件(*.mxd或者*.mxt),您也可以利用刚才的方式一次性多加入一些图层而不仅仅加入“bou2_4p”一个,同时可以更改各图层的叠放次序,也可以在“Data”面板中设置地图的旋转角度(Rotation)等,您还可以设置MapControl的显示方式,是否支持地图的预览功能,边框样式等等。您可以做一些尝试,看看能得到哪些有趣的结果,这些尝试对您今后熟悉ArcGISEngine的开发是有一定帮助的。如果需要重置MapControl,只需要点击“Data”面板中的“Reset”按钮。当您完成了这个例子,并做了一些积极的尝试之后,您就可以接着学习下一个小节的内容了。1.2属性查询查询是GIS中非常重要的一个功能,下面将分别介绍属性查询和空间查询的制作方法。1.2.1添加控件如果上一小节的工程已经关闭,则将其打开,如果您之后又在MapControl中添加了一些别的数据,请将其删除,只保留一个“bou2_4p”图层,请务必注意这一步,这直接关系到您下面的工作能否顺利进行。用之前讲过添加控件的方式,在窗体中添加一个Label和一个TextBox。将Label控件的“Text”属性修改为“城市名称”,TextBox控件的Name属性修改为txtStateName。控件添加完毕后效果如下:图24添加Label控件和TextBox控件后界面1.2.2添加代码首先添加引用。首先可以在项目的“解决方案资源管理器窗口”中单击展开“引用”选项,查看项目中已添加引用。图25项目已添加“引用”这个项目中我们需要使用“ESRI.ArcGIS.Carto”和“ESRI.ArcGIS.Geodatabase”两个引用项,点击菜单栏上的“项目”—>“添加引用”(或者在“解决方案资源管理器窗口”中右击“引用”,在弹出菜单中选择“添加引用”),在弹出的对话框中选择需要添加的引用,同时选择“ESRI.ArcGIS.Carto”和“ESRI.ArcGIS.Geodatabase”(选择的时候按下Ctrl键以同时选择多个),这里“ESRI.ArcGIS.Carto”在添加MapControl控件时已自动添加,我们只添加“ESRI.ArcGIS.Geodatabase”,点击确定。图26添加引用对话框之后双击TextBox控件,进入代码编辑界面。在代码编辑区域的命名空间(namespace)的上方输入以下内容:usingESRI.ArcGIS.Carto;usingESRI.ArcGIS.Geodatabase;如下图所示:图27引用添加位置之后在控件TextBox的事件中选择KeyUp,在KeyUp事件中添加以下代码:图28KeyUp方法privatevoidtxtStateName_KeyUp(objectsender,KeyEventArgse){//判断鼠标键值,如果Enter键按下抬起后,进入查询if(e.KeyCode==Keys.Enter){//定义图层,要素游标,查询过滤器,要素IFeatureLayerpFeatureLayer;//图层IFeatureCursorpFeatureCursor;//要素游标IQueryFilterpQueryFilter;//查询过滤器IFeaturepFeature;//要素//获取图层pFeatureLayer=this.axMapControl1.Map.get_Layer(0)asIFeatureLayer;//如果图层名称不是states,程序退出if(pFeatureLayer.Name!="bou2_4p")return;//清除上次查询结果this.axMapControl1.Map.ClearSelection();//pQueryFilter的实例化pQueryFilter=newQueryFilterClass();//设置查询过滤条件pQueryFilter.WhereClause="NAME='"+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+"的省","提示");}}}运行程序,分别向编辑框中输入“吉林省”和“长春省”,键入回车,如下图所示:图29吉林省查询结果图30长春省查询结果注释:if(e.KeyCode==Keys.Enter)上述代码是一个判断语句,即当用户输入回车的时候,开始进行查询。下面两行代码是定义查询的范围,默认为上一小节中添加的图层“bou2_4p”,如果找不到这个图层则自动退出。//获取图层pFeatureLayer=this.axMapControl1.Map.get_Layer(0)asIFeatureLayer;//如果图层名称不是states,程序退出if(pFeatureLayer.Name!="bou2_4p")return;//清除上次查询结果this.axMapControl1.Map.ClearSelection();下面部分是生成一个新的查询器,选择条件(WhereClause)就是检索是否有与用户输入相符的州,并将结果从查询得到的pCursor中读取出来。//pQueryFilter的实例化pQueryFilter=newQueryFilterClass();//设置查询过滤条件pQueryFilter.WhereClause="NAME='"+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,而不能对别的字段进行查询),而且这个查询不支持模糊查询。为了使查询变的更加丰富,更加人性化,请您参考IQueryFilter接口中WhereClause属性的设置方法,拓展WhereClause可以得到许多有趣的结果。在书写代码的过程中,对任何有疑问的地方,或者您想要拓展的位置,都可以在帮助系统中查询相关的接口和属性,查看最原始的定义,帮助系统中的解释和定义对于您熟悉ArcObjects,熟悉ArcGISEngine的二次开发以及后续的工作都是十分重要的,请一定不要忽视这个环节。如果您已经尝试了一些变化,或者对本小节的内容比较熟悉了,则可以进入下一小节的学习。1.3空间查询(包括pointlinerectanglecircle查询)上一小节我们已经学习了如何进行属性查询,在这一小节中,我们将继续学习GIS中的另一种查询方式——空间查询,其中有点查询、线查询、矩形查询、圆查询。本节我们将空间查询的方法抽象为一个独立的函数,这个函数中我们将根据不同的空间查询方式,返回查询得到的一个或多个要素的名称并在地图上高亮显示。1.3.1添加控件新建一个C#.Net工程,向工程中添加控件,如下图所示:图31窗体布局其中包括MapControl控件,4个Button,一个TextBox,LicenceControl控件。属性设置如下:窗体及控件属性设置类型NameText用途FormMainForm空间查询主窗体TextBoxtxtTips请在地图上选取地物!系统操作提示ButtonbtnPointQuery点查询点查询ButtonbtnLineQuery线查询线查询ButtonbtnRectQuery矩形查询矩形查询ButtonbtnCircleQuery圆查询圆查询通过在控件属性中添加地图的方法,向Mapcontrol中添加例子数据。(例子数据是位于China文件夹下的bou2_4p)如下图所示:图32添加数据下面我们在MainForm的代码页添加空间查询的函数。本例中我们需要添加ESRI.ArcGIS.Carto、ESRI.ArcGIS.Geometry、ESRI.ArcGIS.Geodatabase、ESRI.ArcGIS.Controls四个个命名空间。我们仍然需要上节中的ConvertPixelToMapUnits(IActiveViewactiveView,doublepixelUnits)函数,请自行添加。1.3.2添加代码先在类中添加一个公共函数,用来根据屏幕像素计算实际的地理距离。//////根据屏幕像素计算实际的地理距离//////屏幕视图///像素个数///privatedoubleConvertPixelToMapUnits(IActiveViewactiveView,doublepixelUnits){doublerealWorldDiaplayExtent;//地图显示范围intpixelExtent;//像素个数doublesizeOfOnePixel;//每个像素大小代表的实际距离doublemapUnits;//地理距离//获取设备中视图显示宽度,即像素个数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;returnmapUnits;}//pixelExtent=activeView.ScreenDiaplay.DisplayTransformation.get_DeviceFrame().right-activeView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;//realWorldDisplayExtent=activeView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;//sizeOfOnePixel=realWorldDisplayExtent/pixelExtent;//mapUnits=sizeOfOnePixel*pixelUnits;//returnmapUnits;然后添加空间查询的方法,空间查询函数代码如下://////空间查询//////MapControl///空间查询方式///字段名称///查询得到的要素名称privatestringQuerySpatial(AxMapControlmapControl,IGeometrygeometry,stringfieldName){//本例添加一个图层进行查询,多个图层时返回if(mapControl.LayerCount>1)returnnull;//清除已有选择mapControl.Map.ClearSelection();//查询得到的要素名称stringstrNames=null;IFeatureLayerpFeatureLayer;IFeatureClasspFeatureClass;//获取图层和要素类,为空时返回pFeatureLayer=mapControl.Map.get_Layer(0)asIFeatureLayer;pFeatureClass=pFeatureLayer.FeatureClass;if(pFeatureClass==null)returnnull;//初始化空间过滤器ISpatialFilterpSpatialFilter;pSpatialFilter=newSpatialFilterClass();pSpatialFilter.Geometry=geometry;//根据图层类型选择缓冲方式switch(pFeatureClass.ShapeType){caseesriGeometryType.esriGeometryPoint://点查询pSpatialFilter.SpatialRel=esriSpatialRelEnum.esriSpatialRelContains;break;caseesriGeometryType.esriGeometryPolyline://线查询pSpatialFilter.SpatialRel=esriSpatialRelEnum.esriSpatialRelCrosses;break;caseesriGeometryType.esriGeometryPolygon://多边形查询pSpatialFilter.SpatialRel=esriSpatialRelEnum.esriSpatialRelIntersects;break;}//定义空间过滤器的空间字段pSpatialFilter.GeometryField=pFeatureClass.ShapeFieldName;IQueryFilterpQueryFilter;IFeatureCursorpFeatureCursor;IFeaturepFeature;//利用要素过滤器查询要素pQueryFilter=pSpatialFilterasIQueryFilter;pFeatureCursor=pFeatureLayer.Search(pQueryFilter,true);pFeature=pFeatureCursor.NextFeature();intfieldIndex;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();}returnstrNames;}定义鼠标标记的成员变量mMouseFlag。在设计页面双击点查询按钮,进入点击按钮响应事件填写如下代码。privatevoidbtnPointQuery_Click(objectsender,EventArgse){mMouseFlag=1;this.axMapControl1.MousePointer=esriControlsMousePointer.esriPointerCrosshair;}相应的线查询、矩形查询、圆查询添加同样的代码,但nMouseFlag得值要有所改变。线查询:nMouseFlag=2矩形查询:nMouseFlag=3圆查询:nMouseFlag=4为MapControl控件添加OnMouseDown事件,填入以下代码privatevoidaxMapControl1_OnMouseDown(objectsender,IMapControlEvents2_OnMouseDownEvente){//记录查询到的要素名称stringstrNames="查询到的要素为:";//查询的字段名称stringstrFieldName="NAME";//点查询if(mMouseFlag==1){IActiveViewpActiveView;IPointpPoint;doublelength;//获取视图范围pActiveView=this.axMapControl1.ActiveView;//获取鼠标点击屏幕坐标pPoint=pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x,e.y);//屏幕距离转换为地图距离length=ConvertPixelToMapUnits(pActiveView,2);ITopologicalOperatorpTopoOperator;IGeometrypGeoBuffer;//根据缓冲半径生成空间过滤器pTopoOperator=pPointasITopologicalOperator;pGeoBuffer=pTopoOperator.Buffer(length);strNames=strNames+QuerySpatial(this.axMapControl1,pGeoBuffer,strFieldName);}elseif(mMouseFlag==2)//线查询{strNames=strNames+QuerySpatial(this.axMapControl1,this.axMapControl1.TrackLine(),strFieldName);}elseif(mMouseFlag==3)//矩形查询{strNames=strNames+QuerySpatial(this.axMapControl1,this.axMapControl1.TrackRectangle(),strFieldName);}elseif(mMouseFlag==4)//圆查询{strNames=strNames+QuerySpatial(this.axMapControl1,this.axMapControl1.TrackCircle(),strFieldName);}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=pPointasITopologicalOperator;pGeoBuffer=pTopoOperator.Buffer(length);pSpatialFilter=newSpatialFilterClass();pSpatialFilter.Geometry=pGeoBuffer;上述代码是以鼠标的点击位置,以缓冲距离length为半径,生成一个缓冲区。pSpatialFilter=newSpatialFilterClass();pSpatialFilter.Geometry=pGeoBuffer;//根据图层类型选择缓冲方式switch(pFeatureClass.ShapeType){caseesriGeometryType.esriGeometryPoint:pSpatialFilter.SpatialRel=esriSpatialRelEnum.esriSpatialRelContains;break;caseesriGeometryType.esriGeometryPolyline:pSpatialFilter.SpatialRel=esriSpatialRelEnum.esriSpatialRelCrosses;break;caseesriGeometryType.esriGeometryPolygon:pSpatialFilter.SpatialRel=esriSpatialRelEnum.esriSpatialRelIntersects;break;//caseeariSpatialFilterType.esriGeometryPolygon:pSpatialFilter.SpatialRel=eariSpatiaRelEnum.esriSpatialRelIntersect;break;}//定义空间过滤器的空间字段pSpatialFilter.GeometryField=pFeatureClass.ShapeFieldName;//pSpatialFilter.GeometryField=pFeatureClass.ShapeFieldName;上述代码是设置pSpatialFilter的各项参数,供后续查询,包括空间查询的几何形状(之前生成的缓冲区),空间查询的方式(相交,包含等)以及Shape字段。fieldIndex=pFeature.Fields.FindField("NAME");MessageBox.Show("查找到“"+pFeature.get_Value(fieldIndex)+"”","提示");//fieldIndex=pFeature.Fields.FindField(“NAME”);MessageBox.Show(“”+pFeature.get_Value(fieldIndex)+”’’”,””);这两句代码是找出“NAME”所在的列数,并将其显示出来。点击运行,运行效果如下图所示:图33线查询运行效果仔细研读代码,您会发现,在这部分中我们并没有用到什么新的知识,只是在结构上做了调整,应为空间查询都是需要使用一个IGeometry对象进行空间求交进行查询的。所以我们将公共的代码放在公共的模块中进行调用。有心的同学可能发现,我们为了判断用户在MapControl上的操作,我们引入了一个全局变量nMouseFlag,程序中多一个全局变量,对程序的结构的封闭性就有所破坏,能不能去掉这个全局变量而是Mapcontrol自主判断是哪个功能进行操作呢?答案是肯定的,我们可以使用BaseCommand和BaseTool来完成这个工作,详细的用法在3.4和3.5小节将会介绍。1.3.3小结在这一小节中,我们学习了如何进行简单的空间查询。空间查询不仅包括点查询,还包括线查询,矩形查询,多边形查询等(为了实现这些功能,可以参考MapControl中的TrackRectangle等方法)。对于这一小节的代码,强烈建议您参看帮助系统中对相关接口的解释和定义,以进一步熟悉接口的使用,这对后面的学习以及掌握ArcGISEngine二次开发是极有好处的。如果您对这一部分比较熟悉了,可以进入下一小节。在第四章中,我们介绍了控件命令(ControlCommands),并提到ArcGISEngine允许用户自定义开发一些控件命令,在下两小节中,我们将具体学习如何开发。1.4BaseCommand开发实例在这一小节和下一小节中中,我们将学习ArcEngine中基于BaseCommand和BaseTool的功能开发步骤。基于BaseCommand的功能实现与Button的功能类似,是当鼠标点击按钮的时候,MapControl控件会对其中的命令做出相应响应而无需额外的操作,如ArcMap中的居中放大FixedZoomIn,全图FullExtent等。在这一小节中,我们将基于BaseCommand制作一个“固定比例尺放大”的按钮,当鼠标单击按钮时,地图将居中放大一倍。1.4.1添加控件如果上一小节的程序已经关闭,则重新打开,同时保证MapControl控件中加载了至少一个图层。在主窗体(MapViewForm)中添加一个Button,将其Name属性改为btnFixedZoomIn,Text属性更改为“居中放大”。1.4.2添加BaseCommand点击菜单栏上的“项目”—>“添加类”,弹出以下对话框。图34添加新项对话框如上图所示,在类别中选择ArcGIS项,在右侧的模板中选择“BaseCommand”项,并在名称中将其更改为“FixedZoomIn”,点击添加,出现如下对话框。图35类别选择向导我们这个命令是用于MapControl控件的,所以在选择项中选择“ArcMap,MapControlorPageLayoutControlCommand”或者“MapControlorPageLayoutControlCommand”,这里我们选择后者,点击OK。1.4.3添加代码双击解决方案资源管理器中的FixedZoomIn.cs项,进入该类的代码编写界面。首先按照前几节介绍过的方法,加入引用“ESRI.ArcGIS.Geometry”,并在该类的最上方添加如下代码:usingESRI.ArcGIS.Carto;usingESRI.ArcGIS.Geometry;将base.m_caption、base.m_toolTip更改为“居中放大”,将base.m_name更改为“FixedZoomIn”。之后在OnClick()函数中添加如下代码:publicoverridevoidOnClick(){//TODO:AddFixedZoomIn.OnClickimplementation//获取当前视图范围IActiveViewpActiveView=m_hookHelper.ActiveView;IEnvelopepEnvelope=pActiveView.Extent;//扩大视图范围并刷新视图pEnvelope.Expand(0.5,0.5,true);pActiveView.Extent=pEnvelope;pActiveView.Refresh();}转到主窗体(MapViewForm),双击“居中放大”按钮,进入该按钮Click事件相应函数,添加如下代码:privatevoidbtnZoomIn_Click(objectsender,EventArgse){//声明与初始化FixedZoomInfixedZoomin=newFixedZoomIn();//与MapControl关联fixedZoomin.OnCreate(this.axMapControl1.Object);fixedZoomin.OnClick();}1.4.4运行运行程序,点击“居中放大”时,地图会放大一倍。点查询功能依然可用,如下图:图36程序运行结果1.4.5小结在这一小节中,我们学习到了如何制作一个BaseCommand。使用BaseCommand的好处主要有,首先按照面向对象的思想,居中放大这个功能已经被封装在我们自己书写的类中,若是以后需要再将这个功能移植到别的程序,或者由多个程序员共同完成一个程序时,只需要将这个类复制到相关工程下,稍作调整即可运行;其次,这样做可以是代码更易读,而且当需要完成许多不同的功能时,这种方法的优势就体现出来了,因为我们不需要再单独设立一个MouseFlag变量来判断具体用户点击了哪个按钮,MapControl的OnMouseDown事件中也无需再添加冗长的代码,而是分散到各类中,增强了程序的稳定性。在新建FixedZoomIn类的同时,我们发现还会附带生成一个FixedZoomIn.bmp位图文件,您可以双击这个图标以做相关编辑更改工作,也可以用自己的图标来替换(注意保持文件名一致)。这个图标的作用,是在使用ToolbarControl的时候,用于显示按钮图标的。您可以尝试着在工程中加入一根ToolbarControl,并使用AddItem方法添加我们写好的这个类,看能否得到一样的结果。使用ArcEngine自带BaseCommand基类,可以方便的开发出相关的Command按钮,从这个实例我们可以看出,根据Command按钮随鼠标点击MapControl及时响应的特性,我们一般只需要重载BaseCommand的OnClick()函数即可。然后在功能的实现处首先调用OnCreate()函数实现与MapControl的关联,调用OnClick()函数实现功能响应。这样有效的提高了我们进行功能开发的效率。其实,对于一些基本的地图操作Command的功能,ArcEngine进行了完整的封装,我们在使用时可以直接使用ArcEngine的封装类进行实例化。仍以“固定比例尺放大”为例,我们可以在“居中放大”按钮的Click事件中直接使用ArcEngine的封装类实现(注意,在这个示例中需要添加“ESRI.ArcGIS.SystemUI”和“ESRI.ArcGIS.Controls”的引用),代码如下:ICommandcommand=newControlsMapZoomInFixedCommandClass();command.OnCreate(this.axMapControl1.Object);command.OnClick();这种方法比我们基于BaseCommand的开发方法更加简便,我们在此介绍的目的是为了让大家掌握这种基本的开发方法,方便用于其他Command功能的开发。如果您对本小节的内容比较熟悉,也做了一些积极的尝试,那么您可以进入下一小节的学习。在下一小节中我们将学习BaseTool的开发方法。1.5BaseTool开发实例经过上一小节的学习,我们了解到了如何自定义BaseCommand来拓展ArcGIS的应用。我们将学习基于BaseTool的自定义功能开发,BaseTool与BaseCommand有些相似的地方,它们都是点击之后可以对MapControl控件做相应的操作,但是BaseCommand点击之后MapControl会直接予以相应,不需要额外的操作,而对于BaseTool来说,点击该功能之后,只是开启一个交互的过程,需要用户再用鼠标、键盘等对地图做进一步交互式的操作,MapControl控件才会予以相应,如ArcMap中的放大ZoomIn、漫游Pan等。为了实现BaseTool与BaseCommand功能实现的差异,在这一小节中,我们将剖析ArcMap的放大(ZoomIn)功能,并利用BaseTool进行实现。1.5.1打开工程我们这里需要在上一小节的基础上继续完善,如果您已经将MapView关闭,请重新打开。在主窗体(MapViewForm)中添加一个Button,将其Name属性改为btnZoomIn,Text属性更改为“拉框放大”。3.5.2添加BaseTool在菜单栏上选择“项目”——“添加类”,出现如下对话框:图37添加新项对话框在类别中选中ArcGIS,在模板中选择BaseTool,并将名称更改为“ZoomIn”,点击添加,出现如下对话框:图38类别选择向导我们这个工具是要用于MapControl,仍选择“MapControlorPageLayoutControlCommand”,点击OK。1.5.2添加代码双击解决方案资源管理器中的ZoomIn.cs,进入该类的代码编写界面。首先添加ESRI.ArcGIS.Carto、ESRI.ArcGIS.Geodatabase、ESRI.ArcGIS.Geometry、ESRI.ArcGIS..Display四个引用,类似的,将base.m_caption、base.m_toolTip更改为“拉框放大”,将base.m_name更改为“ZoomIn”。我们简单分析一下拉框放大的执行过程,点击“拉框放大”按钮后,鼠标在MapControl的视图中的拉框过程可以分解为三个事件,鼠标在视图上的按下(MouseDown),鼠标按下在视图上的移动(MouseMove),鼠标放开(MouseUp),我们需要在鼠标按下时刻和放开时刻记录鼠标点击的坐标,然后可以得到一个新的视图范围,完成放大操作。下面添加代码,首先我们需要在这个类中定义三个成员变量,三个成员变量的功能如注释所示。//记录鼠标位置privateIPointm_point;//标记MouseDown是否发生privateBooleanm_isMouseDown;//追踪鼠标移动产生新的EnvelopeprivateINewEnvelopeFeedbackm_feedBack;在ZoomIn.cs类中的OnMouseDown函数中添加如下代码:publicoverridevoidOnMouseDown(intButton,intShift,intX,intY){//当前地图视图为空时返回if(m_hookHelper.ActiveView==null)return;//获取鼠标点击位置m_point=m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);m_isMouseDown=true;}在ZoomIn.cs类中的OnMouseMove函数中添加如下代码:publicoverridevoidOnMouseMove(intButton,intShift,intX,intY){//MouseDown为发生时返回if(!m_isMouseDown)return;IActiveViewpActiveView=m_hookHelper.ActiveView;//m_feedBack追踪鼠标移动if(m_feedBack==null){m_feedBack=newNewEnvelopeFeedbackClass();m_feedBack.Display=pActiveView.ScreenDisplay;//开始追踪m_feedBack.Start(m_point);}//追踪鼠标移动位置m_feedBack.MoveTo(pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y));}在ZoomIn.cs类中的OnMouseMove函数中添加如下代码:publicoverridevoidOnMouseUp(intButton,intShift,intX,intY){//MouseDown为发生时返回if(!m_isMouseDown)return;IActiveViewpActiveView=m_hookHelper.ActiveView;//获取MouseUp发生时的范围并放大IEnvelopepEnvelope;if(m_feedBack==null)//鼠标未拉框时进行固定比例尺放大{pEnvelope=pActiveView.Extent;pEnvelope.Expand(0.5,0.5,true);pEnvelope.CenterAt(m_point);}else{//停止追踪pEnvelope=m_feedBack.Stop();//判断新的范围的高度和宽度是否为零if(pEnvelope.Width==0||pEnvelope.Height==0){m_feedBack=null;m_isMouseDown=false;}}//获取新的范围pActiveView.Extent=pEnvelope;//刷新视图pActiveView.Refresh();m_feedBack=null;m_isMouseDown=false;}再进入MapViewForm窗体的代码界面,定义成员变量privateZoomInmZoomIn=null;双击MapViewForm窗体上的“拉框放大”按钮,进入Click事件响应函数,将其中的代码删除,用下列代码替代:privatevoidbtnZoomIn_Click(objectsender,EventArgse){//初始化mZoomIn=newZoomIn();//与MapControl的关联mZoomIn.OnCreate(this.axMapControl1.Object);//设置鼠标形状this.axMapControl1.MousePointer=esriControlsMousePointer.esriPointerZoomIn;}将MapControl控件的OnMouseDown响应函数中的内容全部删除,添加代码如下:if(mZoomIn!=null)mZoomIn.OnMouseDown(e.button,e.shift,e.x,e.y);在MapControl控件的OnMouseMove响应函数中添加代码如下:if(mZoomIn!=null)mZoomIn.OnMouseMove(e.button,e.shift,e.x,e.y);在MapControl控件的OnMouseUp响应函数中添加代码如下:if(mZoomIn!=null)mZoomIn.OnMouseUp(e.button,e.shift,e.x,e.y);1.5.3运行图39程序运行结果如上图所示,首先点击“拉框放大”按钮,然后在MapControl中按下鼠标拉框,即可完成放大,点击不拖动鼠标情况下为居中放大。1.5.4小结在这一小节中,我们学习了如何制作BaseTool,正如同前一小节的小结中写到的那样,当有许多功能(例如漫游,点查询等)时,由于BaseTool在生成的时候会自动和MapControl控件关联起来。在这个例子中,我们通过重载自定义了OnMouseDown、OnMouseMove和OnMouseUp三个函数,实现Tool类型功能的响应。当然,这里的拉框放大功能在ArcEngine中也进行了封装。利用封装类来实现Tool类型的工具时,同样需要定义ICommand接口,通过ICommand接口来实现与MapControl的关联。通过查询帮助文档我们可以发现,本节中我们所自定义的BaseTool工具也是从接口ICommand和ITool同时继承得到的。以“拉框放大”为例,利用ArcEngine封装的类库实现基本的Tool类型功能的代码如下(注意,在这个示例中需要添加“ESRI.ArcGIS.SystemUI”和“ESRI.ArcGIS.Controls”的引用),感兴趣的同学可以将这段代码拷贝到“拉框放大”按钮的Click事件中,删除原来的代码,运行程序可以看到一致的效果。//Tool的定义和初始化ITooltool=newControlsMapZoomInToolClass();//查询接口获取ICommandICommandcommand=toolasICommand;//Tool通过ICommand与MapControl的关联command.OnCreate(this.axMapControl1.Object);command.OnClick();//MapControl的当前工具设定为toolthis.axMapControl1.CurrentTool=tool;如果您对这一小节的内容比较熟悉了,就可以开始学习本章最后一小节的内
/
本文档为【ArcGIS-Engine二次开发——基础篇Word版】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
热门搜索

历史搜索

    清空历史搜索