分享

自己用C#写的一个鹰眼类,功能比较齐全

 xenophobe 2015-04-11
基本上从开始学习AE就做鹰眼程序,学了这么长时间了,在开发过程中也写过几个鹰眼的类,但多多少少都不是太完美,今天有了一个再写一个的冲动,就写了一个,解决了以前那几个中的不足,特来分享

该鹰眼实现的主要功能:
1.鼠标左键在鹰眼地图窗口上点击,可以重新定位矩形框位置,主地图相应更新
2.鼠标移动到鹰眼地图窗口的矩形框内之后,鼠标变为手型样式
3.鼠标移动到鹰眼地图窗口的矩形框内之后,左键按住不放可以实现拖动矩形框定位,主地图相应更新
4.鼠标右键拉框绘制矩形框,重新定位,主地图相应更新
5.主地图加载数据和打开地图文档都可以正常更新
6.鹰眼的基本功能
在编写过程中遇到的最大问题:
主地图窗口加载和打开地图文档之后,鹰眼更新但不显示,或者显示异常。
找到的原因:两个地图对象中的空间坐标系统不一致
解决的办法:pSmallMap.SpatialReference = pMainMap.SpatialReference;

关于怎么使用:
加入该类之后,在你的主程序的代码中声明该类的全局变量,在form_Load函数中进行实例化,将你的鹰眼和主地图窗口实例的object作为形参传入。
例如:
  1. namespace YingYan
  2. {
  3.     public partial class Form1 : Form
  4.     {
  5.         private EagleEye.EagleEye eagleEye;
  6.         public Form1()
  7.         {
  8.             InitializeComponent();
  9.         }

  10.         private void Form1_Load(object sender, EventArgs e)
  11.         {
  12.             eagleEye = new EagleEye.EagleEye(axMapControl1.Object as IMapControlDefault, axMapControl2.Object as IMapControlDefault);
  13.         }
  14.     }
  15. }
复制代码




