ArcObjects

ArcObjects是一个COM组件的集合,它是ArcInfo 8的两个新应用程序的基石,即ArcMap和ArcCatalog。这一系列的组件包含了超过1200个对象,它们可以用来定制、扩展和构建GIS应用程序。乍一看来,这么大的一个对象模型看起来真有点让人喘不过气来。仔细看一下ArcMap的对象模型你会发现它和其它一些大的对象模型的基本组成很相似。
1、基础构架

图片 1

图1显示了ArcMap的概念对象模型。顶端的对象MxApplication代表ArcMap本身。MxApplication只管理一个文档MxDocument。与ArcView GIS不同的是ArcMap使用单文档界面。MxDocument管理一组Map对象和一个PageLayout对象。在数据视图下,ActiveView是一个Map;而在页面视图下,ActiveView是PageLayout。无论在何种视图下,总是只有一个FocusMap。
例 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”。

图片 2

注意例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。随着每次版本的更新都会有新的对象和接口发布,所以对于开发者来说,要密切注意版本的变化。 


 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值