AO中的GraphicsLayer---------元素的容器

时间:2022-05-13 15:16:28

come from AO中的GraphicsLayer---------元素的容器

图形元素(Graphic Element)是存储于GraphicsLayer中的,本文主要涉及的接口和类主要有以下几种:

IGraphicsContainer、IGraphicsLayer、ICompositeGraphicsLayer、GraphicsSubLayer类、CompositeGraphicsLayer类。

GraphicsSubLayer类主要实现了接口IGraphicsContainer、IGraphicsLayer、ILayer.

CompositeGraphicsLayer类实现了接口IGraphicsContainer、IGraphicsLayer、ILayer、ICompositeGraphicsLayer

IMap接口的BasicGraphicsLayer在AE的帮助文档中显示的得到的是一个IGraphicsLayer,但是其实IMap.BasicGraphicsLayer并不仅仅是IGraphicsLayer这么简单,它其实在实质上可以看作是一个CompositeGraphicsLayer的对象,为什么这么说呢?由于ArcGIS是基于COM标准开发的,所以它所有的属性或者方法都是返回的某个接口,而不是某个具体的类。为了探明IMap.BasicGraphicsLayer的本质是什么类型,我做了一个检测,检测过程如下:

IMap Map1 = axMapControl1.Map;

IGraphicsLayer gl = Map1.BasicGraphicsLayer;

我们现在可以肯定的是gl是IGraphicsLayer接口类型,我查看了一下AE的帮助,CompositeGraphicsLayer类实现了包括IGraphicsLayer接口在内的22个普通接口以及2个事件接口。如果BasicGraphicsLayer实际上是CompositeGraphicsLayer的实例,那么gl就应该实现了CompositeGraphicsLayer中所有的接口,所以我在调试状态下,在即时窗口中依次对这个20多个接口进行如下测试,比如测试第一个接口IBarrierProperties的语句如下,在即时窗口中输入gl is IBarrierProperties,回车,得到的结果是true,也就是说gl实现了IBarrierProperties接口,我依次对22个普通接口进行测试,发现返回的都是true,但是在对两个事件接口ISelectionEvents和IGraphicsContainerEvents进行测试时,却返回了false,不过由于事件接口比较特殊,我们可以忽略不计。综上,BasicGraphicsLayer实现了CompositeGraphicsLayer中的所有普通接口,现在我们有充分的理由认为BasicGraphicsLayer在本质上是一个CompositeGraphicsLayer类的实例对象。

我们现在再来看一下GraphicsSubLayer类,通过名字Sub就可以看出这是一个子图层,之所以称之为“子图层”,这是相对于复合图形图层CompositeGraphicsLayer来说的。我们可以把CompositeGraphicsLayer看作是GraphicsSubLayer的容器,我们甚至还可以简单的这么认为CompositeGraphicsLayer是一个画本,而GraphicsSubLayer是画本中的一页纸。我们画画的时候既可以直接无规律的画在画本上,也可以有规律的将不同类型的画画在不同的纸张上。

一个Map对象都管理着一个CompositeGraphicsLayer对象,也就是说一个Map就对应着一个画本,但是画本中的纸张数目确实不确定的。

既然我们既可以把在画本(CompositeGraphicsLayer)上画画,又可以在画本内的某个纸张(GraphicsSubLayer)上画画,那我们在画画的时候什么时候应该画在画本上,什么时候又应该画在画本内的纸张上呢?

在一般情况下,我们如果想在Map中添加Graphic Element(图形元素),我们为了简单,可以直接画在画本上,即使用CompositeGraphicsLayer,下面的函数演示了如何通过CompositeGraphicsLayer在Map上画一个Graphic Element:

private void AddGraphicElementByCompositeGraphicsLayer(IGraphicElement element)

{

IMap Map1 = axMapControl1.Map;

IGraphicsLayer gl = Map1.BasicGraphicsLayer;

IGraphicsContainer gc = gl as IGraphicsContainer;

gc.AddElement(element, 0);

axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

}

有人可能要问,上面的代码根本就没有出现"CompositeGraphicsLayer",怎么能说是将图形元素画在了CompositeGraphicsLayer上呢?

IGraphicsContainer gs = gl as IGraphicsContainer;

这句代码是关键,这句代码使得gl从CompositeGraphicsLayer类的IGraphicsLayer接口QI到了CompositeGraphicsLayer类的IGraphicsContainer接口,相当于CompositeGraphicsLayer对象内置了一页特殊的纸张,可以作为画纸使用。