###########################################################
下面给出该类详细的代码


  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Diagnostics;

  6. using ESRI.ArcGIS.Controls;
  7. using ESRI.ArcGIS.Display;
  8. using ESRI.ArcGIS.Carto;
  9. using ESRI.ArcGIS.Geometry;
  10. using ESRI.ArcGIS.Geodatabase;

  11. namespace EagleEye
  12. {
  13.     public class EagleEye
  14.     {
  15.         private IMapControlDefault mainMapControl;  //主 MapControl 地图窗口
  16.         private IMapControlDefault smallMapControl; //鹰眼 MapControl 地图窗口
  17.         private IMap pMainMap;   //主地图
  18.         private IMap pSmallMap;   //鹰眼地图
  19.         private IActiveView pMainAV;  //主地图 ActiveView
  20.         private IActiveView pSmallAV;  //鹰眼地图 ActiveView
  21.         private IGraphicsContainer pSmallGpContainer;   //鹰眼地图 GraphicsContainer
  22.         private IEnvelope pEnv;      //记录地图的 Extent
  23.         private bool bCanDrag;      //鹰眼地图上的矩形框可移动的标志
  24.         private IPoint pPoint;      //在移动鹰眼地图上的矩形框的时候使用
  25.         private Stopwatch pTimer; //记录在左键按下到弹起的时间,根据间隔判断是不是长按左键,然后执行不同的动作

  26.         public IMapControlDefault MainMapControl
  27.         {
  28.             set { mainMapControl = value; }
  29.         }

  30.         public IMapControlDefault SmallMapControl
  31.         {
  32.             set { smallMapControl = value; }
  33.         }

  34.         //构造函数
  35.         public EagleEye(IMapControlDefault mainMapControl, IMapControlDefault smallMapControl)
  36.         {
  37.             this.mainMapControl = mainMapControl;
  38.             this.smallMapControl = smallMapControl;
  39.             pMainMap = mainMapControl.Map;
  40.             pSmallMap = smallMapControl.Map;
  41.             pMainAV = mainMapControl.ActiveView;
  42.             pSmallAV = smallMapControl.ActiveView;
  43.             pSmallGpContainer = pSmallMap as IGraphicsContainer;
  44.             bCanDrag = false;

  45.             //为主地图窗口 mainMapControl 添加事件
  46.             ((ESRI.ArcGIS.Controls.IMapControlEvents2_Event)mainMapControl).OnExtentUpdated +=
  47.                 new IMapControlEvents2_OnExtentUpdatedEventHandler(mainMapControl_OnExtentUpdated);
  48.             ((ESRI.ArcGIS.Controls.IMapControlEvents2_Event)mainMapControl).OnMapReplaced +=
  49.                 new IMapControlEvents2_OnMapReplacedEventHandler(mainMapControl_OnMapReplaced);
  50.             ((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)mainMapControl.ActiveView).ItemAdded +=
  51.                 new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemAddedEventHandler(mainMapControl_ItemAdded);
  52.             ((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)mainMapControl.ActiveView).ContentsCleared +=
  53.                 new ESRI.ArcGIS.Carto.IActiveViewEvents_ContentsClearedEventHandler(mainMapControl_ContentsCleared);
  54.             //为鹰眼地图窗口 smallMapControl 添加事件
  55.             ((ESRI.ArcGIS.Controls.IMapControlEvents2_Event)smallMapControl).OnMouseDown +=
  56.                 new IMapControlEvents2_OnMouseDownEventHandler(smallMapControl_OnMouseDown);
  57.             ((ESRI.ArcGIS.Controls.IMapControlEvents2_Event)smallMapControl).OnMouseMove +=
  58.                 new IMapControlEvents2_OnMouseMoveEventHandler(smallMapControl_OnMouseMove);
  59.             ((ESRI.ArcGIS.Controls.IMapControlEvents2_Event)smallMapControl).OnMouseUp +=
  60.                 new IMapControlEvents2_OnMouseUpEventHandler(smallMapControl_OnMouseUp);
  61.             //初次在鹰眼地图上画矩形框
  62.             pSmallAV.Extent = pMainAV.FullExtent;
  63.             pEnv = pSmallAV.Extent;
  64.             DrawRectangle(pEnv);
  65.         }

  66.         #region 鹰眼地图窗口的响应事件函数
  67.         void smallMapControl_OnMouseUp(int button, int shift, int X, int Y, double mapX, double mapY)
  68.         {
  69.             if (button == 1)
  70.             {
  71.                 pTimer.Stop();  //停止计时
  72.                 if (pTimer.Elapsed.Milliseconds <= 150)
  73.                 {
  74.                     //鼠标按下到弹起时间小于150毫秒,说明是单纯的点击,则
  75.                     mainMapControl.CenterAt(pPoint);
  76.                 }
  77.                 else
  78.                 {
  79.                     //时间大于150毫秒,说明是长按,应该就是发生了拖动的动作,则
  80.                     if (bCanDrag) //判断是否可拖动
  81.                     {
  82.                         double Dx, Dy;  //记录鼠标移动的距离
  83.                         Dx = mapX - pPoint.X;
  84.                         Dy = mapY - pPoint.Y;
  85.                         pEnv.Offset(Dx, Dy); //根据偏移量更改 pEnv 位置
  86.                         pPoint.PutCoords(mapX, mapY);
  87.                         IPoint pTempPoint = new PointClass();
  88.                         pTempPoint.PutCoords(pEnv.XMin + pEnv.Width/2,pEnv.YMin + pEnv.Height/2);
  89.                         mainMapControl.CenterAt(pTempPoint);
  90.                     }
  91.                 }
  92.                 bCanDrag = false;
  93.             }
  94.         }

  95.         void smallMapControl_OnMouseMove(int button, int shift, int X, int Y, double mapX, double mapY)
  96.         {
  97.             if (mapX > pEnv.XMin && mapY > pEnv.YMin && mapX < pEnv.XMax && mapY < pEnv.YMax)
  98.             //如果鼠标移动到矩形框中,鼠标换成小手,表示可以拖动
  99.             {
  100.                 //新建图标,我这里是将此类封装为dll了,所以我将图标资源作为嵌入的资源处理
  101.                 System.Drawing.Icon icon = new System.Drawing.Icon(this.GetType().Assembly.GetManifestResourceStream("EagleEye.MyIcon.ico"));
  102.                 smallMapControl.MouseIcon = (stdole.IPictureDisp)ESRI.ArcGIS.ADF.COMSupport.OLE.GetIPictureDispFromIcon(icon);
  103.                 smallMapControl.MousePointer = esriControlsMousePointer.esriPointerCustom;
  104.                 if (button == 2)
  105.                     //如果在内部按下鼠标右键,将鼠标换回原来的
  106.                     smallMapControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
  107.             }
  108.             else
  109.             {
  110.                 //在其他位置将鼠标设为默认的样式
  111.                 smallMapControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
  112.             }
  113.             if (bCanDrag)
  114.             {
  115.                 double Dx, Dy;  //记录鼠标移动的距离
  116.                 Dx = mapX - pPoint.X;
  117.                 Dy = mapY - pPoint.Y;
  118.                 pEnv.Offset(Dx, Dy); //根据偏移量更改 pEnv 位置
  119.                 pPoint.PutCoords(mapX, mapY);
  120.                 DrawRectangle(pEnv);
  121.             }
  122.         }

  123.         void smallMapControl_OnMouseDown(int button, int shift, int X, int Y, double mapX, double mapY)
  124.         {
  125.             if (button == 1) //左键按下
  126.             {
  127.                 if (mapX > pEnv.XMin && mapY > pEnv.YMin && mapX < pEnv.XMax && mapY < pEnv.YMax)
  128.                     bCanDrag = true; //如果指针落在鹰眼的矩形框中,标记可移动
  129.                 pTimer = new Stopwatch();   //开始计时,到鼠标弹起时结束计时
  130.                 pPoint = new PointClass();
  131.                 pPoint.PutCoords(mapX, mapY);  //记录点击的第一个点的坐标
  132.                 pTimer.Start();
  133.             }
  134.             else if (button == 2) //右键按下
  135.             {
  136.                 //在鹰眼地图上面拉个矩形框,然后根据矩形框的范围和位置更改主地图显示范围
  137.                 //这里说明一下为什么还用 mainMapControl.CenterAt(pTempPoint); 这个语句
  138.                 //我是为了更新主地图 OnExtentUpdated 事件中的 newEnvelope,
  139.                 //单独的给 Extent 赋值,newEnvelope 是拉框的范围,我们知道我们拉框的时候
  140.                 //不可能把宽高比例和地图中的宽高比例弄的刚好一样,那么就利用 CenterAt()
  141.                 //让它自己重新调整 newEnvelope,那么我们依赖 newEnvelope 在鹰眼地图中画
  142.                 //矩形框的比例就和地图的宽高比例一致了,当然也可以用其他的办法
  143.                 //其他地方的调整我也是用的这样的方法
  144.                 IEnvelope pEnvelope = ((MapControl)smallMapControl).TrackRectangle();
  145.                 IPoint pTempPoint = new PointClass();
  146.                 pTempPoint.PutCoords(pEnvelope.XMin + pEnvelope.Width / 2, pEnvelope.YMin + pEnvelope.Height / 2);
  147.                 mainMapControl.Extent = pEnvelope;
  148.                 mainMapControl.CenterAt(pTempPoint);
  149.             }
  150.         }
  151.         #endregion

  152.         #region 主地图窗口的响应事件函数
  153.         //地图中所有的数据删除后
  154.         void mainMapControl_ContentsCleared()
  155.         {
  156.             pSmallMap.ClearLayers();  //清空鹰眼地图中所有的图层
  157.             //刷新地图
  158.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pSmallAV.Extent);
  159.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, pSmallAV.Extent);
  160.         }

  161.         //往主地图中添加数据时发生
  162.         void mainMapControl_ItemAdded(object Item)
  163.         {
  164.             pSmallMap.ClearLayers();  //清空鹰眼地图中所有的图层
  165.             IFeatureLayer pFeatureLayer;
  166.             IFeatureClass pFeatureCls;
  167.             int count = mainMapControl.LayerCount;
  168.             //获得主地图中的图层数,然后遍历,往鹰眼地图中添加数据
  169.             //由于鹰眼地图较小,所以过滤点图层不添加
  170.             for (int i = count - 1; i >= 0; i--)
  171.             {
  172.                 pFeatureLayer = pMainMap.get_Layer(i) as IFeatureLayer;
  173.                 if (pFeatureLayer != null)
  174.                 {
  175.                     pFeatureCls = pFeatureLayer.FeatureClass;
  176.                     if (pFeatureCls.ShapeType != esriGeometryType.esriGeometryMultipoint
  177.                         && pFeatureCls.ShapeType != esriGeometryType.esriGeometryPoint)
  178.                     {
  179.                         pSmallMap.AddLayer(pFeatureLayer);
  180.                     }
  181.                 }
  182.             }
  183.             pSmallMap.SpatialReference = pMainMap.SpatialReference;   //设置鹰眼和主地图的坐标系统一致
  184.             pSmallAV.Extent = mainMapControl.FullExtent;   //设置鹰眼地图全图显示
  185.             pEnv = mainMapControl.Extent as IEnvelope;
  186.             DrawRectangle(pEnv);
  187.             //刷新鹰眼地图
  188.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pSmallAV.Extent);
  189.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, pSmallAV.Extent);
  190.         }

  191.         //主地图窗口更换地图文档后发生
  192.         void mainMapControl_OnMapReplaced(object newMap)
  193.         {
  194.             if (pSmallMap.LayerCount > 0)
  195.             //如果鹰眼地图中存在图层则删除它们
  196.             {
  197.                 pSmallMap.ClearLayers();
  198.             }
  199.             pSmallMap.SpatialReference = pMainMap.SpatialReference;    //这个很关键
  200.             IFeatureLayer pFeatureLayer = null;
  201.             ESRI.ArcGIS.Geodatabase.IFeatureClass pFeatCls;
  202.             int count = mainMapControl.LayerCount;
  203.             //获得主地图中的图层数,然后遍历,往鹰眼地图中添加数据
  204.             //由于鹰眼地图较小,所以过滤点图层不添加
  205.             for (int i = count - 1; i >= 0; i--)
  206.             {
  207.                 pFeatureLayer = mainMapControl.get_Layer(i) as IFeatureLayer;
  208.                 if (pFeatureLayer != null)
  209.                 {
  210.                     pFeatCls = pFeatureLayer.FeatureClass;
  211.                     if (pFeatCls.ShapeType != esriGeometryType.esriGeometryPoint &&
  212.                         pFeatCls.ShapeType != esriGeometryType.esriGeometryMultipoint)
  213.                     {
  214.                         pSmallMap.AddLayer(pFeatureLayer);
  215.                     }
  216.                 }
  217.             }
  218.             pSmallAV.Extent = mainMapControl.FullExtent;
  219.             pEnv = mainMapControl.Extent as IEnvelope;
  220.             DrawRectangle(pEnv);
  221.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, pSmallAV.Extent);
  222.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pSmallAV.Extent);
  223.         }

  224.         void mainMapControl_OnExtentUpdated(object displayTransformation, bool sizeChanged, object newEnvelope)
  225.         {
  226.             pEnv = newEnvelope as IEnvelope;
  227.             DrawRectangle(pEnv);
  228.         }
  229.         #endregion

  230.         //在鹰眼地图上面画矩形框
  231.         private void DrawRectangle(IEnvelope pEnvelope)
  232.         {
  233.             pSmallGpContainer.DeleteAllElements();  //清除之前绘制的矩形框
  234.             IRectangleElement pRectangleEle = new RectangleElementClass();
  235.             IElement pEle = pRectangleEle as IElement;
  236.             pEle.Geometry = pEnvelope;

  237.             IRgbColor pColor = new RgbColorClass();
  238.             pColor.Red = 255;
  239.             pColor.Green = 0;
  240.             pColor.Blue = 0;
  241.             pColor.Transparency = 255;
  242.             ILineSymbol pOutLine = new SimpleLineSymbolClass();
  243.             pOutLine.Width = 1.5;
  244.             pOutLine.Color = pColor;

  245.             pColor = new RgbColorClass();
  246.             pColor.Transparency = 0;
  247.             IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
  248.             pFillSymbol.Color = pColor;
  249.             pFillSymbol.Outline = pOutLine;

  250.             IFillShapeElement pFillShapeEle = pEle as IFillShapeElement;
  251.             pFillShapeEle.Symbol = pFillSymbol;
  252.             pSmallGpContainer.AddElement(pFillShapeEle as IElement, 0);
  253.             pSmallAV.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pSmallAV.Extent);
  254.         }
  255.     }
  256. }
复制代码



自己测试了,自己能见到的bug都修复了,如果大家还发现什么bug,欢迎指出,感激不尽,这样就会更完美了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多