3

Does anyone know a good alternative to the IMapServer2.ExportScaleBar function?

I want to do essentialy the same task, but outside the ArcGIS Server environment. For a given map scale, predefined scale bar style, scale bar size and image resolution, I'd like to generate a scale bar image.

I know I could add a scale bar to the page layout and then export the whole layout, but I do not want to clutter and/or modify the page layout if at all possible.

This is the closest I was able to get, but works only if the resolution used is 96 DPI (screen resolution).

IMapSurround mapSurround = null;
IMap map = GetMap(); // returns the map

var originalScale = map.MapScale;

try
{
    var scaleBar = DefaultSymbols.ScaleBar; // returns a scalebar with some predefined properties
    var scaleBarUid = new UIDClass() {Value = scaleBar.GetType().GUID.ToString("B")};

    mapSurround = map.CreateMapSurround(scaleBarUid, scaleBar);

    var resolution = 300;

    map.MapScale = 1000;

    mapSurround.Refresh();
    ((IScaleBar)mapSurround).UseMapSettings();

    var querySize = (IQuerySize)mapSurround;
    double widthPoints = 0;
    double heightPoints = 0;

    querySize.QuerySize(ref widthPoints, ref heightPoints);

    var widthInches = 3.0; // scale bar is 3 inches wide
    var heightInches = widthInches * (heightPoints / widthPoints); // determine height by respecting the aspect ratio

    var pixelsWidth = (int)(widthInches * resolution);
    var pixelsHeight = (int)(heightInches * resolution);

    using (var bitmap = new Bitmap(pixelsWidth, pixelsHeight, PixelFormat.Format32bppRgb))
    {
        bitmap.SetResolution(resolution, resolution);

        using (var graphics = Graphics.FromImage(bitmap))
        {
            graphics.Clear(Color.White);

            var simpleDisplay = new SimpleDisplayClass();
            simpleDisplay.DisplayTransformation.Resolution = resolution;
            simpleDisplay.DisplayTransformation.Units = esriUnits.esriInches;
            simpleDisplay.DisplayTransformation.Bounds = new EnvelopeClass
                 {
                     XMin = 0,
                     YMin = 0,
                     XMax = widthInches,
                     YMax = heightInches
                 };
            simpleDisplay.DisplayTransformation.VisibleBounds = simpleDisplay.DisplayTransformation.Bounds;

            var tagRect = new tagRECT {left = 0, top = 0, right = pixelsWidth, bottom = pixelsHeight};
            simpleDisplay.DisplayTransformation.set_DeviceFrame(ref tagRect);

            simpleDisplay.StartDrawing(graphics.GetHdc().ToInt32(), 0);

            var drawBounds = new EnvelopeClass
                 {
                     XMin = 0,
                     YMin = 0,
                     XMax = widthInches,
                     YMax = heightInches
                 };

            mapSurround.Draw(simpleDisplay, null, drawBounds);

            simpleDisplay.FinishDrawing();
        }
        bitmap.Save("c:\\image.bmp", ImageFormat.Bmp);
    }
}
finally
{
    map.MapScale = originalScale;

    if (mapSurround != null)
    {
        map.DeleteMapSurround(mapSurround);
    }
}

For resolutions other than 96 DPI this does not work correctly, the scale bar IS drawn to the bitmap, but the measurements it shows are not correct.

Is there a way to do this?

3
  • Did you try calling IActiveView.Activate using a window handle from GetDesktopWindow ? rantincsharp.wordpress.com/2010/10/29/… I'm not even sure what the desktop window should be when running as a gp service on a virtual server (which is what I was dealing with) but this worked. Maybe someday I'll figure out why. Commented Feb 7, 2011 at 23:09
  • I am actually working within an ArcMap session, so all the objects are properly initialized. Changes to scale etc. are working.
    – Petr Krebs
    Commented Feb 7, 2011 at 23:21
  • This three year old question has no attracted any answers, or more comments during that time. If you have discovered the answer in the meantime would you be able to post that here, please? If you think it is still an important question that needs an answer perhaps you can edit it to try and tease that out somewhere? It may help to include the last version at which you have tested this too. If it is no longer important perhaps just delete it?
    – PolyGeo
    Commented Jun 29, 2014 at 2:05

1 Answer 1

1

If you still need a solution to this question then I think you should post an ArcGIS Idea to have ArcObjects enhanced, and then post a link within a self-answer to your own question so that I can delete this one.

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.