2

I am creating a "tool" add-in for ArcGIS 10 that basically draws a polygon where user left-clicks on map display and, as long as mouse is left-clicked, drags it around. When left button is released, polygon is erased.

It should not be so complicated, but I'm struggling in making the polygon persist on screen while dragging. When mouse is clicked, polygon is displayed ok, but as soon as I start moving around it vanishes - but if I move the mouse fastly, I can see the polygon there (like a "flickering" effect). That is: polygon is drawn, but when mouse stops moving, it is cleared from screen.

If I remove the mxDoc.getActiveView().refresh() call, every polygon drawn during movement persist on screen. So may be something related to the correct refresh method to use? What am I doing wrong?

I'm just beginning my development with ArcObjects and Engine, so I might be missing something here.

Here is a piece of my code (Java):

@Override
public void mouseMoved(MouseEvent me) {
  try
  {
      if(me.getButton() != 0)
      {
          mxDoc.getActiveView().refresh();
          gabPolygon = new Polygon();
          gabPolygon = getPolygon(me); // my code - creates a Polygon object based on
                                       // mouse coordinates 
          screenDisplay.startDrawing(screenDisplay.getHDC(), (short) esriScreenCache.esriNoScreenCache);
          screenDisplay.setSymbol(getSymbol()); // my code - sets polygon symbology
          screenDisplay.drawPolygon(gabPolygon);
          screenDisplay.finishDrawing();
      }
  }
  catch(Exception e){
      e.printStackTrace();
  }
}
1

For anyone trying to do something like this, I found a solution using the help from danielm.

Let's go to the code:

@Override
public void mouseMoved(MouseEvent me) {
  try
  {
      IGraphicsContainer graphicsContainer = (IGraphicsContainer) mxDoc.getFocusMap();
      graphicsContainer.deleteAllElements();
      mxDoc.getActiveView().refresh();
      if(me.getButton() != 0)
      {
          mxDoc.getActiveView().refresh();
          gabPolygon = new Polygon();
          gabPolygon = getPolygon(me); // my method - see original question
          IPolygonElement gabElement = new PolygonElement();
          IElement elem = (IElement) gabElement;
          elem.setGeometry(gabPolygon);
          graphicsContainer.addElement(elem, 0);
          mxDoc.getActiveView().partialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
      }
  }
  catch(Exception e){
      e.printStackTrace();
  }
}

Drawings should not be done using IScreenDisplay, but IGraphicsContainer. The "magic" for clearing all dragging drawings is at the graphicsContainer.deleteAllElements() line. Refreshing is not needed at this event (but I maintained), but is still required for mousePressed and mouseReleased overrides.

0

When you draw to the screen like this it isn't actually adding the graphic to the map. This answer essentially goes through what you need to do. The differences:

  • You would use a PolygonElement instead of a RectangleElement.
  • You would probably want to cast your mxDoc.FocusMap as the IGraphicsContainer instead of the PageLayout
  • You would need to set the Symbol you want to use on the PolygonElement. Do this by casting it to an IFillShapeElement.

So it would probably look something like this (untested) code:

IGraphicsContainer graphicsContainer = mxDoc.FocusMap as IGraphicsContainer;
IPolygonElement polyElement = new PolygonElement();
IElement elem = polyElement as IElement;
elem.Geometry = getPolygon(me);
IFillShapeElement fillElement = polyElement as IFillShapeElement;
fillElement.Symbol = getSymbol();
graphicsContainer.AddElement(elem, 0);
activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
  • Thanks for the answer, danielm. But it doesn't work the way I need to. Your code also draws every polygon created during mouse move. I need to draw only the last one, erasing the previous. Only one should be at the screen. Any other ideas? – Diego Benincasa May 2 '17 at 12:35
  • Just to clarify: I do not want to add the drawing to the map. What am I trying to do is to implement an acquisition template (cartography requirement): if a feature is smaller than the template (fixed size for the acquisition scale used), it should not be acquired (vectorized). When tool is enabled, user should drag the template over the input (usually a sattelite image) and visually check the size. – Diego Benincasa May 2 '17 at 12:48
  • Well, I guess I found the solution myself. I used your code, but at the beginning I had to include a graphicsContainer.deleteAllElements. Now it works ok! Thanks for the help! – Diego Benincasa May 2 '17 at 13:00
  • Glad you found a solution. I didn't realize getPolygon was returning different polygons each time. – danielm May 2 '17 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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