ArcMap的Editor工具,实现要素拖动、编辑

     本来根本没有写这个工具的意思,自己一直用的Ae自带的工具。虽然可控制力弱了一些,但终究还是凑或能用。一天,问到一个同学,想请教一下,居然以百般理由回绝。算了,秉承毛老人家的口号:自力更生,丰衣足食!好了,闲话少说,各位看官,咱步入正题了。

     首先,说一下,所有的要素的更新、插入、删除最好放在编辑的Session 里面,即以一对StartEditing和StopEditing包裹。

     一开始我的疑问在于,为什么我用IWorkspaceEdit的StartEditing方法后,怎么鼠标不会变成AcrMap里面Editor的开始编辑那样呢,为什么不能选中要素,为什么不能双击后编辑要素?原来,选中要素和使要素处于编辑状态还是要自己写的(经高人指点,呵呵)。

     先介绍一下程序中用到的变量:

Code
private AxMapControl m_MapControl;//从外部传进来的MapControl控件
private ILayer m_SelectedLayer;//当前正在编辑的图层
private bool m_IsEdited = false;//当前是否处于编辑状态
private bool m_IsInUse = false;//这个其实我这里没有用到,这个实在创建新要素时用到的
private List<IFeature> m_SelectedFeature;//这个存储鼠标点击下,击中的要素
private IPoint m_CurrentMousePosition;//这个好像也没用到,记录当前鼠标的位置
private IDisplayFeedback m_FeedBack;//这个就是当前屏幕(鼠标动作)的反馈信息

    那我们就按照逻辑顺序来一一展示这个到底是怎么做的。首先是,开始和结束编辑的代码:

