缩放到要素以及闪烁形状是非常常规的操作,用处很广泛。单一的来看这两个通常都不会有什么问题,但是当将他们放在一起时,稍不注意就会达不到目的。
其实比较容易引起的问题就是:尽管缩放到要素的代码放在闪烁代码的前面,也刷新了视图,但是执行的时候,却是先闪烁,再缩放。执行顺序不对其实是牵涉到一个非常关键的要点。
要点:IActiveView.Refresh()并不会立刻启动 redraw 方法来重新绘制窗口,要想立刻绘制,需要显式调用ScreenDIsplay.UpdateWindow()方法。
这个要点同样适用于其他需要刷新后立刻执行屏幕操作的地方。
下面分别来讲实现。
移动缩放
public static void ZoomToGeometry(IGeometry geometry, IActiveView activeView)
{
IEnvelope env = geometry.Envelope;
IGeometry5 geo = geometry as IGeometry5;
if (env.Width == 0 || env.Height == 0)
{
IPoint centerPoint = new PointClass();
centerPoint.X = geo.CentroidEx.X;
centerPoint.Y = geo.CentroidEx.Y;
//IDisplayTransformation displayTrans = activeView.ScreenDisplay.DisplayTransformation;
//displayTrans.SpatialReference = activeView.FocusMap.SpatialReference;
env.XMin = centerPoint.X - 0.001;
env.XMax = centerPoint.X + 0.001;
env.YMin = centerPoint.Y - 0.001;
env.YMax = centerPoint.Y + 0.001;
env.CenterAt(centerPoint);
}
env.Expand(0.5, 0.5, true);
activeView.Extent = env;
activeView.Refresh();
activeView.ScreenDisplay.UpdateWindow();
}
闪烁形状
闪烁主要有三种方式:
第一种方式使用IMapControlDefault接口的FlashShape方法,非常直观,但是仅能在ArcEngine环境下才行,做Arcgis的Addin开发由于获取不到IMapControlDefault对象,不能使用此方式;
第二种是在当前地图展示窗口绘制临时的形状,这种方式的优点是闪烁的形状不一定是要素,也可以是某个不存在的点或者多边形,只要有坐标就可以;
第三种方式是采用识别要素的方式,这种方式代码实现比较直观,调用Arcgis本身的接口实现闪烁,但采用这种方式的话,要求闪烁的图形必须是存在的几何要素(Feature)。
直接调用FlashShape方法
在ArcEngine开发环境中,获取到IMapControlDefault对象,直接调用FlashShape方法就可以了,这种方法比较直观
IMapControlDefault.FlashShape(IGeometry geometry);
绘制图形的方式
其实这个代码在Arcgis的Code Snippets里面是有的,直接粘贴过来。
public static void FlashGeometry(IGeometry geometry, IRgbColor color, IDisplay display, System.Int32 delay)
{
if (geometry == null || color == null || display == null)
{
return;
}
display.StartDrawing(display.hDC, (System.Int16)esriScreenCache.esriNoScreenCache); // Explicit Cast
switch (geometry.GeometryType)
{
case esriGeometryType.esriGeometryPolygon:
{
//Set the flash geometry's symbol.
ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbolClass();
simpleFillSymbol.Color = color;
ISymbol symbol = simpleFillSymbol as ISymbol; // Dynamic Cast
symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;
//Flash the input polygon geometry.
display.SetSymbol(symbol);
display.DrawPolygon(geometry);
System.Threading.Thread.Sleep(delay);
display.DrawPolygon(geometry);
break;
}
case esriGeometryType.esriGeometryPolyline:
{
//Set the flash geometry's symbol.
ISimpleLineSymbol simpleLineSymbol = new SimpleLineSymbolClass();
simpleLineSymbol.Width = 4;
simpleLineSymbol.Color = color;
ISymbol symbol = simpleLineSymbol as ISymbol; // Dynamic Cast
symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;
//Flash the input polyline geometry.
display.SetSymbol(symbol);
display.DrawPolyline(geometry);
System.Threading.Thread.Sleep(delay);
display.DrawPolyline(geometry);
break;
}
case esriGeometryType.esriGeometryPoint:
{
//Set the flash geometry's symbol.
ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();
simpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
simpleMarkerSymbol.Size = 12;
simpleMarkerSymbol.Color = color;
ISymbol symbol = simpleMarkerSymbol as ISymbol; // Dynamic Cast
symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;
//Flash the input point geometry.
display.SetSymbol(symbol);
display.DrawPoint(geometry);
System.Threading.Thread.Sleep(delay);
display.DrawPoint(geometry);
break;
}
case esriGeometryType.esriGeometryMultipoint:
{
//Set the flash geometry's symbol.
ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();
simpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
simpleMarkerSymbol.Size = 12;
simpleMarkerSymbol.Color = color;
ISymbol symbol = simpleMarkerSymbol as ISymbol; // Dynamic Cast
symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;
//Flash the input multipoint geometry.
display.SetSymbol(symbol);
display.DrawMultipoint(geometry);
System.Threading.Thread.Sleep(delay);
display.DrawMultipoint(geometry);
break;
}
}
display.FinishDrawing();
}
识别要素的方式
这种方式使用IFeatureIdentifyObj接口当中的Flash方法来达到闪烁的目的,代码如下。
public static void identifyFlash(IActiveView activeView, IFeature feature)
{
IFeatureIdentifyObj featIdentify = new FeatureIdentifyObject();
featureIdentify.Feature = feature;
IIdentifyObj identify = featIdentify as IIdentifyObj;
identify.Flash(activeView.ScreenDisplay);
}
调用
注意到上面的ZoomToGeometry方法中,最后一句
activeView.ScreenDisplay.UpdateWindow();
这句非常关键,它会让地图显示窗口立刻重新绘制,更新显示。如果没有这一句,在调用ZoomToGeometry之后紧接着使用FlashGeometry方法就起不到效果,地图窗口会先闪烁一个形状,然后再缩放过去,顺序是不对的。但是加上上面这一句,强制地图窗口重新绘制以后,也就是缩放就立马见效了,这个时候闪烁的形状就是正确的。
arcobjects