6

We want to update a combobox so that it always shows the correct scale. If the user zooms-in, out or resizes the control hosting the map. What is the best event or events to catch and use in ArcGIS to update the scale?

Update1: Background I'm using the synchronization sample made by ESRI, and I can't find any event that handles the switching between map and layout. Tried using the MapControl ExtentUpdated event.

Public Function getScale() As Integer
    Dim returnValue As Integer = Convert.ToInt32(axMapControl1.ActiveView.ScreenDisplay.DisplayTransformation.ScaleRatio())
    Return returnValue
End Function

Private Sub axMapControl1_OnExtentUpdated(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.IMapControlEvents2_OnExtentUpdatedEvent) Handles axMapControl1.OnExtentUpdated
    TextBox1.Text = "Scale: " & getScale()
End Sub

Private Sub axPageLayoutControl1_OnExtentUpdated(ByVal sender As System.Object, ByVal e As ESRI.ArcGIS.Controls.IPageLayoutControlEvents_OnExtentUpdatedEvent) Handles axPageLayoutControl1.OnExtentUpdated
    TextBox1.Text = "Scale: " & getScale()
End Sub

Update2: Tried the ITransformEvents but it doesn't work when switching map to pagelayout:

  Private transformationEvents As ESRI.ArcGIS.Display.ITransformEvents_Event
    Private m_transformationEventsAfterDraw As ESRI.ArcGIS.Display.ITransformEvents_VisibleBoundsUpdatedEventHandler

    Private Sub wireEvent()
        transformationEvents = CType(axMapControl1.ActiveView.ScreenDisplay.DisplayTransformation, ESRI.ArcGIS.Display.ITransformEvents_Event)
        m_transformationEventsAfterDraw = New ESRI.ArcGIS.Display.ITransformEvents_VisibleBoundsUpdatedEventHandler(AddressOf OnTransformEventsVisibleBoundsUpdated)
        AddHandler CType(axMapControl1.ActiveView.ScreenDisplay.DisplayTransformation, ESRI.ArcGIS.Display.ITransformEvents_Event).VisibleBoundsUpdated, m_transformationEventsAfterDraw

    End Sub


    Private Sub OnTransformEventsVisibleBoundsUpdated(ByVal sender As ESRI.ArcGIS.Display.IDisplayTransformation, ByVal theSizeChanged As Boolean)
        TextBox1.Text = "Scale: " & getScale()
    End Sub

The result looks like this, the scalebar in the ESRI Toolbar is showing the layout scale but my textbox still shows the scale that was in the Map: Wrong scale in textbox

Update3: I tried this and now I get an Event when switching to the pagelayout but when I return to the map the scale is still way off:

