在Engine的工具(ITool)里:

OnClick事件处理函数中:

首先需要获取一个图层,作为Snapping的参照,

IFeatureLayer targetLayer

然后声明一个IMovePointFeedBack作为鼠标移动时捕捉点的显示:

IMovePointFeedback m_pMovePtFeed = new MovePointFeedback();
mFeedback = (IDisplayFeedback)m_pMovePtFeed;
ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();
IRgbColor pRGBColor = new RgbColorClass();
pRGBColor.Red = ;
pRGBColor.Green = ;
pRGBColor.Blue = ;
simpleMarkerSymbol.Color = pRGBColor;
simpleMarkerSymbol.Size = ;
simpleMarkerSymbol.Style = ESRI.ArcGIS.Display.esriSimpleMarkerStyle.esriSMSSquare;
ISymbol symbol = simpleMarkerSymbol as ISymbol;
symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;
//symbol.ROP2 = esriRasterOpCode.;
m_pMovePtFeed.Symbol = (ISymbol)simpleMarkerSymbol;

然后, 开始Feedback的显示(tmpPoint是指开始的点,其实影响不大,如果不想要源点在屏幕上的话,可以取一个在屏幕外的点):

m_pMovePtFeed.Display = mMapControl.ActiveView.ScreenDisplay;
m_pMovePtFeed.Start(tmpPoint, tmpPoint);

在OnMouseMove事件中:

IPoint pPoint2 = null;
IPoint pPoint = pMap.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
pPoint2 = Snapping(pPoint.X, pPoint.Y, targetLayer, pMap, );
if (pPoint2 == null)
pPoint2 = pPoint;
((IMovePointFeedback)mFeedback).MoveTo(pPoint2);

其中Snapping函数即为最主要的查找函数,其功能为根据输入的点坐标在目标图层上查找最为相近的点(也即需要捕捉的点),返回该点,若没有找到则返回NULL,最后一个参数的含义是,在地图控件上,以多少个像素为单位在周边查找捕捉点.

public IPoint Snapping(double x, double y, IFeatureLayer iFeatureLyr, IMapControl3 axMapControl1,double snappingDis)
{
IPoint iHitPoint = null;
IMap iMap = axMapControl1.Map;
IActiveView iView = axMapControl1.ActiveView;
IFeatureClass iFClss = iFeatureLyr.FeatureClass;
IPoint point = new PointClass();
point.PutCoords(x, y);
double length = ConvertPixelsToMapUnits(axMapControl1.ActiveView, snappingDis);
ITopologicalOperator pTopo = point as ITopologicalOperator;
IGeometry pGeometry = pTopo.Buffer(length).Envelope as IGeometry;
ISpatialFilter spatialFilter = new SpatialFilterClass();
spatialFilter.GeometryField = iFeatureLyr.FeatureClass.ShapeFieldName;
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
spatialFilter.Geometry = pGeometry;
IFeatureCursor cursor = iFClss.Search(spatialFilter, false);
IFeature iF = cursor.NextFeature();
if (iF == null) return null;
IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point();
IHitTest iHitTest = iF.Shape as IHitTest;
double hitDist = ;
int partIndex = ;
int vertexIndex = ;
bool bVertexHit = false;
// Tolerance in pixels for line hits
double tol = ConvertPixelsToMapUnits(iView, snappingDis);
if (iHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartBoundary,
iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bVertexHit))
{
iHitPoint = iHitPt;
}
//axMapControl1.ActiveView.Refresh();
return iHitPoint;
}
public double ConvertPixelsToMapUnits(IActiveView pActiveView, double pixelUnits)
{
double realWorldDisplayExtent;
int pixelExtent;
double sizeOfOnePixel;
pixelExtent = pActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right - pActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;
realWorldDisplayExtent = pActiveView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;
sizeOfOnePixel = realWorldDisplayExtent / pixelExtent;
return pixelUnits * sizeOfOnePixel;
}

此时即可实现鼠标实时地捕捉目标图层上的对象,若需要获取当前位置的捕捉点时,则可以在相应事件(例如OnMouseDown或OnDbClick)中调用:

IPoint pPoint = ((IMovePointFeedback)mFeedback).Stop();

这时实时捕捉将会停止,若需要重新开始捕捉,则在之后调用这些语句即可:

//重新开始Snap
IPoint tmpPoint = new PointClass();
tmpPoint.PutCoords(pMap.Extent.XMin - , pMap.Extent.YMin - );
IMovePointFeedback m_pMovePtFeed = (IMovePointFeedback)mFeedback;
m_pMovePtFeed.Display = pMap.ActiveView.ScreenDisplay;
m_pMovePtFeed.Start(tmpPoint, tmpPoint);
05-02 18:54