I am working in ArcGIS 10.0 (ArcMap) and Python 2.6.5 and in the Data View. I have an IGroupElement3 to which I add a TextElement and up to several RectangleElements. I want then to retrieve the envelope of the GroupElement, recenter that envelope, and set the envelope as the new geometry of the GroupElement. The intent is to reposition (translate) the GroupElement. Here is a snippet:

pGrpElem = CType(pGroupElementFull, esriCarto.IElement)
pEnv = pGrpElem.Geometry.Envelope
pGrpElem.Geometry = pEnv

When the code runs, I get an error on the CenterAt method, saying I am performing an operation on an empty geometry. I checked, and indeed the pEnv is empty. So I have a few questions:

(1) Is this a valid method for moving a GroupElement?

(2) If not, how should I be doing it?

(3) If so, then I have a problem elsewhere. Do I have to add the component elements - and the GroupElement for that matter - to the display's GraphicsContainer to get them to "gel" and have valid envelopes? I was trying to avoid the GraphicsContainer step, because I really don't want the graphics to draw to the screen. The GroupElement is really for loading into an annotation feature. When I use the GraphicsContainer the screen drawing can get messed up unnecessarily. The graphics draw anyway when they are added to annotation, so I don't need two copies onscreen.

(4) If, as described above, I need to do something in addition to simply adding elements to the GroupElement to make their geometries visible to the GroupElement, how might I do that and avoid drawing the graphics to the screen at the same time?

Thanks for the help, all.

2 Answers 2


This is a common gotcha when working with GroupElements. The best way to change position, size etc. of group elements is to use the ITransform2D interface which the GroupElement class implements.

So, to recenter a group element to another location, first retrieve its current envelope through IElement.QueryBounds, for example. This will allow you to determine the offset to move the element to the desired location, which you will then use when calling ITransform2D.Move.

This Python function using comtypes centers an element (of just about any type, including a group element) to the [x,y] location. display is an IDisplay reference, this will usually be IActiveView.ScreenDisplay on the map. objectFactory is IObjectFactory used to create out-of-process COM objects.

def centerElementAt(element, display, x, y, objectFactory):
    boundsEnvelope = CType(objectFactory.Create("esriGeometry.Envelope"), esriGeometry.IEnvelope)
    (CType(element, esriCarto.IElement)).QueryBounds(CType(display, esriDisplay.IDisplay), boundsEnvelope)
    currentCenterPoint = CType((CType(boundsEnvelope, esriGeometry.IArea)).Centroid, esriGeometry.IPoint)
    transform2D = CType(element, esriGeometry.ITransform2D)
    transform2D.Move(x - currentCenterPoint.X, y - currentCenterPoint.Y)
  • Thank you, Petr. I shall try that. I am already using ITransform2D to rotate the GroupElement at some point, so I have a reference already. About the QueryBounds method: I have had trouble getting it to work. Can I create a new blank envelope and pass that in to get populated by QueryBounds? Feb 1, 2011 at 21:08
  • See the code sample. Yes, the envelope you pass to QueryBounds needs to be an existing IEnvelope instance.
    – Petr Krebs
    Feb 1, 2011 at 21:32
  • 1
    Also as a side note, remembering our previous discussion on in-process vs. inter-process COM calls, this is one of the cases when it's perfectly safe to use NewObj to create the Envelope instead of IObjectFactory. I still recommend using the object factory just like in the sample for performance reasons, but since ArcMap does not hold onto the envelope reference, you can try for yourself that it actually does NOT need to be instantiated inside the ArcMap process.
    – Petr Krebs
    Feb 1, 2011 at 22:09

I've also noticed when building a groupelement programatically it is (at least sometimes) necessary to call IElement.Activate in order to get a non-empty geometry.

  • 1
    Interesting, looks like a nice alternative to retrieving the current envelope using QueryBounds. The docs say that this method "prepares the screen display for output and orients the scale of the element to the specified display". I'm only curious what the display preparation means and whether it has any (possibly unwanted) side effects
    – Petr Krebs
    Feb 1, 2011 at 21:59
  • I should have mentioned that the elements I was adding to the group element were those returned from IGraphicsComposite.get_Graphics, on a legend, so this behavior might be specific to this context. Feb 1, 2011 at 22:21
  • Kirk, I did at least try the Activate method in the context I described above, but it did not "gel" the envelope. Using QueryBounds as petr k suggests below did the trick. Feb 3, 2011 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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