2

I require the cursor of the form to change to the cursor Cursors.Hand when the user hovers the pointer over a node with a specifically named parent node.

The issue I am having in implementing this is regarding changing the cursor back to the default one when the user moves the pointer away from the TreeNode in concern.

I have handled the NodeMouseHover event of the TreeView control (as in the code snippet in the end) to change the pointer to the alternative cursor and back to the default cursor when the pointer is moved to another node, but this does not handle the case when the user moves the pointer away from the nodes to a, say, a blank area of the TreeView control.

My initial, and only, intuition regarding the solution to this problem was to get the location and calculate the area of the TreeNodes which require the cursor to change and check if the pointer is still on one of these on the event handler of the MouseMove event of the TreeView control, but, I believe, this is not an elegant solution as there are a lot of TreeNodes that require this behavior which would require looping through a lot of them for checking, which in turn may cause the application to be, in rare scenarios, a tad non-responsive.

Thanks in advance.

PS The code snippet in question:

this.treeView.NodeMouseHover += delegate (object sender, TreeNodeMouseHoverEventArgs e)
{
   bool isNewCursorAssigned = false;
   if (e.Node.Parent != null)
   {
      if (e.Node.Parent.Text == "someTxt")
      {
         this.Cursor = Cursors.Hand;
         isNewCursorAssigned = true;
      }
   }
   if (isNewCursorAssigned == false && this.Cursor != this.DefaultCursor)
      this.Cursor = this.DefaultCursor;
};
hecate
  • 620
  • 1
  • 8
  • 33

2 Answers2

2

Handle the MouseMove instead, get a Node from the current mouse location, iterate backward to get the Parent (and the parent of the parent if any) of the current Node, and change the Cursor accordingly:

private void treeView1_MouseMove(object sender, MouseEventArgs e)
{
    var node = treeView1.GetNodeAt(e.Location);

    if (node != null)
    {
        var parent = node.Parent;

        while (parent != null)
        {
            if (parent.Text == "someTxt")
            {
                if (Cursor != Cursors.Hand)
                            Cursor = Cursors.Hand;
                        return;
            }
            parent = parent.Parent;
        }
        Cursor = Cursors.Default;
    }
}

Also handle the MouseLeave event to check if there's a need to Default the Cursor.

private void treeView1_MouseLeave(object sender, EventArgs e)
{
    if (Cursor != Cursors.Default)
        Cursor = Cursors.Default;
}

Or if you prefer the Lambda way:

//In the constructor:

treeView1.MouseMove += (s, e) =>
{
    var node = treeView1.GetNodeAt(e.Location);

    if (node != null)
    {
        var parent = node.Parent;
        while (parent != null)
        {
            if (parent.Text == "someTxt")
            {
                if (Cursor != Cursors.Hand)
                    Cursor = Cursors.Hand;
                return;
            }
            parent = parent.Parent;
        }
        Cursor = Cursors.Default;
    }
};

treeView1.MouseLeave += (s, e) =>
{
    if (Cursor != Cursors.Default)
        Cursor = Cursors.Default;
};
1

This is how I believe it must be done to incorporate the cursor changes when the cursor is moved sideways beyond the boundaries of the text of the node.

this.treeView.MouseMove += delegate (object sender, MouseEventArgs e)
{
     TreeNode concernedNode = this.treeViewOfAvailableMachines.GetNodeAt(e.Location);
     if (concernedNode != null)
        if (!(concernedNode.Parent != null && concernedNode.Parent.Text == "someTxt"))
               concernedNode = null;
     if (concernedNode != null)
     {
          if ((e.Location.X >= concernedNode.Bounds.Location.X &&
                    e.Location.X <= concernedNode.Bounds.Location.X + concernedNode.Bounds.Width) &&
                    (e.Location.Y >= concernedNode.Bounds.Location.Y &&
                    e.Location.Y <= concernedNode.Bounds.Location.Y + concernedNode.Bounds.Height))
          {
               this.Cursor = Cursors.Hand;
          }
          else
          {
               this.Cursor = this.DefaultCursor;
          }
     }
     else
     {
          this.Cursor = this.DefaultCursor;
     }
};
hecate
  • 620
  • 1
  • 8
  • 33
  • I think there are 2 flaws in this answer: 1. `this.treeViewOfAvailableMachines` should be `((TreeView)sender)`. Odd things can happen when you have more than 1 treeview. And 2. `MouseLeave` should be implemented as described in the other answer. – ffonz Mar 29 '21 at 11:38