『公告』 预祝您龙年大吉,万事如意, 过节期间, 大家如需数据服务,请拨打400 或直接添加客服微信,再祝大家龙年,心想事成。
关注我们 新浪 腾讯

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

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

       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)

        {

        }

    }

      京ICP备2025132830号-1 京公网安备 号