Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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? Any help and ideas are greatly appreciated.

share|improve this question
    
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. –  Kirk Kuykendall Feb 7 '11 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 Feb 7 '11 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 Jun 29 at 2:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.