How to create an advanced pan tool


There are two approaches to panning - TrackPan and the group PanStart, PanMoveTo, and PanStop. TrackPan is the easiest to use as it takes care of all the mouse events, performs the pan, and refreshes the display when the pan is complete. This sample shows how to use the PanStart group which gives developers more control. This pan tool works very much like ArcMap's pan tool working with whatever view is currently acitve: the focus map, an activated view, the layout view, and magnifier windows.
See the How to TrackPan for a sample showing how TrackPan works.

How to use

  1. Add a UIToolControl to any toolbar.
  2. Paste this code in for the control. Make sure the name of thenew control matches the sample code. The sample codeassumes the control's name is UIToolControl1.
  3. Load some data and after zooming in, use the new Pan tool.
  4. Add several magnifier windows and notice how the pan works only when they are in snap shot mode.
[VBA]
Option Explicit

Private m_pMxApp As IMxApplication
Private m_pMxDocument As IMxDocument
Private m_pScreenDisplay As IScreenDisplay
Private m_pMapInsetWindow As IMapInsetWindow
Private m_bMouseDown As Boolean

Private Sub UIToolControl1_MouseDown(ByVal button As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)
    Dim pStartPoint As IPoint
    
    If Not button = 1 Then Exit Sub 'Check for single click
    
    'Get the screen display currently with focus
    Set m_pScreenDisplay = GetFocusDisplay
    'Check if this screen display is a magnification window
    Set m_pMapInsetWindow = GetMapInset(m_pScreenDisplay)
    If Not m_pMapInsetWindow Is Nothing Then
        'Don't allow user to pan if mag. window doesn't have a snap shot
        If m_pMapInsetWindow.IsLive Then Exit Sub
    End If
    
    'Start the pan
    m_bMouseDown = True
    Set pStartPoint = m_pScreenDisplay.DisplayTransformation.ToMapPoint(x, y)
    m_pScreenDisplay.PanStart pStartPoint
    
End Sub

Private Sub UIToolControl1_MouseMove(ByVal button As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)
    Dim pMoveToPoint As IPoint
    If Not m_bMouseDown Then Exit Sub
    Set pMoveToPoint = m_pScreenDisplay.DisplayTransformation.ToMapPoint(x, y)
    m_pScreenDisplay.PanMoveTo pMoveToPoint
End Sub

Private Sub UIToolControl1_MouseUp(ByVal button As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)
    Dim pEnvelope As IEnvelope
    Dim pActiveView As IActiveView
    Dim pMapInset As IMapInset
    Dim pMapInsetWindow As IMapInsetWindow
    
    If Not m_bMouseDown Then Exit Sub
    
    m_bMouseDown = False
    Set pEnvelope = m_pScreenDisplay.PanStop 'Stop panning
    If pEnvelope Is Nothing Then Exit Sub
    
    'Check if the screen display with focus is a magnification window
    If Not m_pMapInsetWindow Is Nothing Then
        'We already know that if we have a mag window, it has a snap shot so do the pan
        Set pMapInset = m_pMapInsetWindow.MapInset
        pMapInset.VisibleBounds = pEnvelope
        m_pMapInsetWindow.Refresh
        Exit Sub
        'Otherwise, check if we are in data view or layout view
    Else
        Set pActiveView = m_pMxDocument.ActiveView
        If TypeOf pActiveView Is IMap Then
            pActiveView.Extent = pEnvelope 'Change the extent of the map
            pActiveView.Refresh 'Refresh the screen
        Else 'Must be in layout view
            Set pActiveView = pActiveView.FocusMap
            pActiveView.Extent = pEnvelope
            pActiveView.Refresh
        End If
    End If
    
End Sub

Private Sub UIToolControl1_Select()
    m_bMouseDown = False
    Set m_pMxApp = Application
    Set m_pMxDocument = Application.Document
End Sub

Private Function GetFocusDisplay() As IScreenDisplay
    Dim pActiveView As IActiveView
    Dim pActiveMap As IMap
    
    'Check if we are in layout or data view
    Set pActiveView = m_pMxDocument.ActiveView
    If TypeOf pActiveView Is IMap Then
        'Return the ScreenDisplay of the FocusScreen.  This could be the main
        'map window or a lens (magnifier window).
        Set GetFocusDisplay = m_pMxApp.Display.FocusScreen
    Else
        'Must be in Layout view.  Return the ScreenDisplay of FocusMap
        Set pActiveView = pActiveView.FocusMap
        Set GetFocusDisplay = pActiveView.ScreenDisplay
    End If
End Function

Private Function GetMapInset(pScreenDisplay As IScreenDisplay) As IMapInsetWindow
    Dim pAppWindows As IApplicationWindows
    Dim pWindowsSet As ISet
    Dim pDataWindow As IDataWindow
    Dim pLensWindow As ILensWindow
    
    'Determine which data window the screen display belongs to
    Set pAppWindows = m_pMxApp 'QI
    Set pWindowsSet = pAppWindows.DataWindows
    pWindowsSet.Reset
    Set pDataWindow = pWindowsSet.Next
    Do While Not pDataWindow Is Nothing
        'Only look at lens windows
        If TypeOf pDataWindow Is ILensWindow Then
            Set pLensWindow = pDataWindow
            If pLensWindow.ScreenDisplay Is m_pScreenDisplay Then
                'Double check that we are indeed working with a MapInsetWindow object
                If TypeOf pLensWindow Is IMapInsetWindow Then
                    Set GetMapInset = pLensWindow
                    Exit Function
                End If
            End If
            
        End If
        Set pDataWindow = pWindowsSet.Next
    Loop
    
    'Couldn't find a data window that matched
    Set GetMapInset = Nothing
    
End Function