Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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?

share|improve this question

1 Answer 1

up vote 3 down vote accepted

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;

///<summary>Flash geometry on the display.</summary>
///<param name="geometry"> The input IGeometry to flash.  Supported geometry types are GeometryBag, Polygon, Polyline, Point and Multipoint.</param>
///<param name="screenDisplay">An IScreenDisplay reference</param>
///<param name="delay">An integer that is the time in milliseconds to wait.</param>
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();
    }
}

/// <summary>
/// Draws the input geometry using the specified colors.
/// </summary>
/// <param name="geometry">The input IGeometry to draw. Supported geometry types are GeometryBag, Polygon, Polyline, Point and Multipoint.</param>
/// <param name="fillColor">An IRgbColor reference for the fill color</param>
/// <param name="lineColor">An IRgbColor reference for the line or outline color</param>
/// <param name="display">An IDisplay reference</param>
/// <param name="cancelTracker">An ITrackCancel reference</param>
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;
            }
    }
}
share|improve this answer
    
It is not looking like I can access the flash that ESRI. Thanks for the code samples. I appreciate the help. I may end using what you provided and change the delay value to show the feature longer. –  user6663 May 5 '12 at 13:32
    
What problem are you having with the "ESRI" flash? Did you try the sample? –  blah238 May 5 '12 at 22:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.