Monday, 3 August 2015

arcgis desktop - ESRI Flash Command in custom code


I would like to implement the same flash feature command that ESRI uses when accessing the context menu on a table row.


I have used the following successfully to flash a selected feature:


IActiveView activeView = ArcMap.Document.ActiveView;
IFeatureIdentifyObj featIdentify = new FeatureIdentifyObject();
featIdentify.Feature = feature;
IIdentifyObj identify = featIdentify as IIdentifyObj;
identify.Flash(activeView.ScreenDisplay);


This code works, but does not have the 'crosshairs' additional effect that the ESRI flash command does.


I was looking possibly executing a command with ICommand.Execute, but could not find an ID for the Flash Command from the table context menu.


Anyone have success with implementing the same Flash Command that ESRI uses within custom code? Does anyone know where to find the ID used for the Flash Command?



Answer



I believe the Flash command on the ArcMap Identify tool and table views is built-in to ArcMap and not exposed as a normal command like Pan, Zoom, etc.


One option is to use IHookActions.DoAction or one of its variants and pass in the esriHookActionsFlash constant. This gives the ArcMap-style flash except it does not draw the crosshairs. See the sample Using HookActions in custom commands.


The "hook" object is just a reference to the current Application which you can get in an ArcMap add-in by using ArcMap.Application. You can for example create a hook helper with the following code:


m_hookHelper = new HookHelperClass();
m_hookHelper.Hook = ArcMap.Application;


There is a different effect used by the Identify dialog in ArcCatalog and the IIdentifyObj.Flash method you mentioned that also does not have the crosshair effect and uses a simple XOR raster operation to flash the feature rather than the nice green fill/black outline symbology used by ArcMap.


If you want to customize the effect you could implement a flash routine yourself. This is a custom flash routine based on the Flash Geometry Snippet, but modified to support geometry collections and to use the same drawing style as the ArcMap Identify tool (except for the "crosshair effect", though maybe you could adapt this to replicate that effect):


using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;

///Flash geometry on the display.
/// The input IGeometry to flash. Supported geometry types are GeometryBag, Polygon, Polyline, Point and Multipoint.
///An IScreenDisplay reference

///An integer that is the time in milliseconds to wait.
public static void FlashGeometry(IGeometry geometry, IScreenDisplay screenDisplay, int delay)
{
if (geometry == null || screenDisplay == null)
{
return;
}
bool continueFlashing = true;

using (ComReleaser comReleaser = new ComReleaser())

{
ITrackCancel cancelTracker = new CancelTrackerClass();
comReleaser.ManageLifetime(cancelTracker);
screenDisplay.CancelTracker = cancelTracker;
short cacheID = screenDisplay.AddCache();
int cacheMemDC = screenDisplay.get_CacheMemDC(cacheID);
IRgbColor fillColor = new RgbColorClass();
comReleaser.ManageLifetime(fillColor);
fillColor.Green = 128;
IRgbColor lineColor = new RgbColorClass();

comReleaser.ManageLifetime(lineColor);
screenDisplay.StartDrawing(cacheMemDC, cacheID);
DrawGeometry(geometry, fillColor, lineColor, (IDisplay)screenDisplay, cancelTracker);
ESRI.ArcGIS.esriSystem.tagRECT RECT = new tagRECT();
screenDisplay.FinishDrawing();
if (continueFlashing == true)
{
screenDisplay.DrawCache(screenDisplay.hDC, cacheID, ref RECT, ref RECT);
if (delay > 0)
{

for (int i = 0; i < delay; i += 50)
{
if (continueFlashing = cancelTracker.Continue())
{
System.Threading.Thread.Sleep(50);
}
else
{
break;
}

}
}
screenDisplay.Invalidate(null, true, cacheID);
screenDisplay.UpdateWindow();
}
screenDisplay.RemoveCache(cacheID);
cancelTracker.Reset();
}
}


///
/// Draws the input geometry using the specified colors.
///

/// The input IGeometry to draw. Supported geometry types are GeometryBag, Polygon, Polyline, Point and Multipoint.
/// An IRgbColor reference for the fill color
/// An IRgbColor reference for the line or outline color
/// An IDisplay reference
/// An ITrackCancel reference
private static void DrawGeometry(IGeometry geometry, IRgbColor fillColor, IRgbColor lineColor, IDisplay display, ITrackCancel cancelTracker)
{

bool continueDrawing = true;
switch (geometry.GeometryType)
{
case esriGeometryType.esriGeometryBag:
{
IEnumGeometry enumGeometry = (IEnumGeometry)geometry;
IGeometry innerGeometry = enumGeometry.Next();
while (innerGeometry != null && continueDrawing == true)
{
DrawGeometry(innerGeometry, fillColor, lineColor, display, cancelTracker); // Recursive method call

innerGeometry = enumGeometry.Next();
if (cancelTracker != null)
{
continueDrawing = cancelTracker.Continue();
}
}
break;
}
case esriGeometryType.esriGeometryPolygon:
{

// Set the input polygon geometry's symbol.
ISimpleFillSymbol fillSymbol = new SimpleFillSymbolClass();
fillSymbol.Color = (IColor)fillColor;
ILineSymbol lineSymbol = new SimpleLineSymbolClass();
lineSymbol.Color = lineColor;
fillSymbol.Outline = lineSymbol;

// Draw the input polygon geometry.
display.SetSymbol((ISymbol)fillSymbol);
display.DrawPolygon(geometry);

break;
}
case esriGeometryType.esriGeometryPolyline:
{
// Set the input polyline geometry's symbol.
IMultiLayerLineSymbol multiLineSymbol = new MultiLayerLineSymbolClass();
ISimpleLineSymbol simpleLineSymbol1 = new SimpleLineSymbolClass();
ISimpleLineSymbol simpleLineSymbol2 = new SimpleLineSymbolClass();
simpleLineSymbol1.Width = 3;
simpleLineSymbol1.Color = fillColor;

simpleLineSymbol2.Width = 5;
simpleLineSymbol2.Color = lineColor;
multiLineSymbol.AddLayer((ILineSymbol)simpleLineSymbol2);
multiLineSymbol.AddLayer((ILineSymbol)simpleLineSymbol1);

// Draw the input polyline geometry.
display.SetSymbol((ISymbol)multiLineSymbol);
display.DrawPolyline(geometry);
break;
}

case esriGeometryType.esriGeometryPoint:
{
// Set the input point geometry's symbol.
ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();
simpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
simpleMarkerSymbol.Size = 12;
simpleMarkerSymbol.Color = fillColor;
simpleMarkerSymbol.Outline = true;
simpleMarkerSymbol.OutlineColor = lineColor;


// Draw the input point geometry.
display.SetSymbol((ISymbol)simpleMarkerSymbol);
display.DrawPoint(geometry);
break;
}
case esriGeometryType.esriGeometryMultipoint:
{
// Set the input multipoint geometry's symbol.
ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();
simpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;

simpleMarkerSymbol.Size = 8;
simpleMarkerSymbol.Color = fillColor;
simpleMarkerSymbol.Outline = true;
simpleMarkerSymbol.OutlineColor = lineColor;

// Draw the input multipoint geometry.
display.SetSymbol((ISymbol)simpleMarkerSymbol);
display.DrawMultipoint(geometry);
break;
}

}
}

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...