6

i want to know if the mouse is in a particular control in .NET

private void panel1_MouseLeave(object sender, EventArgs e)
{
   if (MouseIsInControl((Control)sender)
      return; //the mouse didn't leave, don't fire a MouseLeave event

   ...
}

public Boolean MouseIsInControl(Control control)
{
    //return (control.Bounds.Contains(MousePosition));
    return control.Bounds.Contains(control.PointToClient(MousePosition))
}

But i need someone to fiddle with the four different coordinate systems to make it work.

Related questions

Community
  • 1
  • 1
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 1
    Ok so what is your question? You just said yourself how to solve it... – Tudor Nov 16 '11 at 22:20
  • possible duplicate of [How to detect if the mouse is inside the whole form and child controls in C#?](http://stackoverflow.com/questions/986529/how-to-detect-if-the-mouse-is-inside-the-whole-form-and-child-controls-in-c) – LarsTech Nov 16 '11 at 23:46
  • @LarsTech that detects when the mouse is inside a form, i need just a control on a form. – Ian Boyd Nov 17 '11 at 15:32
  • Sorry, I think I linked to the wrong question. I added an answer that shows how to do that. BTW, I wasn't a down voter. – LarsTech Nov 17 '11 at 15:47
  • Why was this question not updated with: http://stackoverflow.com/questions/8172535/winforms-how-to-cause-mouseenter-to-fire-when-the-mouse-enters-a-control#question – Kev Nov 19 '11 at 02:14
  • @Kev That's a separate question (`MouseEnter` event vs checking if the mouse is in a control). My motivation may stem from the same root problem: but the questions are different, with wider applicability than my immediate problem. And the *reason* for a question is irrelevant. – Ian Boyd Nov 20 '11 at 00:17
  • Ok that's fine, there were dupe flags and I thought "hey ho, Ian's an old hat on the site and wouldn't do a thing like that" :). So I'm only checking to see what's going on and to understand how they are different. Maybe you could make it clear in the other questions how they are different because to a non-winforms/.net user they're pretty darned similar. Thanks. – Kev Nov 20 '11 at 00:41
  • In the end none of the solutions were "good". i ended up creating a custom control, drawing all the elements myself. It's faster (one window rather than four), cleaner (doesn't require 3 screenfuls of buggy glue code), and doesn't experience the WinForms bugs (since i did Microsoft's job for them) – Ian Boyd Nov 21 '11 at 19:26
  • Isn't this redundant? If the mouse doesn't leave the control, it won't fire the mouseleave event. Am I missing something? – henriquesirot Nov 16 '11 at 23:18
  • There's a "quirk" in WinForms: if the mouse is moved over another control *inside the panel*, the `MouseLeave` event is fired (saying that the mouse has left the panel). Kind of like the alarm system of my house arming when i leave the house - when in reality i'm still in my house, just in the bathroom. – Ian Boyd Nov 17 '11 at 15:35

3 Answers3

10

No hooks or subclassing needed.

private bool MouseIsOverControl(Button btn) => 
    btn.ClientRectangle.Contains(btn.PointToClient(Cursor.Position))

This method also works if the mouse is outside of the form containing the control. It uses a button object but you can use any UI class

You can test the method easily like so:

private void button1_Click(object sender, EventArgs e)
{
    // Sleep to allow you time to move the mouse off the button
    System.Threading.Thread.Sleep(900); 

    // Try moving mouse around or keeping it over the button for different results
    if (MouseIsOverControl(button1))
         MessageBox.Show("Mouse is over the button.");
    else MessageBox.Show("Mouse is NOT over the button.");
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Victor Stoddard
  • 3,582
  • 2
  • 27
  • 27
4

This Hans Passant Answer can be adapted to do what you want:

private bool mEntered;
private Timer timer1;

public Form1() {
  InitializeComponent();

  timer1 = new Timer();
  timer1.Interval = 200;
  timer1.Tick += timer1_Tick;
  timer1.Enabled = false;
}

private void panel1_MouseEnter(object sender, EventArgs e) {
  timer1.Enabled = true;
}

private void timer1_Tick(object sender, EventArgs e) {
  bool entered = panel1.ClientRectangle.Contains(panel1.PointToClient(Cursor.Position));
  if (entered != mEntered) {
    mEntered = entered;
    if (!entered) {
      timer1.Enabled = false;
      // OK, Do something, the mouse left the parent container
    }
  }
}
Community
  • 1
  • 1
LarsTech
  • 80,625
  • 14
  • 153
  • 225
-1

I also use a System.Windows.Forms.Timer for this solution, but I don't use the enter/leave mouse events anymore. They have caused me too much grief. Instead I use the MouseMove event on the component I need to know the mouse is over. I have 2 member variables named in this class.

bool Hovering = false;
System.Drawing.Point LastKnownMousePoint = new System.Drawing.Point();

In my case, I wanted to toggle a border around a label. I deal with knowing if the mouse is over the label control I care about as follows:

    private void label1_MouseMove(object sender, MouseEventArgs e)
    {
        // Mouse Position relative to the form... not the control
        LastKnownMousePoint = Cursor.Position; 

        label1.BorderStyle = BorderStyle.Fixed3D;
        timer1.Stop();
        timer1.Interval = 50; // Very fast (Overkill?  :) )
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        System.Drawing.Point point = Cursor.Position;
        if (LastKnownMousePoint.Equals(point))
        {
            // If the mouse is somewhere on the label, I'll call that Hovering.  
            // Though not technically the MS definition, it works for me.
            Hovering = true;
        }
        else if (Hovering == false)
        {
            label1.BorderStyle = BorderStyle.None;
            timer1.Stop();
        }
        else
        {
            Hovering = false;
            // Next time the timer ticks, I'll stop the timer and
            // Toggle the border.
        }
    }

This works because I only update the LastKnownMousePoint when the mouse is over the control (a label in this case). So, if the mouse moves outside of the control, I won't update LastKnownMousePoint and I'll know it's time to toggle the border style.

Ronald Weidner
  • 690
  • 5
  • 15