Dim activeViewEventsMap As IActiveViewEvents_Event
    Private m_ActiveViewEventsViewRefreshedMap As IActiveViewEvents_ViewRefreshedEventHandler
    Private Sub wireActiveViewEventMap()
        activeViewEventsMap = TryCast(axMapControl1.ActiveView.FocusMap, IActiveViewEvents_Event)

        'Create an instance of the delegate, add it to ViewRefreshed event
        m_ActiveViewEventsViewRefreshedMap = New IActiveViewEvents_ViewRefreshedEventHandler(AddressOf OnActiveViewEventsViewRefreshedMap)
        AddHandler activeViewEventsMap.ViewRefreshed, m_ActiveViewEventsViewRefreshedMap
    End Sub


    Dim activeViewEventsPagelayout As IActiveViewEvents_Event
    Private m_ActiveViewEventsViewRefreshedPagelayout As IActiveViewEvents_ViewRefreshedEventHandler
    Private Sub wireActiveViewEventPagelayout()
        activeViewEventsPagelayout = TryCast(axPageLayoutControl1.ActiveView.FocusMap, IActiveViewEvents_Event)

        'Create an instance of the delegate, add it to ViewRefreshed event
        m_ActiveViewEventsViewRefreshedPagelayout = New IActiveViewEvents_ViewRefreshedEventHandler(AddressOf OnActiveViewEventsViewRefreshedPagelayout)
        AddHandler activeViewEventsPagelayout.ViewRefreshed, m_ActiveViewEventsViewRefreshedPagelayout
    End Sub

    Private m_scale As Integer = 0
    Private Sub OnActiveViewEventsViewRefreshedMap(ByVal view As IActiveView, ByVal phase As esriViewDrawPhase, ByVal data As System.Object, ByVal envelope As IEnvelope)
        Dim tempScale As Integer = getScaleMap()
        If m_scale <> tempScale Then
            TextBox1.Text = "Scale: " & tempScale
        End If
        m_scale = tempScale
    End Sub


    Private Sub OnActiveViewEventsViewRefreshedPagelayout(ByVal view As IActiveView, ByVal phase As esriViewDrawPhase, ByVal data As System.Object, ByVal envelope As IEnvelope)
        Dim tempScale As Integer = getScalePagelayout()
        If m_scale <> tempScale Then
            TextBox1.Text = "Scale: " & tempScale
        End If
        m_scale = tempScale
    End Sub


    Public Function getScaleMap() As Integer
        Dim returnValue As Integer

        Dim control As IMapControl4 = CType(m_controlsSynchronizer.ActiveControl, IMapControl4)
        returnValue = Convert.ToInt32(control.ActiveView.ScreenDisplay.DisplayTransformation.ScaleRatio())

        Return returnValue
    End Function


    Public Function getScalePagelayout() As Integer
        Dim returnValue As Integer
        Dim control As IPageLayoutControl3 = CType(m_controlsSynchronizer.ActiveControl, IPageLayoutControl3)
        returnValue = Convert.ToInt32(control.ActiveView.ScreenDisplay.DisplayTransformation.ScaleRatio())

        Return returnValue
    End Function

The solution: As far as I can see the only true way to catch when the scale is changed is by combining several methods, all of the above methods works if only a map or layout is used. The problem starts when used with the ESRI sync example, somehow the ESRI scale in the toolbar catches the switch between map and layout, probably because it is called when changing buddy control, but the only way to get the same behaviour is by using any of the above methods and adding a line of code that calculates and show the scale when the tab control event handler gets called, directly after the sync of the Map object to the active control.

2 Answers 2

4

Please note that ITransformEvents.VisibleBoundsUpdated also does not fire when you resize the map's frame element on page layout, which is an action that can change scale as well.

I personally ended up listening for IActiveViewEvents.ViewRefreshed on BOTH the map and the page layout. As this event fires very frequently (and for each uncached draw phase), I keep track of previous map scale and fire an action only when the current scale actually differs.

1
  • I thought that this worked, but it seems like I hit a new problem and that is getting the correct scale. Commented Sep 22, 2010 at 14:16
3

You are looking for an "event" which gets raised when the scale changes. You attach your subroutine/method to the event and that method gets fired every time the event happens. In your case you would attach a method like UpdateScaleUI() to the ScaleChangedEvent (or what ever it happens to be called, I haven't found it in the documents yet).

This is a discussion in a forum over at ESRI with sample code.

5
  • Yes, I know it's all about finding it in the documentation. Which isn't the easiest of tasks :) Commented Sep 21, 2010 at 15:38
  • 2
    Found it, it's the ITransformEvents you refering to help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/… Commented Sep 21, 2010 at 15:44
  • Well done! If you put all your info into a good answer, I'll vote you up and delete this one.
    – yhw42
    Commented Sep 21, 2010 at 16:01
  • Well it workes, but not fully, I'm not sure why the switching between map and layout in the synchronization sample doesn't fire the events. Commented Sep 21, 2010 at 17:59
  • Do the map event and the layout events have the same signature? (there might be an implicit cast or something... I'm just guessing)
    – yhw42
    Commented Sep 21, 2010 at 19:21

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.