<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Best practice for changing cursor in ArcGIS Pro MapTool without lag in ArcGIS Pro SDK Questions</title>
    <link>https://community.esri.com/t5/arcgis-pro-sdk-questions/best-practice-for-changing-cursor-in-arcgis-pro/m-p/1693319#M13481</link>
    <description>&lt;P&gt;Hey there,&lt;/P&gt;&lt;P&gt;&lt;EM&gt;Traditional&lt;/EM&gt; OnToolMouseMove tricks wont work here but you can use some Task secret sauce (TaskCompletionSource).&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;    private Geometry _firstSelectedGeometry = null;
    private TaskCompletionSource&amp;lt;MapPoint&amp;gt; _tcs;
    private System.Windows.Point _lastClientPoint;
    private bool _processing = false; 

    protected override void OnToolMouseMove(MapViewMouseEventArgs args)
    {
      _lastClientPoint = args.ClientPoint;

      // If a conversion is already in progress, don't start another
      if (_processing)
        return;

      _processing = true;
      _tcs = new TaskCompletionSource&amp;lt;MapPoint&amp;gt;();

      QueuedTask.Run(() =&amp;gt;
        {
          var mapPoint = MapView.Active.ClientToMap(args.ClientPoint);
          _tcs.TrySetResult(mapPoint);
        });

      // Continue on UI thread when MCT finishes
      _ = HandleMapPointAsync();

      base.OnToolMouseMove(args);
    }

    private async Task HandleMapPointAsync()
    {
      try
      {
        var mapPoint = await _tcs.Task;
        bool isHit = GeometryEngine.Instance.Intersects(_firstSelectedGeometry, mapPoint);
        Cursor = isHit ? Cursors.Hand : Cursors.Cross;
      }
      finally
      {
        _processing = false;
      }
    }&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Why this works&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Only one ClientToMap is ever queued.&lt;/LI&gt;&lt;LI&gt;Latest mouse position always wins.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;If you have complex geometry you could still do a pre-hit test with the evelope (.Contains) but this may not be required.&lt;/P&gt;&lt;P&gt;Ps. This is not definitive Esri code....&lt;/P&gt;</description>
    <pubDate>Mon, 30 Mar 2026 09:33:43 GMT</pubDate>
    <dc:creator>sjones_esriau</dc:creator>
    <dc:date>2026-03-30T09:33:43Z</dc:date>
    <item>
      <title>Best practice for changing cursor in ArcGIS Pro MapTool without lag</title>
      <link>https://community.esri.com/t5/arcgis-pro-sdk-questions/best-practice-for-changing-cursor-in-arcgis-pro/m-p/1693051#M13480</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;I am developing an ArcGIS Pro SDK MapTool in C#.&lt;/P&gt;&lt;P&gt;I want to change the mouse cursor depending on whether the current mouse position is on a selected polygon feature or not.&lt;BR /&gt;For example:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;show `Hand` when the mouse is on the selected feature&lt;/LI&gt;&lt;LI&gt;show `Cross` otherwise&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;At first, I implemented the check inside `OnToolMouseMove` using `QueuedTask.Run`, something like:&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;protected override void OnToolMouseMove(MapViewMouseEventArgs args)
{
    _ = QueuedTask.Run(() =&amp;gt;
    {
        var mapPoint = MapView.Active.ClientToMap(args.ClientPoint);
        bool isHit = GeometryEngine.Instance.Intersects(_selectedGeometry, mapPoint);
        Cursor = isHit ? Cursors.Hand : Cursors.Cross;
    });

    base.OnToolMouseMove(args);
}&lt;/LI-CODE&gt;&lt;P&gt;However, this caused noticeable lag.&lt;BR /&gt;It looks like `QueuedTask` calls keep getting queued during mouse movement, and cursor updates become delayed.&lt;/P&gt;&lt;P&gt;I improved the behavior by preventing multiple simultaneous cursor checks and only processing the latest mouse position, but I still have these questions:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Is there any official or recommended best practice for changing the cursor dynamically in a `MapTool` based on mouse position?&lt;/LI&gt;&lt;LI&gt;Is there any way to avoid `ClientToMap` on every mouse move while still keeping correct hit-testing?&lt;/LI&gt;&lt;LI&gt;Is the default `MapTool` cursor documented anywhere?I am currently using `Cursors.Cross` as the non-hit cursor, but I am not sure whether that matches ArcGIS Pro’s default tool cursor.&lt;/LI&gt;&lt;LI&gt;More generally, what is the recommended pattern for high-frequency mouse-move processing in a `MapTool` when MCT access is required?&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;For context, the selected geometry may sometimes include multiple polygons, and possibly polygons with holes, so replacing the hit-test with a very rough custom approximation is not always ideal.&lt;/P&gt;&lt;P&gt;If anyone has sample code, recommendations, or experience with this kind of cursor handling, I would appreciate it.&lt;/P&gt;&lt;P&gt;Thank you.&lt;/P&gt;</description>
      <pubDate>Fri, 27 Mar 2026 05:31:55 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-sdk-questions/best-practice-for-changing-cursor-in-arcgis-pro/m-p/1693051#M13480</guid>
      <dc:creator>rdc_hirohara</dc:creator>
      <dc:date>2026-03-27T05:31:55Z</dc:date>
    </item>
    <item>
      <title>Re: Best practice for changing cursor in ArcGIS Pro MapTool without lag</title>
      <link>https://community.esri.com/t5/arcgis-pro-sdk-questions/best-practice-for-changing-cursor-in-arcgis-pro/m-p/1693319#M13481</link>
      <description>&lt;P&gt;Hey there,&lt;/P&gt;&lt;P&gt;&lt;EM&gt;Traditional&lt;/EM&gt; OnToolMouseMove tricks wont work here but you can use some Task secret sauce (TaskCompletionSource).&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;    private Geometry _firstSelectedGeometry = null;
    private TaskCompletionSource&amp;lt;MapPoint&amp;gt; _tcs;
    private System.Windows.Point _lastClientPoint;
    private bool _processing = false; 

    protected override void OnToolMouseMove(MapViewMouseEventArgs args)
    {
      _lastClientPoint = args.ClientPoint;

      // If a conversion is already in progress, don't start another
      if (_processing)
        return;

      _processing = true;
      _tcs = new TaskCompletionSource&amp;lt;MapPoint&amp;gt;();

      QueuedTask.Run(() =&amp;gt;
        {
          var mapPoint = MapView.Active.ClientToMap(args.ClientPoint);
          _tcs.TrySetResult(mapPoint);
        });

      // Continue on UI thread when MCT finishes
      _ = HandleMapPointAsync();

      base.OnToolMouseMove(args);
    }

    private async Task HandleMapPointAsync()
    {
      try
      {
        var mapPoint = await _tcs.Task;
        bool isHit = GeometryEngine.Instance.Intersects(_firstSelectedGeometry, mapPoint);
        Cursor = isHit ? Cursors.Hand : Cursors.Cross;
      }
      finally
      {
        _processing = false;
      }
    }&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Why this works&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Only one ClientToMap is ever queued.&lt;/LI&gt;&lt;LI&gt;Latest mouse position always wins.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;If you have complex geometry you could still do a pre-hit test with the evelope (.Contains) but this may not be required.&lt;/P&gt;&lt;P&gt;Ps. This is not definitive Esri code....&lt;/P&gt;</description>
      <pubDate>Mon, 30 Mar 2026 09:33:43 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-sdk-questions/best-practice-for-changing-cursor-in-arcgis-pro/m-p/1693319#M13481</guid>
      <dc:creator>sjones_esriau</dc:creator>
      <dc:date>2026-03-30T09:33:43Z</dc:date>
    </item>
  </channel>
</rss>

