第2章桌面GIS应用软件的开发方式对于桌面GIS应用来说,ArcGIS平台不仅提供了用于开发独立运行的GIS应用软件的二次开发工具包ArcGISEngine,还提供了对ArcGISDesktop桌面软件进行扩展的开发方法。在开发一个具体的GIS行业应用软件时,程序员应该根据系统规模、用户水平和具体应用环境等设计相应的系统架构,从而决定是采用C/S架构还是B/S架构?如果采用C/S架构,是开发一个独立的系统还是在现有的ArcGIS桌面软件上进行扩展?因此选择合适的开发方式是进行GIS软件设计的第一步。特别需要注意的是,并不是所有的GIS应用系统都一定要基于ArcGISEngine开发。因此,本章将首先介绍基于ArcGIS平台开发桌面GIS应用系统的其它几种方式,包括使用VBA的方法,使用DLL动态链接库的方法,以及使用Add-In的方法等。最后再介绍使用ArcGISEngine创建一个简单的能独立运行的GIS应用软件的方法。2.1使用VBA进行桌面软件开发VBA(VisualBasicforApplications)可以理解为简化的VisualBasic语言,它是VisualBasic语言的子集,主要用于对支持VBA的Windows程序(称为“宿主程序”)进行扩展和定制。Word、Excel等Office办公套件很早就集成了VBA语言,利用它可以进一步扩充这些宿主程序的功能,或者基于这些宿主程序开发较为复杂的应用系统。VisualBasic开发的系统可以脱离VisualBasic而运行,但是基于VBA开发的系统不能脱离宿主软件运行,它的代码存储在宿主程序的文档中,如对Word进行VBA定制和开发的代码存储在*.doc文件中,对ArcMap进行扩展的代码存储于*.mxd地图文档中。使用VBA进行系统扩展是一种轻量级的软件开发模式。Esri目前不特别推荐使用VBA进行系统开发,而更侧重于推荐使用Python语言进行扩展。但在很多情况下,特别是一些业务模式相对固定的生产和管理部门,并不需要复杂的GIS分析功能,而是更侧重于地理数据的管理,并且这些用户基本掌握了ArcGIS软件的使用,通过VBA开发方式将一系列业务管理流程自动化为工具按钮置于ArcGIS桌面软件中,既能满足行业管理的需求,又能充分利用ArcGIS本身强大的空间数据管理功能,这时使用VBA开发定制无疑是一种较好的方式。但需要注意的是,出于产品线战略布局的总体考虑,ArcGIS10.1中已不再支持VBA开发(当然10.0及以下版本的ArcGIS还可以使用VBA),对应的开发模式转为Add-in方式。不过由于生产单位软件更新的滞后性,在今后较长的一段时间内,较低版本的ArcGIS软件依旧存在,因此了解VBA的开发还是有必要的。2.1.1VBA开发方式通过VBA开发环境进行ArcGIS桌面软件的扩展和定制是最简单的GIS软件开发方式。开发者只需专注于ArcGIS软件不能提供的功能,对于ArcGIS软件已经提供的工具,直接“拿过来”使用即可。并且VBA环境本身已经提供了对整个应用程序和文档进行控制的变量,例如在ArcMap中开发人员可以直接通过Application、ThisDocument两个全局变量获取程序本身和程序所使用的文档对象,使开发更为快捷和简单。在ArcGIS10.0版本中,进行VBA的开发需要单独安装VBA开发程序模块,安装ArcGISDesktop时不再附带VBA安装选项。根据操作方式的不同,在ArcGISDesktop中进行VBA编程的方法有两种:一种是编写VBA宏命令,另一种是创建UIControl工具并在其事件中写入实现代码。2.1.1.1宏命令方式开发人员将那些能够自动执行某种操作的命令统称为宏(Macros)。宏是一种操作命令,它和菜单操作命令的使用方式一致,因此可以认为宏和普通的命令是一样的。使用宏的目的往往是完成某些重复的操作,借以提高工作效率。下面以在ArcMap中根据选择集创建临时图层为例,说明如何使用宏命令进行VBA的编程。1)在ArcMap中,点击主菜单中的【Customize】菜单,选择【VBAMacros】然后选择【Macros…】或者直接按【Alt+F8】键弹出图2.1所示的宏命令对话框。在其中输入宏名称为“CreateLayerBySelection”。图2.1创建宏在“宏的位置”下拉列表中,“Project”选项表示该宏命令将保存在程序正在使用的*.mxd文档中;“Normal”选项表示这个宏命令将保存在Normal.mxt模板中,这样宏命令将出现在任何一个新建的*.mxd文档中,因为每个*.mxd文档都是从Normal.mxt模板中派生生成的。2)点击【创建】按钮,自动进入图2.2所示的VBA程序代码实现界面。图2.2VBA程序界面(宏命令方式)3)在VBA程序界面中,完成CreateLayerBySelection()过程(Sub),实现根据选择集创建临时图层的操作,具体代码如下:SubCreateLayerBySelection()'定义文档变量DimpMxDocAsIMxDocumentSetpMxDoc=Application.Document'定义地图文档DimpMapAsIMapSetpMap=pMxDoc.ActiveView.FocusMapDimpLayerAsILayerDimpNewLayerAsILayerDimpEnumLyrAsIEnumLayerDimpFeatLyrAsIFeatureLayerDimpNewFeatLyrAsIFeatureLayerDimpFeatSelAsIFeatureSelectionDimpFeatLyrDefAsIFeatureLayerDefinition'获取当前地图中的图层枚举类型SetpEnumLyr=pMap.LayerspEnumLyr.ResetSetpLayer=pEnumLyr.Next'循环遍历当前地图文档中所有图层While(NotpLayerIsNothing)SetpFeatLyr=pLayerSetpFeatSel=pFeatLyr'判断当前图层是否有选中要素,有则根据选中要素生成图层,无则直接跳过IfpFeatSel.SelectionSet.Count0ThenSetpFeatLyrDef=pFeatSelSetpNewFeatLyr=pFeatLyrDef.CreateSelectionLayer(New+pFeatLyr.FeatureClass.AliasName,True,,)pFeatSel.Clear'将根据选择集生成的图层加载到当前地图文档中IfNotpNewFeatLyrIsNothingThenSetpNewLayer=pNewFeatLyrpMap.AddLayerpNewLayerEndIfEndIfSetpLayer=pEnumLyr.NextWendEndSub4)点击【保存】按钮,保存代码。关闭VBA环境回到ArcMap环境中,点击主菜单中的【Customize】菜单,然后选择【CustomizeMode…】,弹出如图2.3所示对话框,在Commands选项卡中单击“[Macros]”可以看到刚才创建的宏命令出现在对话框中,选中该宏命令拖动至ArcMap工具条中,则会在工具条中出现对应的工具按钮。图2.3宏的调用5)拖拽完成宏命令添加后,用户可以通过在该宏命令按钮上单击鼠标右键来改变它的属性信息。选中该宏命令按钮,单击鼠标右键,弹出图2.4所示下拉菜单,用户可以在这里设置该宏命令按钮的图像、样式等属性信息,如设置成是只显示文字还是同时显示文字和图片等。当然用户也可以对按钮进行编组、删除等操作。图2.4宏属性信息设置6)单击该宏命令按钮,ArcMap根据当前选择集的情况自动创建临时图层,并将创建的临时图层添加到当前地图中。2.1.1.2UIControl方式使用宏命令可以将重复的过程包装起来,让用户更加方便的调用,但是如果涉及到鼠标交互,如使用鼠标拖拽的方式来实现拉框放大、缩小等,宏命令则无法做到。这时需要使用ArcMap提供给开发人员的UIControl工具进行鼠标交互,即VBA开发的另一种方式:使用UIControl进行交互式开发。1)在ArcMap界面中,点击主菜单中的【Customize】,然后选择【CustomizeMode…】,弹出图2.3所示【Customize】对话框,在Commands选项卡中找到“[UIControl]”,然后点击【NewUIControl】,弹出如图2.5所示【NewUIControl】对话框。图2.5新建UIControl对话框在这个对话框中,可以创建自定义的控件,它罗列了四种不同的类型,每种类型的作用如表2.1所示:表2.1UIControl类型与用途UIControl类型用途UIButtonControl创建Button(按钮)UIToolControl创建与Map交互的Tool(工具)UIEditBoxControl创建EditBox(编辑框)UIComboBoxControl创建ComboBox(组合框)2)下面以新建UIToolControl为例介绍UIControl的用法。选择【UIToolControl】单选框,点击按钮【CreateandEdit】进入图2.6所示VBA编码界面。图2.6VBA编码界面(UIControl方式)3)以“定位到所选范围”功能为例,在图2.7右侧事件下拉框列表中选择MouseDown事件。图2.7选择控件事件在该事件中,添加“将当前视图窗口定位到鼠标绘制范围”的代码,具体代码如下所示:'获取当前地图文档DimpMxDocAsIMxDocumentSetpMxDoc=Application.DocumentDimpScreenDisAsIScreenDisplaySetpScreenDis=pMxDoc.ActiveView.ScreenDisplay'获取缩放范围DimpEnvAsIEnvelopeDimpRubberAsIRubberBandSetpRubber=NewRubberEnvelopeSetpEnv=pRubber.TrackNew(pScreenDis,Nothing)'缩放到所选范围pMxDoc.ActiveView.Extent=pEnvpMxDoc.ActiveView.Refresh4)点击【保存】按钮,保存代码关闭VBA环境回到ArcMap环境中。5)点击主菜单中的【Customize】,然后选择【CustomizeMode…】,弹出图2.8所示对话框,在Commands选项卡中点击“[UIControl]”可以看到刚才创建的功能按钮出现在对话框中,选中该功能按钮并将其拖动至ArcMap工具栏中,点击该按钮即可执行相应代码。图2.8添加UIControl工具通过上面两个简单的例子,可以看出VBA编程既具有充分利用现有ArcGIS桌面软件所提供功能的便利,又能有效地扩展原有桌面软件的功能。生产管理部门和数据处理需求较多的业务化部门均会对这种开发方式有较强的需求。本书之所以介绍VBA编程,一方面在于提醒读者进行项目设计时勿对简单项目进行过度设计,另一方面也告诉读者对于日常工作中经常进行的重复性工作可以通过VBA简单编程的方法来极大地提高工作效率。2.1.2VBA代码的安全性VBA代码保存在文档或者模板中,即保存在*.mxd或者*.mxt文件里,开发人员编写的代码很容易被别人使用。为了保护开发人员的成果不被非法修改和利用,可以设置VBA代码的密码,以增加安全性。在【Customize】对话框中选择【Options】选项卡,可以查看、设置VBA代码的安全级别等相关信息。点击图2.9中的【LockCustomization…】按钮,用户会被要求输入文档保护密码。设置密码后,在尝试打开VBA代码编写窗口时,将会出现一个认证对话框,只有输入正确的密码才能进入。图2.9设置VBA代码的安全级别同时