|
|
|
|

ArcGIS Engine开发-TOCControl中实现图层的拖放

ArcGIS Engine开发-TOCControl中实现图层的拖放TOCControl非常好,不用写一行代码就可以将整个地图的图层信息况显示出来;TOCControl也非常坏,提供的接口非常少,我认为有用的只有三个:HitTest,SetBuddyControl,Update,而且Update方法一执行,整个TocC...

作者:未知来源:BBS|2009年06月12日

ARCGIS Engine开发-TOCControl中实现图层的拖放
TOCControl非常好,不用写一行代码就可以将整个地图的图层信息况显示出来;TOCControl也非常坏,提供的接口非常少,我认为有用的只有三个:HitTest,SetBuddyControl,Update,而且Update方法一执行,整个TocControl就会重新装载一次,闪烁很厉害,实在是让人烦。要想在TOCControl中拖动图层,也并不容易,得动一动脑筋才行。

下面是我写的一个类,用于实现拖动图层,有需要的朋友,可以复制过去了,看一看。
需要说明的是,该类需要传入一个System.Windows.Forms.Control作为移动图层时显示要移到的位置,所以,在TOCControl上最好上一个Panel,然后传入到TocHelper中。另外,在计算同m_MovingLine显示的位置时,偶没找到什么好办法,只好设置了一个行高的参数。在正常字体时,据我的经验,行高是16,在Windows大字体显示时,行高是18,可以精确的显示。但这毕竟不是一个好办法。哪位高人要是看到了这个帖子,也请指点小弟一二,感激不尽!


