ae的官方类库没有提供该控件,需要自己实现,不过也比较简单,原理或实现的思路是,另外增加一个axMapControl控件,把他的视图设为地图的全图范围,把当前地图的范围,在这个地图控件上用红色框画出来即可。
首先新建一个用户控件,名称设为MapEagle,在控件上拖拽一个axmapcontrol控件,名称设为axMapEagle ,用来显示地图。
接下来,增加一个自定义属性,用来和地图主窗口关联,使得axMapEagle 能获得当前地图的范围
1: private AxMapControl pMap;
2:
3: /// <summary>
4: /// 关联的地图控件
5: /// </summary>
6: public AxMapControl MapControl
7: {
8: set
9: {
10: if (value != pMap) pMap = value;
11: //this.axMapEagle.Extent = pMap.FullExtent;
12: pMap.OnMapReplaced += new IMapControlEvents2_Ax_OnMapReplacedEventHandler(pMap_OnMapReplaced);
13: pMap.OnExtentUpdated += new IMapControlEvents2_Ax_OnExtentUpdatedEventHandler(pMap_OnExtentUpdated);
14: }
15:
16: }
主地图控件的OnMapReplaced事件,使得当主地图窗口重新加载时,刷新axMapEagle 的视图范围,实现代码如下
1: void pMap_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
2: {
3:
4: for (int i = 0; i <= pMap.LayerCount; i++)
5: {
6: axMapEagle.AddLayer(pMap.get_Layer(i));
7: }
8: this.axMapEagle.Extent = pMap.FullExtent;
9:
10: IGraphicsContainer pGraphicsContainer = this.axMapEagle.Map as IGraphicsContainer;
11: IActiveView pActiveView = pGraphicsContainer as IActiveView;
12: pGraphicsContainer.DeleteAllElements();
13:
14: IElement pEle = Envelope2Element(pMap.Extent);
15: pGraphicsContainer.AddElement(pEle, 0);
16: pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
17: }
该事件中,首先将主地图的图层都加载到axMapEagle 控件中,然后将试图设为全图,接下来删除窗口中的所有Element,再往后就是把主地图的视图范围,在axMapEagle 的视图上画出来,采用创建element的方法实现,方法Envelope2Element 实现将视图范围IEnvelope转化为一个element,把axMapEagle的地图设为图形容器,把创建好的element加进去,然后刷新视图即可。
方法Envelope2Element 的实现过程,如下所示
1: private IElement Envelope2Element(IEnvelope env)
2: {
3: IRectangleElement pRectangleEle = new RectangleElementClass();
4: IElement pEle = pRectangleEle as IElement;
5: pEle.Geometry = env;
6:
7: IRgbColor pColor = new RgbColorClass();
8: pColor.RGB = 255;
9: pColor.Transparency = 255;
10:
11: ILineSymbol pOutline = new SimpleLineSymbolClass();
12: pOutline.Width = 1.5;
13: pOutline.Color = pColor;
14:
15: pColor = new RgbColorClass();
16: pColor.RGB = 255;
17: pColor.Transparency = 0;
18:
19: IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
20: pFillSymbol.Color = pColor;
21: pFillSymbol.Outline = pOutline;
22:
23: IFillShapeElement pFillshapeEle = pEle as IFillShapeElement;
24: pFillshapeEle.Symbol = pFillSymbol;
25: return pFillshapeEle as IElement;
26: }
到这里已经实现一半了,剩下当主地图视图放大或缩小后,鹰眼地图上的范围标示随之变化没有实现了。也就是主地图的OnExtentUpdated方法,它的官方说明是这样 “Fires after the extent (visible bounds) of the MapControl is changed.”当地图控件的可视范围变化后触发,正是我们想要的。它的实现和加载时一样,同样将变化后的视图范围在地图上绘制就可以了,不用重新加载地图,具体代码如下
1: void pMap_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
2: {
//删除已添加的Element
3: IGraphicsContainer pGraphicsContainer = this.axMapEagle.Map as IGraphicsContainer;
4: IActiveView pActiveView = pGraphicsContainer as IActiveView;
5: pGraphicsContainer.DeleteAllElements();
6:
7: IElement pEle = Envelope2Element(e.newEnvelope as IEnvelope );
8: pGraphicsContainer.AddElement(pEle, 0);
9: pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
10: }
工作已经完成90%了,呵呵,axMapEagle 控件都会适应主地图视图的变化,还缺的就是主地图视图要适应axMapEagle的视图变化。
即,当在鹰眼视图上点击时,主地图也要能够移动到点击的位置,这样才是真正的方便。要实现这样的功能,就要用到地图控件
的OnMouseDown事件,代码如下
1: private void axMapEagle_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
2: {
3: IRubberBand pBand = new RubberEnvelopeClass();
4: IGeometry pGeometry = pBand.TrackNew(axMapEagle.ActiveView.ScreenDisplay, null);
5:
6: if (pGeometry.IsEmpty)
7: {
8: IPoint pPt = new PointClass();
9: pPt.PutCoords(e.mapX, e.mapY);
10: //改变主控件的视图范围
11: pMap.CenterAt(pPt);
12: }
13: else
14: {
15: pMap.Extent = pGeometry.Envelope;
16: pMap.ActiveView.Refresh();
17: }
18: }
IRubberBand 接口的官方解释是”Provides access to members that control simple rubberbanding.”rubberbanding 翻译过来是‘橡皮带式生成线’;直译是提供控制简单橡皮带式生成线的权限,(英语水平太凹了,只能查字典直译了!)就是能够控制按下鼠标左键拉框时的框范围。该接口的TrackNew方法就是将拉框转换成一个地理要素,然后可以根据这个要素对地图范围进行设定。
大功告成,主地图和鹰眼实现双向互动了!