///   <summary>
///  开始编辑
///   </summary>
///   <param name="bWithUndoRedo"></param>
public   void  StartEditing( bool  bWithUndoRedo)
{
     
if  (m_SelectedLayer  ==   null return ;
     IFeatureLayer featureLayer 
=  m_SelectedLayer  as  IFeatureLayer;
     
if  (featureLayer  ==   null return ;
     IFeatureClass featureClass 
=  featureLayer.FeatureClass;
     
if  (featureClass  ==   null return ;

     IDataset dataset 
=  featureClass  as  IDataset;
     IWorkspaceEdit workspaceEdit 
=  dataset.Workspace  as  IWorkspaceEdit;
     
try
     {
          workspaceEdit.StartEditing(bWithUndoRedo);
          m_IsEdited 
=   true ;
     }
     
catch  
     {
          
return ;
     }
}

     当然你可以直接传进来IWorkspace,这个可根据你具体的需求,我这里用当前图层获取工作空间。

 

///   <summary>
///  结束编辑
///   </summary>
///   <param name="bSave"></param>
public   void  StopEditing( bool  bSave)
{
     
if  (m_IsEdited)
     {
          m_IsEdited 
=   false ;

          
if  (m_SelectedLayer  ==   null return ;
          IFeatureLayer featureLayer 
=  m_SelectedLayer  as  IFeatureLayer;
          
if  (featureLayer  ==   null return ;
          IFeatureClass featureClass 
=  featureLayer.FeatureClass;
          
if  (featureClass  ==   null return ;

          IDataset dataset 
=  featureClass  as  IDataset;
          IWorkspaceEdit workspaceEdit 
=  dataset.Workspace  as  IWorkspaceEdit;
          
if  (workspaceEdit.IsBeingEdited())
          {
               
try
               {
                   workspaceEdit.StopEditing(bSave);
               }
               
catch
               {
                   workspaceEdit.AbortEditOperation();
                   
return ;
               }
          }
      }
}

 

     开始编辑已经好了,然后就是鼠标点击要素时候,让其处于选中状态,我这里为了方便控制,我分成了两个函数写,给为看官也可以合并成一个:

 

public   void  GetFeatureOnMouseDown( int  x,  int  y)
{
   m_SelectedFeature.Clear();
   
try
   {
      
if  (m_SelectedLayer  ==   null return ;
      IFeatureLayer featureLayer 
=  m_SelectedLayer  as  IFeatureLayer;
      
if  (featureLayer  ==   null return ;
      IFeatureClass featureClass 
=  featureLayer.FeatureClass;
      
if  (featureClass  ==   null return ;

      IPoint point 
=  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
      IGeometry geometry 
=  point  as  IGeometry;

      
double  length  =  ConvertPixelsToMapUnits( 4 );
      ITopologicalOperator pTopo 
=  geometry  as  ITopologicalOperator;
      IGeometry buffer 
=  pTopo.Buffer(length);
      geometry 
=  buffer.Envelope  as  IGeometry;

      ISpatialFilter spatialFilter 
=   new  SpatialFilterClass();
      spatialFilter.Geometry 
=  geometry;
      
switch  (featureClass.ShapeType)
      {
         
case  esriGeometryType.esriGeometryPoint:
              spatialFilter.SpatialRel 
=  esriSpatialRelEnum.esriSpatialRelContains;
              
break ;
         
case  esriGeometryType.esriGeometryPolygon:
              spatialFilter.SpatialRel 
=  esriSpatialRelEnum.esriSpatialRelIntersects;
              
break ;
         
case  esriGeometryType.esriGeometryPolyline:
              spatialFilter.SpatialRel 
=  esriSpatialRelEnum.esriSpatialRelCrosses;
              
break ;
       }
       spatialFilter.GeometryField 
=  featureClass.ShapeFieldName;
       IQueryFilter filter 
=  spatialFilter  as  IQueryFilter;

       IFeatureCursor cursor 
=  featureClass.Search(filter,  false );
       IFeature pfeature 
=  cursor.NextFeature();
       
while  (pfeature  !=   null )
       {
           m_SelectedFeature.Add(pfeature);
           pfeature 
=  cursor.NextFeature();
       }
   }
   
catch
   {
       
return ;
   }
}

///   <summary>
///  根据鼠标点击位置使击中要素处于高亮显示状态
///   </summary>
///   <param name="x"></param>
///   <param name="y"></param>
public   void  SelectOnMouseDown()
{
    
try
    {
        
if  (m_SelectedLayer  ==   null return ;
        m_MapControl.Map.ClearSelection();
        m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, 
null null );
        
foreach  (IFeature feature  in  m_SelectedFeature.ToArray())
        {
              m_MapControl.Map.SelectFeature(m_SelectedLayer, feature);
        }
        m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, 
null null );
    }
    
catch
    { 
return ; }
}

     相信大家对第一个函数并不陌生吧?对的,就是用的空间查询,把点击中的要素放进容器,再用第二个函数进行高亮显示。这个地方注意,如果数据量比较多,强烈推荐用PartialRefresh 而不要用Refresh,参数的含义请参考帮助。

     这个只是开始编辑后,可以用鼠标点击选中要素,使其处于高亮状态,然而,ArcMap里面双击要素怎么出现节点用以编辑呢?这个是要自己绘制到MapControl上面去的:

 

///   <summary>
///  在要素上面绘制一个可拖拽的符号
///   </summary>
///   <param name="geometry"></param>
public   void  DrawEditSymbol(IGeometry geometry, IDisplay display)
{
    IEngineEditProperties engineProperty 
=   new  EngineEditorClass();

    ISymbol pointSymbol 
=  engineProperty.SketchVertexSymbol  as  ISymbol;
    ISymbol sketchSymbol 
=  engineProperty.SketchSymbol  as  ISymbol;

    ITopologicalOperator pTopo 
=  geometry  as  ITopologicalOperator;

    sketchSymbol.SetupDC(display.hDC, display.DisplayTransformation);
    sketchSymbol.Draw(pTopo.Boundary);

    IPointCollection pointCol 
=  geometry  as  IPointCollection;
    
for  ( int  i  =   0 ; i  <  pointCol.PointCount; i ++ )
    {
        IPoint point 
=  pointCol.get_Point(i);
        pointSymbol.SetupDC(display.hDC, display.DisplayTransformation);
        pointSymbol.Draw(point);
        pointSymbol.ResetDC();
    }

    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(sketchSymbol);
    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(pointSymbol);
    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(engineProperty);
}

 

     注意,这个函数是在MapControl的AfterDraw里面调用的,IDisplay参数,是AfterDraw事件的参数,我这里就没有画出来,类似ArcMap里面还有一个红色的节点,这里全是绿色的,因为红色对我的用处不大,也就没有必要了,当然各位看官可以自行修改,还有就是绘制符号的时候一定要记得释放内存哦~

     现在,编辑状态做好了,但是现在只是雏形,因为它还没有响应任何鼠标事件,当鼠标悬停在绿色的节点上时并不会让你可以拖拽,所以我们还要做点工作。

     那现在就开始如果鼠标悬停在绿色节点上时的代码吧:

 

public   void  SnapVertex( int  x, int  y,IGeometry snapContainer, ref   bool  vertexSnaped, ref   bool  contained)
{
    IPoint point 
=  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
    IPoint pHitPoint 
=   null ;
    
double  hitDist  =   - 1 , tol  =   - 1 ;
    
int  vertexIndex  =   - 1 , partIndex  =   - 1 ;
    
bool  vertex  =   false ;

    tol 
=  ConvertPixelsToMapUnits( 4 );

    IHitTest pHitTest 
=  snapContainer  as  IHitTest;
    
bool  bHit = pHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartVertex, pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexIndex,  ref  vertex);
    vertexSnaped 
=   false ;
    contained 
=   false ;
    
if  (bHit)
    {
        m_MapControl.MousePointer 
=  esriControlsMousePointer.esriPointerCrosshair;
        vertexSnaped 
=   true ;
        
return ;
    }
    
else  
    {
        IRelationalOperator pRelOperator
= null ;
        ITopologicalOperator pTopo 
=   null ;
        IGeometry buffer 
=   null ;
        IPolygon polygon 
=   null ;
        
switch  (snapContainer.GeometryType)
        {
             
case  esriGeometryType.esriGeometryPolyline:
                        pTopo 
=  snapContainer  as  ITopologicalOperator;
                        buffer
= pTopo.Buffer( 3 );
                        polygon 
=  buffer  as  IPolygon;
                        pRelOperator
= polygon  as   IRelationalOperator;
                        
break ;
             
case  esriGeometryType.esriGeometryPolygon:
                        polygon 
=  snapContainer  as  IPolygon;
                        pRelOperator
= polygon  as   IRelationalOperator;
                        
break ;
             
case  esriGeometryType.esriGeometryPoint:
                        pTopo 
=  snapContainer  as  ITopologicalOperator;
                        buffer 
=  pTopo.Buffer( 3 );
                        polygon 
=  buffer  as  IPolygon;
                        pRelOperator 
=  polygon  as  IRelationalOperator;
                        
break ;
             
default :
                        
break ;
        }

         
if  (pRelOperator  ==   null return ;
         
if  (pRelOperator.Contains(point))
         {
              m_MapControl.MousePointer 
=  esriControlsMousePointer.esriPointerSizeAll;
              contained 
=   true ;
         }
         
else  m_MapControl.MousePointer  =  esriControlsMousePointer.esriPointerArrow;
         
return ;
   }
}

     这里就是根据鼠标悬停的位置,来改变鼠标样式,抱歉的很,我没有从AE里面找到和ArcMap一样的鼠标样式,只要用一些简单的替代了,当然你可以自己定义,也可以打电话、发Email质问ESRI客服,如果你知道了,一定要告诉我,否则我诅咒你找不到女朋友!这个函数里面,我需要判断,鼠标是悬停在要素的节点上,还是悬停在要素内部了,这个对于后面处理是拽节点还是移动要素有很大的帮助。

     这个根据鼠标悬停位置改变鼠标样式,还远远不够滴,当你悬停到绿色节点上时,按下鼠标时,就意味这拖拽开始,当鼠标左键按下并移动时,要出现像橡皮筋一样的连接线,当左键弹起时,就意味着拖拽结束,如果再按下左键,就意味着要素的编辑结束。这个怎么做到呢,请看下面的代码:

 

public   bool  EditFeature( int  x, int  y,IGeometry geometry)
{
    GetFeatureOnMouseDown(x, y);
    SelectOnMouseDown();
    
if (m_SelectedFeature.Count < 1 ) return   false ;
    
if  (geometry  ==   null return   false ;

    IPoint pHitPoint
= null ;
    
double  hitDist  =   0 , tol  =   0 ;
    
int  vertexIndex  =   0 , vertexOffset  =   0 , numVertices  =   0 , partIndex  =   0 ;
    
bool  vertex = false ;

    IFeature editedFeature 
=  m_SelectedFeature[ 0 ];
    point 
=  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
    tol 
=  ConvertPixelsToMapUnits( 4 );
    
// IGeometry pGeo = editedFeature.Shape;
    
// m_EditingFeature = editedFeature;

    
try
    {
       
switch  (geometry.GeometryType)
       {
           
case  esriGeometryType.esriGeometryPoint:
                        m_FeedBack 
=   new  MovePointFeedbackClass();
                        m_FeedBack.Display 
=  m_MapControl.ActiveView.ScreenDisplay;
                        IMovePointFeedback pointMove 
=  m_FeedBack  as  IMovePointFeedback;
                        pointMove.Start(geometry 
as  IPoint, point);
                        
break ;
           
case  esriGeometryType.esriGeometryPolyline:
           
if  (TestGeometryHit(tol, point, geometry,  ref  pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexOffset,  ref  vertexIndex,  ref  vertex))
           {
                
if ( ! vertex)
                {
                      IGeometryCollection geometryColl 
=  geometry  as  IGeometryCollection;
                      IPath path 
=  geometryColl.get_Geometry(partIndex)  as  IPath;
                      IPointCollection pointColl 
=  path  as  IPointCollection;
                      numVertices 
=  pointColl.PointCount;
                      
object  missing  =  Type.Missing;

                      
if  (vertexIndex  ==   0 )
                      {
                            
object  start  =   1   as   object ;
                            pointColl.AddPoint(point, 
ref  start,  ref  missing);
                      }
                      
else
                      {
                            
object  objVertexIndex = vertexIndex  as   object ;
                            pointColl.AddPoint(point, 
ref  missing,  ref  objVertexIndex);
                      }
                      TestGeometryHit(tol, point, geometry, 
ref  pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexOffset,  ref  vertexIndex,  ref  vertex);
                 }
                 m_FeedBack 
=   new  LineMovePointFeedbackClass();
                 m_FeedBack.Display 
=  m_MapControl.ActiveView.ScreenDisplay;
                 ILineMovePointFeedback lineMove 
=  m_FeedBack  as  ILineMovePointFeedback;
                 lineMove.Start(geometry 
as  IPolyline, vertexIndex, point);
           }
           
else   return   false ;
           
break ;
           
case  esriGeometryType.esriGeometryPolygon:
           
if  (TestGeometryHit(tol, point, geometry,  ref  pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexOffset,  ref  vertexIndex,  ref  vertex))
           {
                
if ( ! vertex)
                {
                    IGeometryCollection geometryColl 
=  geometry  as  IGeometryCollection;
                    IPath path 
=  geometryColl.get_Geometry(partIndex)  as  IPath;
                    IPointCollection pointColl 
=  path  as  IPointCollection;
                    numVertices 
=  pointColl.PointCount;
                    
object  missing  =  Type.Missing;
                    
if  (vertexIndex  ==   0 )
                    {
                        
object  start  =   1   as   object ;
                        pointColl.AddPoint(point, 
ref  start,  ref  missing);
                    }
                    
else
                    {
                        
object  objVertexIndex  =  vertexIndex  as   object ;
                        pointColl.AddPoint(point, 
ref  missing,  ref  objVertexIndex);
                    }
                    TestGeometryHit(tol, point, geometry, 
ref  pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexOffset,  ref  vertexIndex,  ref  vertex);
                }
                m_FeedBack 
=   new  PolygonMovePointFeedbackClass();
                m_FeedBack.Display 
=  m_MapControl.ActiveView.ScreenDisplay;
                IPolygonMovePointFeedback polyMove 
=  m_FeedBack  as  IPolygonMovePointFeedback;
                polyMove.Start(geometry 
as  IPolygon, vertexIndex  +  vertexOffset, point);
            }
            
else   return   false ;
            
break ;
            
default :
            
break ;
        }
     }
     
catch  { return   false ;}
     
return   true ;
}

public   void  FeatureEditMouseMove( int  x, int  y)
{
   
if  (m_FeedBack  ==   null return ;
   IPoint point 
=  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
   m_FeedBack.MoveTo(point);
}

public  IGeometry EndFeatureEdit( int  x,  int  y)
{
    
if  (m_FeedBack  ==   null return   null ;

    IGeometry geometry 
=   null ;
    IPoint point 
=  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
    
if  ((m_FeedBack  as  IMovePointFeedback)  !=   null )
    {
         IMovePointFeedback pointMove 
=  m_FeedBack  as  IMovePointFeedback;
         geometry 
=  pointMove.Stop()  as  IGeometry;
    }
    
else   if  ((m_FeedBack  as  ILineMovePointFeedback)  !=   null )
    {
         ILineMovePointFeedback lineMove 
=  m_FeedBack  as  ILineMovePointFeedback;
         geometry 
=  lineMove.Stop()  as  IGeometry;
    }
    
else   if  ((m_FeedBack  as  IPolygonMovePointFeedback)  !=   null )
    {
         IPolygonMovePointFeedback polyMove 
=  m_FeedBack  as  IPolygonMovePointFeedback;
         geometry 
=  polyMove.Stop()  as  IGeometry;
    }
    m_FeedBack 
=   null ;
    m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_SelectedLayer, 
null );
    
return  geometry;
}

 

     呵,这个排版真的是很累啊,无法自动缩进,害的我只能一行一行的移动。第一个函数,自然是点击下绿色节点时触发,意味着,我们的拖拽就开始了;但是,但按着鼠标左键来回移动时怎么处理啊?呵呵,这就是第二个函数的所具备的功能,所以你要在MapControl 的MouseMove事件中添加这个函数;但是当你确定你移动的位置是最佳位置的时候,想停下来怎么办呢?这就是第三个函数来帮你了,也就意味着你的拖拽结束,并返回一个IGeometry,这个IGeometry就是你编辑过后要素的新的几何形状,并且当你移动结束左键弹起的时候,这个新的IGeometry也需要显示出来它的绿色的节点,所以重绘的时候需要这个IGeometry。

     好了,我们快大功告成了,stop!好像还少点东西,对了,我们最终是要把最新的几何形状赋给编辑的要素以实现更新,所以我们还需要下面的这个函数:

 

public   bool  UpdateEdit(IGeometry newGeom)
{
    
if  (m_SelectedFeature.Count  <   1 return   false ;
    
if  (newGeom  ==   null return   false ;
    
if  (newGeom.IsEmpty)  return   false ;

    IFeature feature 
=  m_SelectedFeature[ 0 ];
    IDataset dataset 
=  feature.Class  as  IDataset;
    IWorkspaceEdit workspaceEdit 
=  dataset.Workspace  as  IWorkspaceEdit;
    
if  ( ! workspaceEdit.IsBeingEdited())  return   false ;

    workspaceEdit.StartEditOperation();
    feature.Shape 
=  newGeom;
    feature.Store();
    workspaceEdit.StopEditOperation();
    m_SelectedFeature.Clear();
    m_SelectedFeature.Add(feature);
    ClearSelection();

    
return   true ;
}

 

     呵呵,对的,这个函数很简单,就是更新一下编辑要素的几何形状,注意啊,这里我获取当前编辑的要素是从容器中取出来的,这样是不是很方便啊?这样我们就可以更新一个要素了。别忘了最后记得调用StopEditing以保存你的编辑!

     当然,不可能一次性做好,我们需要更人性化一点,我们需要添加撤销和重做:

 

public   void  UndoEdit()
        {
            
if  (m_SelectedLayer  ==   null return ;

            IFeatureLayer featLayer 
=  m_SelectedLayer  as  IFeatureLayer;
            IDataset dataset 
=  featLayer.FeatureClass  as  IDataset;
            IWorkspaceEdit workspaceEdit 
=  dataset.Workspace  as  IWorkspaceEdit;
            
bool  bHasUndos  =   false ;
            workspaceEdit.HasUndos(
ref  bHasUndos);
            
if (bHasUndos)
            {
                workspaceEdit.UndoEditOperation();
            }
            ClearSelection();
        }

        
public   void  RedoEdit()
        {
            
if  (m_SelectedLayer  ==   null return ;

            IFeatureLayer featLayer 
=  m_SelectedLayer  as  IFeatureLayer;
            IDataset dataset 
=  featLayer.FeatureClass  as  IDataset;
            IWorkspaceEdit workspaceEdit 
=  dataset.Workspace  as  IWorkspaceEdit;
            
bool  bHasUndos  =   false ;
            workspaceEdit.HasRedos(
ref  bHasUndos);
            
if  (bHasUndos)
            {
                workspaceEdit.RedoEditOperation();
            }
            ClearSelection();
        }

 

     呵呵 这个也是很简单,对吧?这里需要给出几个上述函数中用到的辅助函数,这里就不一一阐明了,请各位看官自行分析:

private   double  ConvertPixelsToMapUnits( double  pixelUnits)
{
   
int  pixelExtent  =  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right -  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;

   
double  realWorldDisplayExtent  =  m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;
   
double  sizeOfOnePixel  =  realWorldDisplayExtent  /  pixelExtent;

   
return  pixelUnits  *  sizeOfOnePixel;
}

private   bool  TestGeometryHit( double  tol,IPoint pPoint,IGeometry geometry, ref  IPoint pHitPoint,
                                   
ref   double  hitDist,  ref   int  partIndex,  ref   int  vertexOffset,
                                   
ref   int  vertexIndex,  ref   bool  vertexHit)
{
     IHitTest pHitTest 
=  geometry  as  IHitTest;
     pHitPoint 
=   new  PointClass();
     
bool  last  =   true ;
     
bool  res  =   false ;
     
if  (pHitTest.HitTest(pPoint, tol, esriGeometryHitPartType.esriGeometryPartVertex, pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexIndex,  ref  last))
     {
          vertexHit 
=   true ;
          res 
=   true ;
     }
     
else
     {
         
if  (pHitTest.HitTest(pPoint, tol, esriGeometryHitPartType.esriGeometryPartBoundary, pHitPoint,  ref  hitDist,  ref  partIndex,  ref  vertexIndex,  ref  last))
         {
              vertexHit 
=   false ;
              res 
=   true ;
         }
     }

     
if (partIndex > 0 )
     {
         IGeometryCollection pGeoColl 
=  geometry  as  IGeometryCollection;
         vertexOffset 
=   0 ;
         
for  ( int  i  =   0 ; i  <  partIndex;i = 2 * i + 1 )
         {
             IPointCollection pointColl 
=  pGeoColl.get_Geometry(i)  as  IPointCollection;
             vertexOffset 
=  vertexOffset  +  pointColl.PointCount;
         }
     }
     
return  res;
}

///   <summary>
///  清除要素选择状态,恢复常态
///   </summary>
public   void  ClearSelection()
{
    m_MapControl.Map.ClearSelection();
    m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_SelectedLayer, 
null );
}

 

     各位看官,由于要素的移动、要素的创建和要素编辑在代码逻辑上差不多,所以我就不做过多阐述了,都是在处理鼠标的事件,需要做判断。其实,可能有看官已经了解,在AE的帮助里面就有类似的代码,是的,我参考了这部分代码,并对ESRI的开发和工作人员表示感谢。

     最后,谢谢AE开发群一叶知秋老大哥的帮助,总是在繁忙之中耐心的指导,再次表示感谢。

     希望大家能够有所启发,谢谢大家的支持!

     最后需要示例源码的请联系我,我的邮箱是lipengguo.cz # gmail.com

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值