public class TocHelper
    {
        private ESRI.ARCGIS.TOCControl.AxTOCControl m_toc;
        private ILayer m_layer = null;
        private object m_other,m_index;

        private LayerPopmenu m_LyMenu ;
        private DataFramePopmenu m_FrameMenu = new DataFramePopmenu();

        public event CurrentLayerChangedHandler CurrentLayerChanged;

        private bool m_Dragging = false;
        private System.Windows.Forms.Control m_MovingLine;// = new System.Windows.Forms.Panel();

        public TocHelper(ESRI.ARCGIS.TOCControl.AxTOCControl toc)
        {
            m_toc = toc;
            m_LyMenu = new LayerPopmenu(this);
            m_LyMenu.TOCControl = m_toc;
            m_FrameMenu.TOCControl = m_toc;

            m_toc.LabelEdit = esriTOCControlEdit.esriTOCControlManual;
            /**////处理事件
            m_toc.OnMouseDown += new ITOCControlEvents_OnMouseDownEventHandler(m_toc_OnMouseDown);
            m_toc.OnMouseMove += new ITOCControlEvents_OnMouseMoveEventHandler(m_toc_OnMouseMove);
            m_toc.OnMouseUp += new ITOCControlEvents_OnMouseUpEventHandler(m_toc_OnMouseUp);
            m_toc.OnBeginLabelEdit += new ITOCControlEvents_OnBeginLabelEditEventHandler(m_toc_OnBeginLabelEdit);
            m_toc.OnEndLabelEdit += new ITOCControlEvents_OnEndLabelEditEventHandler(m_toc_OnEndLabelEdit);
        }

        public void SetMoveLine(System.Windows.Forms.Control line)
        {
            m_MovingLine = line;
            m_MovingLine.Size = new System.Drawing.Size(100,2);
            m_MovingLine.BackColor = System.Drawing.Color.Black;
            m_MovingLine.Visible = false;
        }

        private DevExpress.XtraBars.BarManager m_pBarManager;
        public void SetBarManager(DevExpress.XtraBars.BarManager barMan)
        {
            m_pBarManager = barMan;
            m_LyMenu.SetBarManager(barMan);
            m_FrameMenu.SetBarManager(barMan);
        }

        /**//// <summary>
        /// 获取当前图层
        /// </summary>
        public ESRI.ARCGIS.Carto.ILayer CurrentLayer
        {
            get
            {
                return m_layer;
            }           
        }

        /**//// <summary>
        /// 刷新视图
        /// </summary>
        /// <param name="layer"></param>
        private void RefreshView(ILayer layer)
        {
            if (m_toc == null)
                return;
            if (m_toc.Buddy == null)
                return;

            IActiveView pView = null;
            if (m_toc.Buddy is  ESRI.ARCGIS.MapControl.IMapControl2)
            {
                pView = (m_toc.Buddy as ESRI.ArcGIS.MapControl.IMapControl2).ActiveView;
            }
            else if (m_toc.Buddy is ESRI.ArcGIS.SceneControl.ISceneControl)
            {
                IScene scene = (m_toc.Buddy as ESRI.ArcGIS.SceneControl.ISceneControl).Scene;
                if (scene is IActiveView)
                    pView = scene as IActiveView;
            }

            if (pView != null)
            {
                if (layer != null)
                    pView.PartialRefresh(esriViewDrawPhase.esriViewGeography,layer,pView.Extent);
                else
                    pView.Refresh();
           
            }               
        }

        private int m_DragStartY;
        public int MouseX,MouseY;
        private int m_TextHeight = 18;
        private void m_toc_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
        {
            /**////选中对象           
            ITOCControl m_TOCControl = (ITOCControl) m_toc.Object;
            esriTOCControlItem item =esriTOCControlItem.esriTOCControlItemNone;
            ILayer layer = null;
            IBasicMap map = null;           
            m_TOCControl.HitTest(e.x,e.y,ref item,ref map,ref layer,ref m_other,ref m_index);
            MouseX = e.x;MouseY =e.y;
            m_DragStartY = e.y;

            //设置当前图层
//            if (item == esriTOCControlItem.esriTOCControlItemLayer)
//            {
                if (m_layer != layer)
                {
                    m_layer = layer;
                    if (CurrentLayerChanged != null)
                        CurrentLayerChanged();
                }
//            }
//            else
//            {
//                if (m_layer != null)
//                {
//                    m_layer = null;
//                    if (CurrentLayerChanged != null)
//                        CurrentLayerChanged();
//                }
//            }
            m_LyMenu.CurrentLayer = m_layer;
            m_FrameMenu.CurrentLayer = m_layer;

            //如果点中的图例,则弹出符号设置窗口
            if ((e.button == 1) && (item == esriTOCControlItem.esriTOCControlItemLegendClass))
            {
                ILegendGroup legendGroup;
                ILegendClass legendClass;
                legendGroup = m_other as ILegendGroup;
                Debug.Assert(legendGroup != null);
                legendClass = legendGroup.get_Class(Convert.ToInt32(m_index.ToString()));
                Debug.Assert(legendClass != null);
                ISymbol pSymbol = legendClass.Symbol;

                //选择符号窗口代码去掉了。
                return;

            }
           
            //如果是鼠标右键,则弹出右键菜单
            if (e.button == 2)
            {
                System.Diagnostics.Debug.Assert(m_pBarManager != null);
                if ((item == esriTOCControlItem.esriTOCControlItemLayer) && (layer != null))
                {
                    m_pBarManager.SetPopupContextMenu(m_toc,m_LyMenu.PopMenu);
                }
                else if (item == esriTOCControlItem.esriTOCControlItemMap)
                {
                    m_pBarManager.SetPopupContextMenu(m_toc,m_FrameMenu.PopMenu);
                }
                else
                {
                    m_pBarManager.SetPopupContextMenu(m_toc,null);
                }
                return;
            }

           
            //如果鼠标左键选中了一个图层,则设为拖动状态
            if ((e.button == 1) && (layer != null))
            {
                m_Dragging = true;
                m_DestLayer = null;
            }

           
            m_TextHeight = m_toc.Parent.Font.Height+2;
           
        }

        private int GetLayerIndex(IBasicMap map,ILayer layer,bool DragUp)
        {
            ILayer tmpLayer;
            for (int i=0;i<=map.LayerCount-1;i++)
            {
                tmpLayer = map.get_Layer(i);
                if (tmpLayer == layer)
                {   
                    if (DragUp == true)
                        return i-1;
                    else
                        return i;
                }
            }
            return 0;
        }

        private int GetLayerIndex(ICompositeLayer groupLayer,ILayer layer,bool DragUp)
        {
            for (int i=0;i<=groupLayer.Count-1;i++)
            {
                if (groupLayer.get_Layer(i) == layer)
                {
                    if (i == groupLayer.Count-1)
                        return i;
                    else
                    {
                        if (DragUp == true)
                            return i;
                        else
                            return i+1;
                    }
                   
                }
            }
            return 0;
        }

        private ILayer m_DestLayer;
        private bool m_DestIsMap = false;
        private bool m_DragToCorrectPos = false;
        private void m_toc_OnMouseMove(object sender, ITOCControlEvents_OnMouseMoveEvent e)
        {
            /**////如果正在拖动图层
            if (m_Dragging == true)
            {
                m_DragToCorrectPos = false;

                ITOCControl m_TOCControl = (ITOCControl) m_toc.Object;
                esriTOCControlItem item =esriTOCControlItem.esriTOCControlItemNone;
                ILayer layer = null;
                IBasicMap map = null;
                object other = null;
                object index = null;
                m_TOCControl.HitTest(e.x,e.y,ref item,ref map,ref layer,ref other,ref index);
               
                m_DestIsMap = false;
                m_DestLayer = layer;
                if (item == esriTOCControlItem.esriTOCControlItemMap)
                {
                    m_DestIsMap = true;

                    int yy;                   
                    yy = Convert.ToInt32(Math.Floor(e.y/m_TextHeight) * m_TextHeight)+m_TextHeight;

                    m_MovingLine.Location = new System.Drawing.Point(30,yy);
                    m_MovingLine.Width = m_toc.Width - 35;
                    m_MovingLine.Visible = true;
                    m_toc.MousePointer = ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerDefault;                   
                    m_DragToCorrectPos = true;
                               
                }
                else if ((item == esriTOCControlItem.esriTOCControlItemLayer) && (layer != m_layer) && (layer != null))
                {
                    if (m_DestLayer is IGroupLayer)
                    {
                        m_MovingLine.Visible = false;
                        m_toc.MousePointer = ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerLabel;
                        m_DragToCorrectPos = true;
                    }
                    else
                    {
                        int yy;                   
                        if (e.y > m_DragStartY)  //向下拖放
                        {
                            yy = Convert.ToInt32(Math.Floor(e.y/m_TextHeight) * m_TextHeight)+m_TextHeight;
                        }
                        else  //向上拖放
                        {
                            yy = Convert.ToInt32(Math.Floor(e.y/m_TextHeight) * m_TextHeight);                       
                        }
                        m_MovingLine.Location = new System.Drawing.Point(30,yy);
                        m_MovingLine.Width = m_toc.Width - 35;
                        m_MovingLine.Visible = true;
                        m_toc.MousePointer = ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerDefault;                   
                        m_DragToCorrectPos = true;
                    }
                }
                else
                {
                    m_MovingLine.Visible = false;
                    m_toc.MousePointer = ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerDefault;
                }
               
            }
        }

        /**//// <summary>
        /// 取得图层的上一级对象,可能是igrouplayer,或ibasicmap
        /// </summary>
        /// <param name="map"></param>
        /// <param name="layer"></param>
        /// <returns></returns>
        private object GetLayerParent(IBasicMap map,ILayer layer)
        {
            ILayer tmpLayer;
            for (int i=0;i<= map.LayerCount-1;i++)
            {
                tmpLayer = map.get_Layer(i);
                if (tmpLayer == layer)
                {
                    return map;
                }
                else if (tmpLayer is IGroupLayer)
                {
                    IGroupLayer ly = FindParentGroupLayer(tmpLayer as IGroupLayer,layer);
                    if (ly != null)
                        return ly;
                }
            }
            return map;
        }

        private IGroupLayer FindParentGroupLayer(IGroupLayer groupLayer,ILayer layer)
        {
            if (!(groupLayer is ICompositeLayer))
            {
                return groupLayer;
            }

            ICompositeLayer comLayer = groupLayer as ICompositeLayer;
            ILayer tmpLayer;
            for (int i=0;i<=comLayer.Count-1;i++)
            {
                tmpLayer = comLayer.get_Layer(i);
                if (tmpLayer == layer)
                    return groupLayer;
                else if (tmpLayer is IGroupLayer)
                    return FindParentGroupLayer(tmpLayer as IGroupLayer,layer);
            }
            return null;
        }

        /**//// <summary>
        /// 在grouplayer中移动图层
        /// </summary>
        /// <param name="pGroupLayer"></param>
        /// <param name="pLayer"></param>
        /// <param name="nIndex"></param>
        private void MoveLayerTo(IGroupLayer pGroupLayer, ILayer pLayer, int nIndex)
        {

            ICompositeLayer pCompositeLayer = pGroupLayer as ICompositeLayer;
//            if(pCompositeLayer.Count < 2)
//                return ;

            if(pCompositeLayer.Count-1 == nIndex)
            {
                pGroupLayer.Delete(pLayer);
                pGroupLayer.Add(pLayer);
                return;
            }

            IArray pArray = new ArrayClass();

            for(int i = 0; i < pCompositeLayer.Count; i++)
            {
                pArray.Add(pCompositeLayer.get_Layer(i));
            }

            pGroupLayer.Clear();
            ILayer pLayer1;
            for(int i = 0; i < pArray.Count; i++)
            {
                if(pCompositeLayer.Count  == nIndex)
                {
                    pGroupLayer.Add(pLayer);
                }

                pLayer1  = pArray.get_Element(i) as ILayer;
                if(pLayer1 == pLayer)
                {
                    continue;
                }
                pGroupLayer.Add(pLayer1);

            }           
        }

        private void m_toc_OnMouseUp(object sender, ITOCControlEvents_OnMouseUpEvent e)
        {
            if (m_Dragging == true)
            {
                check dragging conditions#region check dragging conditions
                m_Dragging = false;
                m_toc.MousePointer = ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerDefault;
                if (m_toc == null)
                    return ;
                if (m_toc.Buddy == null)
                    return ;
                if (m_DragToCorrectPos == false)
                    return;
                m_DragToCorrectPos = false;
                m_MovingLine.Visible = false;

                IMap map=null;
                IScene scene=null;
                if (m_toc.Buddy is IMapControl2)
                {
                    map = (m_toc.Buddy as IMapControl2).Map;
                }
                else if (m_toc.Buddy is ESRI.ArcGIS.SceneControl.ISceneControl)
                {
                    scene = (m_toc.Buddy as ESRI.ArcGIS.SceneControl.ISceneControl).Scene;
                }
                else
                {
                    return;
                }

                IBasicMap bmap;
                if (map != null)
                    bmap = map as IBasicMap;
                else
                    bmap = scene as IBasicMap;
                if (bmap.LayerCount ==0)
                    return;

                #endregion

                bool destIgnoreGroupLayer = false;
                if (m_DestIsMap == true)
                {
                    m_DestLayer = bmap.get_Layer(0);
                    destIgnoreGroupLayer = true;
                }

                if (m_DestLayer == null)
                    return;
                if (m_layer == m_DestLayer)
                    return;

                bool DragUp;  //是否正向上拖放
                DragUp = (e.y < m_DragStartY);
                int destIndex;

                object buddy = m_toc.Buddy;
                m_toc.SetBuddyControl(null);

                try
                {
                    object srcGroupLayer = GetLayerParent(bmap,m_layer);
                    object destGroupLayer = GetLayerParent(bmap,m_DestLayer);               
               
                    //先删除源图层
                    if (srcGroupLayer is GroupLayer)
                        (srcGroupLayer as IGroupLayer).Delete(m_layer);
                    else
                        bmap.DeleteLayer(m_layer);

                    //再加入,并移到合适位置
                    if ((m_DestLayer is IGroupLayer) && (destIgnoreGroupLayer == false))
                    {
                        (m_DestLayer as IGroupLayer).Add(m_layer);
                        destIndex = GetLayerIndex(m_DestLayer as ICompositeLayer,m_layer,DragUp);                   
                   
                        MoveLayerTo(m_DestLayer as IGroupLayer,m_layer,destIndex);
                        RefreshView(m_DestLayer);                                       
                    }
                    else if (destGroupLayer is IGroupLayer)
                    {                   
                        (destGroupLayer as IGroupLayer).Add(m_layer);
                        destIndex = GetLayerIndex(destGroupLayer as ICompositeLayer,m_DestLayer,DragUp);                   
                                       
                        MoveLayerTo(destGroupLayer as IGroupLayer,m_layer,destIndex);   
                        RefreshView(destGroupLayer as ILayer);
                    }
                    else
                    {
                        bmap.AddLayer(m_layer);
                        destIndex = GetLayerIndex(bmap,m_DestLayer,DragUp);
                                           
                        if (bmap is IMap)
                            (bmap as IMap).MoveLayer(m_layer,destIndex);
                        else if (bmap is IScene)
                            (bmap as IScene).MoveLayer(m_layer,destIndex);                   
                    }   
   
                }
                finally
                {
                    m_toc.SetBuddyControl(buddy);  //重新绑定,并刷新toc
                }

            }
        }

        private void m_toc_OnBeginLabelEdit(object sender, ITOCControlEvents_OnBeginLabelEditEvent e)
        {
            e.canEdit = false;
        }

        private void m_toc_OnEndLabelEdit(object sender, ITOCControlEvents_OnEndLabelEditEvent e)
        {
        }

    }

上一篇:ArcGIS Engine+最短路径分析(C#源码)

下一篇:ArcGIS Engine+C#缓冲区分析文档及完整源码