编程 & 生活 -- 西西吹雪

开心工作,快乐生活 (原创文章,转载请注明出处)

导航

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

                
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)
        
{
        }


    }


posted on 2006-09-14 13:14  西西吹雪  阅读(5507)  评论(18编辑  收藏  举报