打造自己地图AxTOCContrl树形控件——XUTocControl(成功解决节点控件拖拽问题)...

it2024-10-26  14

   最近在搞应用于Windows平板电脑的系统开发,需要开发适用于平板电脑的地图控制控件取代ArcEngine自带的AxTOCContrl。

       搞控件开发太费脑啦,需要注意的逻辑关系很复杂 都晕倒啦!

        控件实现:地图图层控制(单个控制、图层集控制、整体控制)、图层收缩、控件图层节点拖拽,基本可以替代AE中的AxTocControl。

      

       本控件开发周期为1.5天,解决主要技术问题有节点的动态加载、收缩与展开高度的自动计算、节点控制图层的关闭与打开、节点的拖拽功能。

       控件XUTocControl实现,只有三个文件,如图:

      

      图层节点XUBarNode关键代码:

View Code using  System; using  System.Collections.Generic; using  System.ComponentModel; using  System.Drawing; using  System.Data; using  System.Linq; using  System.Text; using  System.Windows.Forms; using  ESRI.ArcGIS.Carto; using  ESRI.ArcGIS.Controls; using  System.Runtime.InteropServices; namespace  GC_Controls {      // 定义节点      public   partial   class  XUBarNode : UserControl     {          // 绑定的图层名          private   string  _LayerName;          // 是否关闭          private   bool  _IsClose  =   false ;          // 地图窗体          private   AxMapControl mapCtrl;          #region  定义属性          // 父节点容器          public  XUNaviBar ParentBarNode;          public   string  Text         {              get  {                  return   this .NodeLabel.Text;             }              set             {                  this .NodeLabel.Text  =  value;             }         }          public  Button Close         {              get  {                  return   this .btnClose;             }         }          // 节点字体          public  Font TextFont         {              set  {  this .NodeLabel.Font  =  value; }         }          // 图层值          public   string  Value         {              get  {                  return   this ._LayerName;             }              set  {                  this ._LayerName  =  value;             }         }          #endregion                  #region  构造函数          public  XUBarNode(XUNaviBar ParentBar, string  strText)         {             InitializeComponent();             ParentBarNode  =  ParentBar;              this .Text  =  strText;           mapCtrl = ((AxMapControl)ParentBar.Tag);         }          public  XUBarNode(XUNaviBar ParentBar,  string  strText, string  strValue)             : this (ParentBar,strText)         {              this .Value  =  strValue;         }          public  XUBarNode(XUNaviBar ParentBar,  string  strText,  string  strValue, object  tag)             :  this (ParentBar,strText,strValue)         {              this .Tag  =  tag;         }          #endregion          ///   <summary>          ///  打开关闭图层          ///   </summary>          ///   <param name="sender"></param>          ///   <param name="e"></param>          private   void  btnClose_Click( object  sender, EventArgs e)         {             CloseLayer(_IsClose);             mapCtrl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,  null null );             _IsClose  =   ! _IsClose;         }          ///   <summary>          ///  从外部控制:打开或关闭图层          ///   </summary>          ///   <param name="bClose"></param>          public    void  CloseLayer( bool  bClose)         {              if  ( ! bClose)             {                  this .btnClose.Text  =   " 打开 " ;                  // TODO :关闭图层                  if  ( this .Tag  !=   null )                 {                     ILayer2 tmpLayer  =  (ILayer2) this .Tag;                     tmpLayer.Visible  =  bClose;                 }             }              else             {                  this .btnClose.Text  =   " 关闭 " ;                  // TODO :关闭图层                  if  ( this .Tag  !=   null )                 {                     ILayer2 tmpLayer  =  (ILayer2) this .Tag;                     tmpLayer.Visible  =  bClose;                 }             }         }          /******************** 下面是实现拖拽的关键代码部分*********************/          private   void  XUBarNode_MouseDown( object  sender, MouseEventArgs e)         {              // 设置拖拽前的边框类型              this .BorderStyle  =  BorderStyle.Fixed3D;         }          ///   <summary>          ///  获取进入控件里的拖拽进行为类型          ///   </summary>          ///   <param name="sender"></param>          ///   <param name="e"></param>          private   void  XUBarNode_DragOver( object  sender, DragEventArgs e)         {              if  (e.AllowedEffect  ==  DragDropEffects.Move)             {                 e.Effect  =  DragDropEffects.Move;             }         }          ///   <summary>          ///  实现菜单拖拽          ///   </summary>          ///   <param name="sender"></param>          ///   <param name="e"></param>          private   void  XUBarNode_DragDrop( object  sender, DragEventArgs e)         {             XUBarNode item  =  (XUBarNode)e.Data.GetData( typeof (XUBarNode));             item.Dock  =  DockStyle.Bottom;             item.BorderStyle  =  BorderStyle.FixedSingle;              // 获取原来的父节点XUNaviBar,更新节点列表和长度             XUNaviBar parentBar  = item.ParentBarNode;             parentBar.NodeList.Remove(item);              // 重新计算高度             parentBar.Height = parentBar.BarHeight;              // 获取当前父节点,并更新列表和长度             XUNaviBar newPBar  =   this .ParentBarNode;              int  insertPosition = newPBar.NodeList.IndexOf( this );             newPBar.NodeList.Insert(insertPosition, item);              // 重新计算高度             newPBar.Height  =  newPBar.BarHeight;              // 加入控件(TODO:这里当前是将节点插件放在最后端,需要更改)              this .Parent.Controls.Add(item);         }          private   void  XUBarNode_MouseMove( object  sender, MouseEventArgs e)         {              if  (e.Button == MouseButtons.Left)             {                  // 开始对菜单节点项实施拖拽                 this .DoDragDrop(sender, DragDropEffects.Move);             }         }     } }

         父节点XUNaviBar 代码:

View Code namespace  GC_Controls {      public   partial   class  XUNaviBar : UserControl     {          #region  定义共有变量          private   int  _nodeHeight  =   30 ;          private   bool  IsExpand  =   true ;          // 地图窗体          private  AxMapControl mapCtrl;          private  XUNaviBar _ParentBar;          public  ILayer2 CompositeLayer;          #endregion          #region  定义属性          public  ArrayList NodeList = new  ArrayList();          public  ArrayList BarList  =   new  ArrayList();          public   object  Tag         {              get             {                  return  mapCtrl;             }              set             {                 mapCtrl  =  (AxMapControl)value;             }         }          public   string  Text         {              get             {                  return   this .BarText.Text;             }              set             {                  this .BarText.Text  =  value;             }         }          public   int  NodeHeight         {              get  {                  return   this ._nodeHeight;             }              set  {                  this ._nodeHeight  =  value;             }         }          public   int  BarHeight         {              get             {                  if  ( ! IsExpand)                 {                      this .Height  =   this .topPanel.Height;                 }                  else                 {                      this .Height  =   this .topPanel.Height  +   this .NodeList.Count  *   this ._nodeHeight +  GetAllBarHeight();                 }                  return   this .Height;             }              set             {                  this .Height  +=  value;             }         }          #endregion          public  XUNaviBar()         {             InitializeComponent();         }          public  XUNaviBar(XUNaviBar parentBar)         {              // 设置父节点              this ._ParentBar  =  parentBar;             InitializeComponent();         }          public  XUNaviBar(XUNaviBar parentBar, string  layerName): this (parentBar)         {              this .BarText.Text  =  layerName;         }          public  XUNaviBar(XUNaviBar parentBar, ILayer2 layer): this (parentBar)         {              this .BarText.Text  = layer.Name;              this .CompositeLayer  =  layer;         }          ///   <summary>          ///  添加树形节点BarNode          ///   </summary>          ///   <param name="tmp"></param>          public   void  AddBarNode(XUBarNode tmp)         {              // 设置高度             tmp.Height  =   this ._nodeHeight;              this .NodeList.Add(tmp);              // 设置图层节点的高度              this .Height  =   this .topPanel.Height  +   this .NodeList.Count  *  tmp.Height +  GetAllBarHeight();              this .contentPanel.Controls.Add(tmp);              this .contentPanel.Controls.SetChildIndex(tmp,  0 );             tmp.Dock  =  DockStyle.Top;              if  ( ! this .btnClose.Enabled)              if  ( this .NodeList.Count  >   0 )             {                  this .btnClose.Enabled  =   true ;                  this .btnExpand.Enabled  =   true ;             }         }          ///   <summary>          ///  添加NaviBar大节点          ///   </summary>          ///   <param name="navBar"></param>          public   void  AddBar(XUNaviBar navBar)         {              this .BarList.Add(navBar);              // 设置图层节点的高度              this .Height  =   this .topPanel.Height  + GetAllBarHeight()  +   this .NodeList.Count  *  _nodeHeight;              this .contentPanel.Controls.Add(navBar);              this .contentPanel.Controls.SetChildIndex(navBar,  0 );             navBar.Dock  =  DockStyle.Top;              if ( ! this .btnClose.Enabled && this .BarList.Count  >   0 )             {                  this .btnClose.Enabled  =   true ;                  this .btnExpand.Enabled  =   true ;             }         }          ///   <summary>          ///  展开NaviBar下节点          ///   </summary>          ///   <param name="sender"></param>          ///   <param name="e"></param>          private   void  btnExpand_Click( object  sender, EventArgs e)         {              if  (IsExpand)             {                  this .Height  =   this .topPanel.Height;                  this .btnExpand.Text  =   " 展开 " ;             }              else             {                  if  ( this .BarList.Count  >   0 )                 {                      this .Height  =   this .topPanel.Height  +   this .NodeList.Count  *   this ._nodeHeight  +  GetAllBarHeight();                 }                  else                 {                      this .Height  =   this .topPanel.Height  +   this .NodeList.Count  *   this ._nodeHeight;                 }                  this .btnExpand.Text  =   " 收缩 " ;             }              if  (_ParentBar  !=   null )             {                  // 补丁,展开父节点时,需执行首节点的该操作                 _ParentBar.Height  =  _ParentBar.BarHeight;                  this ._ParentBar.Parent.Height  =  _ParentBar.Height;             }             IsExpand  =   ! IsExpand;         }          ///   <summary>          ///  获得当前节点高度          ///   </summary>          ///   <returns></returns>          private   int  GetAllBarHeight()         {              int  barHeight = 0 ;              foreach  (XUNaviBar tmpBar  in  BarList)             {                 barHeight  +=  tmpBar.Height;             }              return  barHeight;         }          ///   <summary>          ///  打开或关闭图层          ///   </summary>          ///   <param name="sender"></param>          ///   <param name="e"></param>          private   void  btnClose_Click( object  sender, EventArgs e)         {              // 图层集合              if  ( this .CompositeLayer  !=   null )             {                  this .CompositeLayer.Visible  =   ! this .CompositeLayer.Visible;                 mapCtrl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,  null null );                  this .btnClose.Text  =   this .CompositeLayer.Visible  ?   " 关闭 "  :  " 打开 " ;                  foreach  (XUBarNode tmpNode  in   this .NodeList)                 {                     tmpNode.CloseLayer( this .CompositeLayer.Visible);                 }             }              else   //  顶级图层             {                  if ( this .btnClose.Text  == " 关闭 "  )                 {                     CloseLayers( false );                      this .btnClose.Text  =   " 打开 " ;                 }                  else                   {                     CloseLayers( true );                      this .btnClose.Text  =   " 关闭 " ;                 }             }         }          // 关闭图层          private   void  CloseLayers( bool  bClose)         {            // 存在图层集合           if ( this .BarList.Count > 0 )           foreach (XUNaviBar tmpBar  in  BarList)          {              tmpBar.CompositeLayer.Visible  =  bClose;              tmpBar.btnClose.Text  = bClose ? " 关闭 " : " 打开 " ;               foreach  (XUBarNode tmpNode  in  tmpBar.NodeList)              {                  tmpNode.CloseLayer(bClose);              }          }          foreach (XUBarNode tmpNode  in   this .NodeList)         {             tmpNode.CloseLayer(bClose);         }            this .mapCtrl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,  null null );         }          private   void  contentPanel_DragOver( object  sender, DragEventArgs e)         {              if  (e.AllowedEffect  ==  DragDropEffects.Move)             {                 e.Effect  =  DragDropEffects.Move;             }         }          private   void  contentPanel_DragDrop( object  sender, DragEventArgs e)         {             Control item  =  (Control)e.Data.GetData( typeof (XUBarNode));             MessageBox.Show( " 1111 " );              this .Controls.Add(item);         }          private   void  XUNaviBar_DragOver( object  sender, DragEventArgs e)         {              if  (e.AllowedEffect  ==  DragDropEffects.Move)             {                 e.Effect  =  DragDropEffects.Move;             }         }          private   void  XUNaviBar_DragDrop( object  sender, DragEventArgs e)         {             Control item  =  (Control)e.Data.GetData( typeof (XUBarNode));             item.Dock  =  DockStyle.Bottom;              this .contentPanel.Controls.Add(item);         }              }

          XUTocControl控件的最终组合代码:

View Code namespace  GC_Controls {      public   partial   class  XUTocControl : UserControl     {          private  ESRI.ArcGIS.Controls.AxMapControl _MapCtrl;          public  XUTocControl()         {             InitializeComponent();         }          public  XUTocControl(AxMapControl mapCtrl)         {             InitializeComponent();             _MapCtrl  =  mapCtrl;             InitTOC(mapCtrl.Map,  this .MainBar);         }          ///   <summary>          ///  初始化图层工具          ///   </summary>          ///   <param name="map"></param>          ///   <param name="mainBar"></param>          private   void  InitTOC(IMap map,XUNaviBar mainBar)         {             MainBar.Text  =  map.Name;              // 保存地图对象             MainBar.Tag  =  _MapCtrl;              for  ( int  j  =   0 ; j  <  map.LayerCount; j ++ )             {                 ILayer2 pLayer  =  map.get_Layer(j)  as  ILayer2;                  if  (pLayer  is  ESRI.ArcGIS.Carto.IGroupLayer)                 {                     ICompositeLayer pCompositelayer;                     pCompositelayer  =  (ICompositeLayer)pLayer;                     XUNaviBar nvBar  =   new  XUNaviBar(mainBar, pLayer);                     nvBar.Tag  =  _MapCtrl;                      int  i =   0 ;                     ILayer2 pLyr;                      for  (i  =   0 ; i  <  pCompositelayer.Count; i ++ )                     {                         pLyr  =  pCompositelayer.get_Layer(i)  as  ILayer2;                         XUBarNode tmpNode  =   new  XUBarNode(nvBar, pLyr.Name, pLyr.Name);                          // 保存图层对象                         tmpNode.Tag  =  pLyr;                         nvBar.AddBarNode(tmpNode);                     }                     MainBar.AddBar(nvBar);                     nvBar.Dock  =  DockStyle.Top;                 }                  else                 {                     XUBarNode tmpNode  =   new  XUBarNode(mainBar, pLayer.Name, pLayer.Name);                      // 保存图层对象                     tmpNode.Tag  =  pLayer;                     MainBar.AddBarNode(tmpNode);                 }             }         }          private   void  node_click( object  sender, EventArgs e)         {                   _MapCtrl.ActiveView.Refresh();           }     }

 

          调用控件的示例代码:该控件使用时,需要ArcEngine 9.3 Runtime.

        private void FormTest_Load(object sender, EventArgs e)         {             this.axMapControl1.LoadMxFile(Application.StartupPath + "\\geodata\tgwGD.mxd");                     XUTocControl tocCtrl = new XUTocControl(this.axMapControl1);           this.panel1.Controls.Add(tocCtrl);           tocCtrl.Dock = DockStyle.Fill;

        }

 

       实现控件的节点拖拽功能参照了下列资料,在此表示感谢!

http://bbs.zbitedu.com/viewthread.php?tid=8711

http://www.cnblogs.com/ttc/archive/2008/08/21/1273172.html

http://www.cppblog.com/AutomateProgram/archive/2010/08/26/124890.html

http://kb.cnblogs.com/a/1671126/

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.dodragdrop.aspx#Y6514

      此外,WorldWind里也有拖拽文件功能WorldWind学习系列十六:3D Cross Section插件功能分析——TerrainViewer ,拖拽控件和拖拽文件本质上是一样的,只是拖拽控件是将控件作为数据用于传递而已。

       本博客声明:本人的技术探索过程中,得到了国信司南公司方面支持。今后,本人博客里的所有技术探索成果将归“无痕客”、“国信司南”和“博客园”三方共同所有,原创作品如需转载,请注明本博客声明。

  

转载于:https://www.cnblogs.com/wuhenke/archive/2011/05/06/2039488.html

相关资源:VC++ DragTreeControl 可随意拖动节点的树形控件
最新回复(0)