ArcGIS Engine – Dragging Features Using ArcObjects and AxMapControl

arcgis-10.0arcgis-enginearcobjectsfeatures

I'm trying to implement moving a point feature in a custom C# ArcGIS Engine application on an AxMapControl. I've already created a custom tool to do some other things. And I can track when the user is doing a drag-type operation (i.e. click and hold while moving the mouse).

What I'd like to be able to do is give some visual feedback of the drag operation, but I'm not sure how to do that.

I can handle the feature selection, identifying the drag, and getting the new position, etc. Just need help specifically with the drag feedback. Ideally I would like to update the cursor to have the same symbology as the feature, but that's not an absolute requirement.

Best Answer

The trick to feedback is setting ISymbol.ROP to esriROPNotXOrPen and drawing the geometry twice, the first draw displays it, the second draw erases it. Be sure if you're using a multilayer symbol to set the ROP for each layer.

public class MyTool : ESRI.ArcGIS.Desktop.AddIns.Tool
{

    private ISymbol m_Symbol;
    private IPoint m_lastPoint;
    private bool m_Dragging = false;
    public MyTool()
    {
        m_Symbol = new SimpleMarkerSymbolClass();
        ((ISimpleMarkerSymbol)m_Symbol).Size = 20.0;
        m_Symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen; 
    }

    protected override void OnUpdate()
    {

    }
    protected override void OnMouseDown(Tool.MouseEventArgs arg)
    {
        m_Dragging = !m_Dragging;
        if (!m_Dragging)
            Draw(arg.X, arg.Y);
    }

    protected override void OnMouseMove(Tool.MouseEventArgs arg)
    {
        if(m_Dragging)
            Draw(arg.X, arg.Y);
    }

    private void Draw(int X, int Y)
    {
        var av = ArcMap.Document.FocusMap as IActiveView;
        var pnt = av.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);
        av.ScreenDisplay.StartDrawing(av.ScreenDisplay.hDC, 0);
        av.ScreenDisplay.SetSymbol(m_Symbol);
        if(m_lastPoint != null)
            av.ScreenDisplay.DrawPoint(m_lastPoint);
        if (m_Dragging)
        {
            av.ScreenDisplay.DrawPoint(pnt);
            m_lastPoint = pnt;
        }
        else
            m_lastPoint = null;
        av.ScreenDisplay.FinishDrawing();
    }

    protected override bool OnDeactivate()
    {
        // todo
        return base.OnDeactivate();
    }
}
Related Question