阅读:2582回复:2
ArcObjects 初探
ArcObjects是一个COM组件的集合,它是ArcInfo 8的两个新应用程序的基石,即ArcMap和ArcCatalog。这一系列的组件包含了超过1200个对象,它们可以用来定制、扩展和构建GIS应用程序。乍一看来,这么大的一个对象模型看起来真有点让人喘不过气来。仔细看一下ArcMap的对象模型你会发现它和其它一些大的对象模型的基本组成很相似。
1、基础构架 ![]() 例 1 Private Sub Zoom() ‘get the active view Dim mxDoc As IMxDocument Set mxDoc = Application.Document Dim activeView As IActiveView Set activeView = mxDoc.activeView ‘ get the active view’s extent Dim ext As IEnvelope Set ext = activeView.Extent ‘ shrink the extent ext.Expand 0.75, 0.75, True ‘ set the extent activeView.Extent = ext activeView.Refresh End Sub 如果ArcMap在页面视图下显示一个有三个数据框(data frame)的文档,将会有三个Map与MxDocument相关,ActiveView属性将返回PageLayout,FocusMap将返回当前被选中的数据框。例1中的VBA代码说明了这一部分对象模型。这段代码会改变ArctiveView的显示范围,放大75%。 这段代码非常的浅显。真正的工作是要从ActiveView中获的当前的显示范围,它是一个IEnvelope接口对象。然后缩放,并把调整的封装边界作为新的显示范围。这段代码在ActiveView上通过IActiveView接口进行操作。ActiveView能在PageLayout或Map中使用,这完全取决于最终用户的选择。这段代码对于两种情况都有效。 2、使用接口 有时候对于Map或PageLayout,你可能要使用不同的接口。在这种情况下,COM对象模型与传统的面向对象模型,像Avenue或是MapObjects,有很大的不同。接口是一组相关方法和属性的集合。COM对象暴露多个接口。比如说,Map对象不但有IActiveView接口,而且有IMap接口和其它一些接口。 例 2 Private Sub ClearLayers() ‘ get the active view Dim mxDoc As IMxDocument Set mxDoc = Application.Document Dim activeView As IActiveView Set activeView = mxDoc.activeView If TypeOf activeView Is IMap Then Dim map As IMap Set map = activeView ‘ acquire the IMap interface map.ClearLayers ‘ remove the layers mxDoc.UpdateContents ‘ refresh the table of contents activeView.Refresh ‘ refresh the display End If End Sub 例2显示了用来从activeView变量获取IMap接口的Set语句。注意这段代码使用TypeOf语句来判断ActiveView是不是Map的情况,通常情况下IMap接口是不显示的。如果不使用TypeOf语句,那么在运行代码时当ActiveView是一个PageLayout,在遇到Set语句的时候就会得到一个类型不匹配的错误。 3、屏幕显示 PageLayout和Map都有一个相关的对所有图形进行描述的ScreenDisplay对象。ScreenDisplay包含一个DisplayTransformation。你能获取DisplayTransformation的属性比如VisibleBounds,并且可以使用相应的方法在地图和显示单位间转换坐标和距离。图2说明了这一点。 比如向地图中增加一个新图层的事件将使ScreenDisplay触发一个重绘事件。这一绘制过程发生在三个方面。绘制顺序是地理数据、选择集和注记。绘制缓存(drawing cache)里存放了地图的一个非屏幕位图,只要窗口刷新,它就会被显示在屏幕上。ScreenDisplay管理几个缓存。如果使用esriNoScreenCashe常量,图形将直接绘制在ScreenDisplay的窗口上,不进行缓存。如果其它窗口获得显示,图形将消失。下面的代码使用esriNoScreenCache在ScreenDisplay的中间绘制文本“Hello”。 ![]() 注意例3中的例子,在StarDrawing和FinishDrawing中间调用了SetSymbol和DrawText。 例 3 Private Sub Hello() Dim mxDoc As IMxDocument Set mxDoc = Application.Document Dim activeView As IActiveView Set activeView = mxDoc.activeView ‘ set up a text symbol to draw with Dim sym As ITextSymbol Set sym = New TextSymbol ‘ change the font size to 18 Dim fnt As IFontDisp Set fnt = sym.Font fnt.Size = 18 sym.Font = fnt ‘ draw into the active view’s display With activeView.ScreenDisplay .StartDrawing .hDC, esriNoScreenCache .SetSymbol sym Dim bnds As IArea Set bnds = .DisplayTransformation.VisibleBounds .DrawText bnds.Centroid, “Hello” .FinishDrawing End With End Sub 4、使用图层 地图维护了一组图层。图层是实现了ILayer接口的对象。图层的实例包括了FeatureLayer、GroupLayer、GraphicsLayer、AnnotationLayer、CadLayer、TinLayer和RasterLayer。IMap接口的Layer(index)和LayerCount属性能够用来浏览图层集合。例4所示的功能是找到并返回指定名字的图层。 例 4 Function FindLayer(map As IMap, name As String) As ILayer Dim i As Integer For i = 0 To map.LayerCount - 1 If map.Layer(i).name = name Then Set FindLayer = map.Layer(i) Exit Function End If Next End Function FeatureLayer通过FeatureClass对象来管理一个矢量数据的连接,比如coverages、shapefile或SDE图层。例5中的代码从一个shapefile中获取一个FeatureClass,通过打开一个Workspace,这个Workspace用ShapefileWorkspaceFactory包含了shapefile。然后创建一个FeatureLayer与图层的FeatureClass相关,在把它加到FocusMap中。 例 5 Sub AddLayer() ‘ use a workspaceFactory to open the workspace Dim wksFact As IWorkspaceFactory Set wksFact = New Shapefi leWorkspaceFactory Dim wks As IFeatureWorkspace Set wks = wksFact.OpenFromFile(“c:\Data\shp”, 0) ‘ open the featureClass Dim fc As IFeatureClass Set fc = wks.OpenFeatureClass(“BigCypress”) ‘ create a featureLayer Dim lyr As IFeatureLayer Set lyr = New FeatureLayer Set lyr.FeatureClass = fc ‘ name the layer with the featureClass name Dim ds As IDataset Set ds = fc lyr.Name = ds.Name ‘ add the layer to the map Dim mxDoc As IMxDocument Set mxDoc = Application.Document Dim map As IMap Set map = mxDoc.FocusMap map.AddLayer lyr End Sub FeatureLayers管理的一个要素的选择集,并且暴露IFeatureSelection接口来操作这个选择集。例6的代码通过使用一个SQL的WHERECLAUSE查询语句得到一个选择集。 例 6 Sub SelectFeatures() Dim mxDoc As IMxDocument Set mxDoc = Application.Document ‘ fi nd the layer we’re going to select from Dim lyr As IFeatureLayer Set lyr = FindLayer(mxDoc.FocusMap, “BigCypress”) ‘ get the layer’s selection interface Dim sel As IFeatureSelection Set sel = lyr ‘ create a query filter Dim filter As IQueryFilter Set filter = New QueryFilter ‘ set up the where clause and the spatial reference filter.WhereClause = “NAME = ‘Hampton’” Dim shapeField As String shapeField = lyr.FeatureClass.ShapeFieldName Set filter.OutputSpatialReference(shapeField) =_ mxDoc.FocusMap.SpatialReference ‘ invalidate the current selection on the display mxDoc.ActiveView.PartialRefresh_ esriViewGeoSelection, Nothing, Nothing ‘ select features and invalidate the new selection sel.SelectFeatures fi lter,_ esriSelectionResultNew, False mxDoc.ActiveView.PartialRefresh_ esriViewGeoSelection, Nothing, Nothing ‘ notify everyone that we’ve modifi ed the selection Dim selEvents As ISelectionEvents Set selEvents = mxDoc.FocusMap selEvents.SelectionChanged End Sub 这段代码中的IFeatureSelection接口上的SelecFeatures方法完成了所有的工作。QueryFilter对象为选择定义了标准。WhereClause属性为SQL表达式而设置,OutputSpatialReference属性用来控制要素如何进行动态投影,当它们从数据库中取出的时候。为了指明一个空间限制条件,你可以使用SpatialFilter对象来替换QueryFilter。 调用IActievView的PartialRefresh方法有目的地重绘显示区,旧的选择区被擦除并且新的选择区被绘制。最后三行通过ISelectionEvents接口调用SelectionChanged方法。这一方法通知那些系统中的通过地图注册的组件,选择已经改变了。属性表窗口(Attribute Table Window)侦听选择事件,以致它能同步的高亮显示与选择相匹配的行。如果图8所示的代码没有调用SelectionChanged方法,表窗口(Table Window)将不会反映激活视图中的选择。这种在ArcObjects中普遍使用的交流方式被称为处理事件过程(working with events)。 5、响应事件 直到现在我们只考虑了用代码操作ArcObjects,从最顶端的对象开始,浏览了用到的对象。ArcObjects一个有趣的方面是能够将对象模型和关联代码进行整合,这些代码只要有一些特别的事情发生就会执行,比如说地图选择集的改变。很多对象模型都能触发事件。COM提供了一个机制监听和响应事件。 如果你是用VBA或Visual Basic,大部分幕后的线程都需要响应事件。你只需要为每个你感兴趣的事件编写代码,这个代码就开始侦听事件。例7所示的例子表明了在VBA环境下如何处理事件。下面的代码用WithEvents语句声明了一个全局变量。WithEvents告诉开发环境对象变量将用来响应对象事件。 Dim WithEvents g_Map As Map 变量声明后,就可以从VBA的对象下拉列表中选择。单击过程下拉列表框将显示Map对象所暴露的变量事件。这个例子使用SelectionChanged方法来编写代码。例7所示的代码响应SelectionChanged事件,只要选择集发生了改变,地图就能触发这个事件,并且用户窗体的列表框会显示选中要素的名字。 例 7 Private Sub g_Map_SelectionChanged() ‘ show the form if it’s not visible If Not UserForm1.Visible Then UserForm1.Show vbModeless End If ‘ clear any previous results in the list UserForm1.ListBox1.Clear ‘ get the map’s selection Dim activeView As IActiveView Set activeView = g_Map ‘ enumerate over the selected features Dim featureEnum As IEnumFeature Set featureEnum = activeView.Selection featureEnum.Reset ‘ reset the cursor Dim feat As IFeature Set feat = featureEnum.Next Do While Not feat Is Nothing ‘ add the feature’s name to the list Dim index As Long index = feat.Fields.FindField(“Name”) If index <> -1 Then UserForm1.ListBox1.AddItem feat.Value(index) End If Set feat = featureEnum.Next ‘ get next feature Loop End Sub 在显示用户窗体,清除列表框以后,代码从地图的IActiveView接口获得一个选择集。选择集的IEnumFeature接口用来浏览选择要素的集合,返回一个IFeature接口。代码搜索每一个要素字段集的Name字段。如果找到Name字段,它的值就加到列表框中。 最后一步是初始化全局变量g_Map,如例8所示。一旦这段代码被运行,只要选择集发生变化例7中的代码就执行,并且列表框将被选择集所更新。 例 8 Sub StartListening() Dim mxDoc As IMxDocument Set mxDoc = Application.Document Set g_Map = mxDoc.FocusMap End Sub 注:ArcObjects的更新很快,目前的版本已到8.2,不久就会有8.3,甚至是9。随着每次版本的更新都会有新的对象和接口发布,所以对于开发者来说,要密切注意版本的变化。 |
|
1楼#
发布于:2003-07-29 19:20
已阅
|
|
|
2楼#
发布于:2003-08-02 01:30
good
|
|