How to move map using custom map tool just like Pro explore tool

392
3
11-06-2023 11:21 PM
Hemant_Chitte
New Contributor

I am trying to create Custom map tool like Explore tool. i have create custom UI like Explore tool. the tool should be able to move the map and zoom in and zoom out. zoom in and zoom out  are working by default. but move map is not working for custom tool. can some one help me

 

@Wolf 

0 Kudos
3 Replies
VedantBajaj
Esri Contributor
0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

This custom tool did the pan of the map for me:

internal class MousePanTool : MapTool
{
    [DllImport("user32.dll")]
    public static extern short GetAsyncKeyState(UInt16 virtualKeyCode);
    public const int VK_LBUTTON = 0x01;
    private short _lastMouseButtonState = -1;

    private System.Windows.Point _fromMousePoint = new() { X = double.NaN, Y = double.NaN };
    private System.Windows.Point _toMousePoint = new() { X = double.NaN, Y = double.NaN };

    public MousePanTool()
    {
        SketchOutputMode = SketchOutputMode.Map;
    }

    /// <summary>
    /// Called when the mouse button is clicked in the view.
    /// </summary>
    protected override void OnToolMouseDown(MapViewMouseButtonEventArgs e)
    {
        if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
        {
            _fromMousePoint = e.ClientPoint;
            e.Handled = true;
            System.Diagnostics.Trace.WriteLine("!!! OnToolMouseDown");
        }                
        base.OnToolMouseDown(e);
    }

    /// <summary>
    /// Called when the mouse button is released in the view.
    /// </summary>
    protected override void OnToolMouseUp(MapViewMouseButtonEventArgs e)
    {
        if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
        {
            e.Handled = true;
            _fromMousePoint = new() { X = double.NaN, Y = double.NaN };
            System.Diagnostics.Trace.WriteLine("!!! OnToolMouseUp");
        }
        base.OnToolMouseUp(e);
    }

    private bool _isPanning = false;
    protected override async void OnToolMouseMove(MapViewMouseEventArgs e)
    {
        var mapView = MapView.Active;
        if (mapView == null || _isPanning)
            return;
        var mouseButtonState = GetAsyncKeyState(VK_LBUTTON);
        if ((mouseButtonState & 0x8000) == 0x0)
        {
            // the physical left button is not down anymore - stop panning
            _fromMousePoint = new() { X = double.NaN, Y = double.NaN };
            if (_lastMouseButtonState != mouseButtonState)
            {
                System.Diagnostics.Trace.WriteLine("!!! MouseUp during mouse move");
                _lastMouseButtonState = mouseButtonState;
            }
            return;
        }
        _lastMouseButtonState = mouseButtonState;
        if (_fromMousePoint.X != double.NaN)
        {
            _toMousePoint = e.ClientPoint;
            _isPanning = true;
            try
            {
                await QueuedTask.Run(() =>
                {
                    var fromPoint = mapView.ClientToMap(_fromMousePoint);
                    var toPoint = mapView.ClientToMap(_toMousePoint);
                    var deltaX = toPoint.X - fromPoint.X;
                    var deltaY = toPoint.Y - fromPoint.Y;
                    var camera = mapView.Camera;
                    camera.X -= deltaX;
                    camera.Y -= deltaY;
                    mapView.PanTo(camera);
                    _fromMousePoint = _toMousePoint;
                });
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex);
            }
            finally
            {
                _isPanning = false;
            }
            _isPanning = false;
            e.Handled = true;
        }
    }

    protected override Task OnToolActivateAsync(bool active)
    {
        _fromMousePoint = new() { X = double.NaN, Y = double.NaN };
        return base.OnToolActivateAsync(active);
    }

    protected override Task OnToolDeactivateAsync(bool active)
    {
        _fromMousePoint = new() { X = double.NaN, Y = double.NaN };
        return base.OnToolActivateAsync(active);
    }
}

This sample only works for 'right-handed' mouse configurations, meaning the left mouse button is the 'physical' left mouse button.  To consider a 'left-handed' mouse configuration you can determine the system's current mapping of physical mouse buttons to logical mouse buttons by calling GetSystemMetrics(SM_SWAPBUTTON) which returns TRUE if the mouse buttons were swapped.

Instead of writing your own custom navigation you can also reuse the map navigation functionality that's built into ArcGIS Pro:

var command = FrameworkApplication.GetPlugInWrapper("esri_mapping_exploreTool") as ICommand;
if (command.CanExecute(null))
    command.Execute(null);

 

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

In order to consider left-handedness, you can use this code snippet (i didn't test this one):

    [DllImport("user32.dll")]
    public static extern short GetAsyncKeyState(UInt16 virtualKeyCode);
    public const int VK_LBUTTON = 0x01;
    public const int VK_RBUTTON = 0x02;
    private short _lastMouseButtonState = -1;

    [DllImport("user32.dll")]
    public static extern Int32 GetSystemMetrics(Int32 bSwap);
    public const int SM_SWAPBUTTON = 23;

...
var logicalLeftButton = Convert.ToUInt16(GetSystemMetrics(SM_SWAPBUTTON) != 0 ? VK_RBUTTON : VK_LBUTTON);
var mouseButtonState = GetAsyncKeyState(logicalLeftButton);
0 Kudos