在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 = 0; pRGBColor.Green = 0; pRGBColor.Blue = 0; simpleMarkerSymbol.Color = pRGBColor; simpleMarkerSymbol.Size = 3; 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, 10); 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 = 0; int partIndex = 0; int vertexIndex = 0; 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 - 1, pMap.Extent.YMin - 1); IMovePointFeedback m_pMovePtFeed = (IMovePointFeedback)mFeedback; m_pMovePtFeed.Display = pMap.ActiveView.ScreenDisplay; m_pMovePtFeed.Start(tmpPoint, tmpPoint);