3

I have a PagyLayoutControl in a print preview dialog. It shows the same extent and layers as the master MapControl. Both controls are not syncronised, because changes made in the PageLayoutControl shall not be reflected in the MapControl. So I load the same map file into the PageLayoutControl and copy the layers from the MapControl. That works fine.

The MapControl adds some Texts to the selected features in the AfterDraw event like this:

private void MapControl_OnAfterDraw(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnAfterDrawEvent e)
{
  if (e.viewDrawPhase == (int)esriViewDrawPhase.esriViewForeground)
  {
    for (int iL = 0; iL < _mapControl.Map.LayerCount; iL++)
    {
      IFeatureSelection features = _mapControl.Map.Layer[iL] as IFeatureSelection;
      if ((features != null) && (features.SelectionSet != null))
      {
        ICursor cursor;
        features.SelectionSet.Search(null, true, out cursor);
        IFeature feature;
        while ((feature = ((IFeatureCursor)cursor).NextFeature()) != null)
        {
          int iBt1 = feature.Fields.FindField("TEXT1");
          if (iBt1 < 0)
            iBt1 = feature.Fields.FindField("NAME");
          if ((feature.Shape != null) && (iBt1 >= 0))
          {
            object ofskz = feature.get_Value(iBt1);
            if (ofskz != null)
            {
              String someText = ofskz.ToString();
              _mapControl.DrawShape(feature.Shape);

              IArea farea = feature.Shape as IArea;
              ESRI.ArcGIS.Geometry.Point start = new ESRI.ArcGIS.Geometry.Point();
              start.X = farea.LabelPoint.X - 100;
              start.Y = farea.LabelPoint.Y;
              ESRI.ArcGIS.Geometry.Point end = new ESRI.ArcGIS.Geometry.Point();
              end.X = farea.LabelPoint.X + 100;
              end.Y = farea.LabelPoint.Y;
              ESRI.ArcGIS.Geometry.Polyline baseline = new ESRI.ArcGIS.Geometry.Polyline();
              baseline.AddPoint(start);
              baseline.AddPoint(end);
              ITextSymbol textSymbol = new TextSymbolClass();
              textSymbol.VerticalAlignment = esriTextVerticalAlignment.esriTVACenter;
              object oTextSym = textSymbol;
              _mapControl.DrawText((ESRI.ArcGIS.Geometry.IGeometry)baseline, someText, ref oTextSym);     
            }
          }
        }
      }
    }
  }
}

I tried to reproduce this for the PageLayoutControl but failed, because there are no methods like MapControls DrawText and DrawShape. I didn't found something like DrawShape with the PageLayoutControl. OK, I can live without the shape been drawn. But the text is what bugs me. I found and tried ActiveView.ScreenDisplay.DrawText which indeed draws text on the map, but it seems that is uses a different positioning than the MapControl.DrawText. I simply tried to use the Point start as the IGeometry for DrawText:

private void Pagelayout_OnAfterDraw(object sender, ESRI.ArcGIS.Controls.IPageLayoutControlEvents_OnAfterDrawEvent e)
{
  if (e.viewDrawPhase == (int)esriViewDrawPhase.esriViewForeground)
  {
    for (int iL = 0; iL < _pageLayoutControl.ActiveView.FocusMap.LayerCount; iL++)
    {
      IFeatureSelection features = _pageLayoutControl.ActiveView.FocusMap.Layer[iL] as IFeatureSelection;
      if ((features != null) && (features.SelectionSet != null))
      {
        ICursor cursor;
        features.SelectionSet.Search(null, true, out cursor);
        IFeature feature;
        while ((feature = ((IFeatureCursor)cursor).NextFeature()) != null)
        {
          int iBt1 = feature.Fields.FindField("TEXT1");
          if (iBt1 < 0)
            iBt1 = feature.Fields.FindField("NAME");
          if ((feature.Shape != null) && (iBt1 >= 0))
          {
            object ofskz = feature.get_Value(iBt1);
            if (ofskz != null)
            {
              String someText = ofskz.ToString();

              //_mapControl.DrawShape(feature.Shape);

              IArea farea = feature.Shape as IArea;
              ESRI.ArcGIS.Geometry.Point start = new ESRI.ArcGIS.Geometry.Point();
              start.X = farea.LabelPoint.X - 100;
              start.Y = farea.LabelPoint.Y;

              ITextSymbol textSymbol = new TextSymbolClass();
              textSymbol.VerticalAlignment = esriTextVerticalAlignment.esriTVACenter;
              object oTextSym = textSymbol;                    

              int mapx;
              int mapy;
              _pageLayoutControl.ActiveView.ScreenDisplay.DisplayTransformation.FromMapPoint(start, out mapx, out mapy);
              IPoint point = new ESRI.ArcGIS.Geometry.Point();
              point.X = mapx;
              point.Y = mapy;                    

              _pageLayoutControl.ActiveView.ScreenDisplay.DrawText((IGeometry)point, someText);
              }
            }
          }
        }
      }
    }
  }
}

The Text is drawn somewhere on the map but not where it is drawn in the MapControl. start has a value like 3103951.3241, 2503651.3274, which seems to me to be world coordinates. I tested to draw at the mouse position (something like 6.4,7.2 - screen coordinates) which draws at the correct position. So I tried the conversion with FromMapPoint which changed the numbers but with no success in drawing at the right position.

How do I find the right input coordinate for DrawText? Or is there an alternative way to draw text in the PageLayoutControl?

1 Answer 1

3

Keep in mind a pagelayout can have multiple maps. To draw text on a particular map in the layout you can use IGraphicsContainer.FindFrame and pass the IMap, or loop through all the elements til you find an IMapFrame using IGraphicsContainer.Next(). Be sure to call IGraphicsContainer.Reset before starting and be aware if you have grouped elements you'll need to recurse.

Once you find an IMapFrame, cast IMapFrame.Map to IActiveViewEvents_Event, and wire up AfterDraw, and draw the text in that handler.

7
  • Thanks, Kirk. That's it. I wired up the event and do the draw like this Display.SetSymbol((ISymbol)textSymbol); Display.DrawText((IGeometry)start, someText);
    – gumo
    Commented Sep 27, 2011 at 12:53
  • Ah, one issue with this solution: When I select an object in the PagyLayoutControl which is partly outside of the extent, the AfterDraw event seems to be lost, because it's never raised afterwards. Is there a way to re-wire the event to the MapFrame?
    – gumo
    Commented Sep 27, 2011 at 13:45
  • Not sure what you mean. You might try casting the mapframe to IElementProperties and assign an instance of your class that's doing the listening to IElementProperties.CustomProperty. I think the documentation is misleading - if you don't need to persist the customproperty, no harm is done by not implementing IPersistStream/IPersistVariant. Commented Sep 27, 2011 at 13:53
  • 1
    Also, just looking at your code, it seems like what your doing might more appropriately be handled in a layer extension that does the drawing in ILayerExtensionDraw.AfterLayerDraw. Commented Sep 27, 2011 at 13:57
  • Kirk, where can I hook the ILayerExtensionDraw.AfterLayerDraw? I'm a bit lost in the ESRI interface jungle... :)
    – gumo
    Commented Sep 27, 2011 at 14:30

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.