那我们又应该什么时候将图形画在GraphicsSubLayer上呢?当我们要为了有规律的管理不同类型的图形元素的时候就应该使用GraphicsSubLayer,也可以使用GraphicsSubLayer与TOC中某个具体的FeatureLaeyr进行联系起来,下面的函数演示了如何向某GraphicsSubLayer中添加Graphic Element:

private void AddGraphicElementByGraphicsSubLayer(string SubLayerName, IGraphicElement element)

{

IGraphicsLayer sublayer = FindOrCreateGraphicsSubLayer(SubLayerName);//返回的实际上是一个GraphicsSubLayer的实例对象

IGraphicsContainer gc = sublayer as IGraphicsContainer;//这里之所以可以QI,是因为GraphicsSubLayer同时实现了IGraphicsLayer和IGraphicsContainer

gc.AddElement(element, 0);

axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

}

private  IGraphicsLayer  FindOrCreateGraphicsSubLayer(string SubLayerName)

{

IMap Map1 = axMapControl1.Map;

IGraphicsLayer gl = Map1.BasicGraphicsLayer;

ICompositeGraphicsLayer cgl = gl as ICompositeGraphicsLayer;

IGraphicsLayer sublayer ;

sublayer = cgl.FindLayer(SubLayerName);//查找CompositeGraphicsLayer中有没有名为SubLayerName的GraphicsSubLayer

if (sublayer == null)

{

sublayer = cgl.AddLayer(SubLayerName, null);//ICompositeGraphicsLayer.AddLayer方法其实返回的是一个GraphicsSubLayer的实例对象

}

return sublayer;

}

这里我要强调一下这句代码sublayer
= cgl.AddLayer(SubLayerName, null);

我们查看一下函数原型

向我在本文开头提到的一样,基于COM的AO的方法返回的都是某个接口,而不是某个类型的对象。那么AddLaeyr到底返回的是什么类型呢?其实返回的是GraphicsSubLayer类型,我已经测试过,测试方法与之前测试的过程相同,不再赘述。注意,AddLayer方法中有一个IFeatureLaeyr类型的参数,该参数可以使TOC中某个要素类图层,从而使得该FeatureLayer与该GraphicsSubLayer相互关联;如果传入的FeatureLayer的参数为null,那么该GraphicsSubLayer不会与任何要素图层关联。以下内容为AE的帮助文档中IMap.ActiveGraphicsLayer的备注部分,由于英文内容相对不是很难,就不翻译了,大家自己看一下:Three
different objects contain and persist graphic elements: a Map, thePageLayout,
and anFDOGraphicsLayer.  Both the Map and the PageLayout store (persist)
their graphics in the document; FDOGraphicsLayers store their graphics in a
database (an FDOGraphics layer is a feature annotation layer).In ArcMap,
graphic elements are kept in graphics layers (GraphicLayers objects).  To
manage all of the graphic layers, the Map has the CompositeGraphicsLayer
object.  The CompositeGraphicsLayer object has a collection of
GraphicsLayers and it implements theICompositeGraphicsLayer interface which provides
methods for creating, finding, and deleting GraphicsLayers.  New graphics
layers are sometimes called 'Groups' or 'Annotation Target Layers'. Not only
does the CompositeGraphicsLayer object have a collection of graphics layers,
but it is itself a graphics layer - like the FDOGraphicsLayer object, it
inherits from the GraphicsLayer object.  This means that the
CompositeGraphicsLayer object has its own graphics Container where graphic elements can be
stored.  The graphics layer it provides is called the 'Basic Graphics
Layer'.  This Basic Graphics Layer is the default graphics layer and it
cannot be deleted.The CompositeGraphicsLayer objects implements the
ICompositeLayer interface, among others, which has the propertiesCount andLayer
.  The Count does not include the Basic Graphics Layer and the Layer
property cannot be used to access the basic graphics layer.  This is
because the Basic Graphics Layer is essentially the CompositeGraphicsLayer
object whereas the Groups are separate GraphicsLayer objects. 
TheBasicGraphicsLayer property always returns a reference to the Basic Graphics
Layer (the CompositeGraphicsLayer object) and from here you can query interface
for the other interfaces implemented by the object including those on the
GraphicsLayer object.

The Map's ActiveGraphicsLayer property provides a reference to the graphics
layer currently active (sometimes this is called the 'Active Annotation Target
Layer).  By default the basic graphics layer is the active layer but any
Group or FDOGraphicsLayer is also settable as the active layer.

The CompositeGraphicsLayer and none of its GraphicsLayers (Groups) are real
layers like aFeatureLayer, aGroupLayer, or anFDOGraphicsLayer.  None of
these layers can be accessed with the Map'sLayers property and are not included
in theLayerCount.