2

I have written a simple tool to pan a viewer window (if present) to the centre of the map view, which reduces the number of clicks required and mouse travel to Pan Viewer to Map Location, it works mostly as anticipated but if the scale of the map viewer is set to a round number (in this case 24000) the scale is expanded on the first use but not on 3rd or subsequent uses: Before running the code Scale set before running. First time code is run Scale after running first time. Second and subsequent Scale for further instances.

The code:

IPoint CentreOfScreen = new PointClass();
IPoint CentreOfInset = new PointClass();

// derive the centre of the map from the active view extent
IEnvelope pMapExtent = ArcMap.Document.ActiveView.Extent;
CentreOfScreen.PutCoords((pMapExtent.XMax + pMapExtent.XMin) / 2,(pMapExtent.YMax + pMapExtent.YMin) / 2);

// get the application windows, could be of a few  
// types but we'll filter the one we want later
IApplicationWindows pAppWin = (IApplicationWindows)ArcMap.Application;
ISet pDatWindows = pAppWin.DataWindows;

// reset the enumeration and get the first object so that it's not null
// Leaving pDatWin unset will mean the loop will not progress
pDatWindows.Reset();
Object pDatWin = pDatWindows.Next();

while (pDatWin != null)
{
    if (pDatWin is IMapInsetWindow)
    {
        // this is the type of data window we want, not an overview window
        IMapInsetWindow pInsWin = (IMapInsetWindow)pDatWin;
        IMapInset pIns = pInsWin.MapInset;

        double pPreScale = 0;
        if (pIns.UsingZoomScale)
        {
            pPreScale = pIns.ZoomScale; // is set correctly 
        }

        // derive the centre of the map viewer from its visible bounds
        IEnvelope pExt = pIns.VisibleBounds;
        CentreOfInset.PutCoords((pExt.XMax + pExt.XMin) / 2, (pExt.YMax + pExt.YMin) / 2);

        // find how far to move the edges of the extent by finding the displacement
        // of the centre of screen to the centre of the map viewer
        double dX = CentreOfScreen.X - CentreOfInset.X;
        double dY = CentreOfScreen.Y - CentreOfInset.Y;

        // apply the offset to a new envelope
        IEnvelope pNewExt = new EnvelopeClass();
        pNewExt.PutCoords(pExt.XMin + dX,   pExt.YMin + dY,
                        pExt.XMax + dX, pExt.YMax + dY);

        // assert the new extent on the inset
        pIns.VisibleBounds = pNewExt;

        if (pIns.UsingZoomScale)
        {
            pIns.ZoomScale = pPreScale; // again set correctly
        }
        pInsWin.MapInset = pIns; // reset the inset window map inset

        // refresh and yield until the inset is redrawn
        pInsWin.Refresh();
        System.Windows.Forms.Application.DoEvents();
    }
    pDatWin = pDatWindows.Next(); // go to the next data window
}

Reasserting the scale seems to have no effect; The math is fairly simple so it's unlikely I'm making a mistake there, if there were a mistake in the math I would expect the extent to keep growing on 2nd and subsequent iterations.

Has anyone who has worked with a viewer window in ArcObjects that can establish why the scale changes and knows how to keep the original scale?

  • Did you try using PanStart, PanMoveTo, PanStop on IMapInsetWindow.ScreenDisplay ? – Kirk Kuykendall Jan 14 at 17:47
  • Yes @KirkKuykendall there was no effect on the IMapInsetWindow, either the PanMoveTo coordinates are in screen coordinates or there was something wrong with the IPoint I passed; I abandoned that approach early and copied some very old code for zoom2point which, from my comments, had the same problem which I solved by then setting IMap.MapScale before IActiveView.Refresh(). IMap is not implemented by IMapInsetWindow so I can't do that. I also tried pExt.Expand(0.9,0.9,true), while it did reduce the extent every iteration after that reduced the extent further. – Michael Stimson Jan 14 at 22:36
  • Before getting pIns.VisibleBounds, did you try calling pIns.CalculateVisibleBounds() ? – Kirk Kuykendall Jan 15 at 4:34
  • No luck there @KirkKuykendall, calling before IEnvelope pExt = pIns.VisibleBounds; changes the scale from 10k to ~330k but calling after pIns.ZoomScale = pPreScale; the scale becomes ~1.3 million, increasing to ~3 million on the second iteration. – Michael Stimson Jan 15 at 4:59

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.