0

I have a UserControl that listens to it's own MouseLeave in order to change it's background color and some of it's children visibility. The children that should lose visibility, also listen their own MouseLeave in order to change their background color.

A scenario in which everything works is this:

  1. Move mouse into UserControl.
  2. Move mouse into Child.
  3. Move mouse out of Child into UserControl.

The problematic scenario is this:

  1. Move mouse into UserControl.
  2. Move mouse into Child.
  3. Move mouse out of Child, not into the UserControl, but directly outside of it.

This scenario happens all the time since the Child is located at the very edge of the UserControl. Note that not only the UserControl's MouseLeave doesn't fire, but neither does the Child's MouseLeave.

In order to find out whether the mouse has actually left the area in this case, I must listen to MouseEnter of other controls, and then notify the UserControl and Child, but I really want to avoid this solution, since it is ugly and not OOPish.

Also, the Child MUST be located at the very edge of the UserControl, and cannot move.

Can anyone think of a neat solution to the problem?

SimpleVar
  • 14,044
  • 4
  • 38
  • 60
  • What exactly are you doing with this. What is changing based on what events. This will help in finding the proper solution. – corylulu Oct 26 '12 at 21:53
  • It's all UI esthetics, nothing that can be done logically somehow else. – SimpleVar Oct 26 '12 at 21:54
  • Yes, but it's not made clear on if you are trying to fire one set of logic simply when the mouse is inside of a panel or any of it's children, or if different things are supposed to happen based on which control it's leaving from. – corylulu Oct 26 '12 at 21:58
  • Also, I'm not sure if there is an MouseEnter event being tied in as well. What I picture right now is a mouse going into a panel and the objects disappear and the bg changes colors. But when it leaves, does it revert back? – corylulu Oct 26 '12 at 22:01
  • Oh, yes. On MouseEnter the colors change back and the UserControl turns it's children visible again. There is no communication between the controls other than that of the UserControl controlling it's children's visibility on it's own MouseLeave. – SimpleVar Oct 26 '12 at 22:04
  • What about listening to the mouseenter event of the container of your usercontrol?. You could do it also inside the user control if you know the container reference. – Steve Oct 26 '12 at 22:07
  • The UserControl itself might be placed at the edge of it's parent, which will probably be the main form. The problem consists. – SimpleVar Oct 26 '12 at 22:09
  • Based on the information you stated here, I think my answer should do what your asking – corylulu Oct 26 '12 at 22:36

3 Answers3

7

My tests show this as a working solution. Just requires a custom user control.

    public class MyPanel : Panel
    {
        protected override void OnControlAdded(ControlEventArgs e)
        {
            e.Control.MouseLeave += DidMouseReallyLeave; 
            base.OnControlAdded(e);
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            DidMouseReallyLeave(this, e);
        }
        private void DidMouseReallyLeave(object sender, EventArgs e)
        {
            if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
                return;
            base.OnMouseLeave(e);
        }
    }
corylulu
  • 3,449
  • 1
  • 19
  • 35
  • Both the UserControl and the Child don't fire their MouseLeave event, so it might not work, but I'll try it. – SimpleVar Oct 26 '12 at 23:06
1

I've seen the same behavior before. Is your .NET version up-to-date? Be sure you're on the latest service packs.

Have you seen the event Application.AddMessageFilter? I used that in an answer here to catch mouse messages and handle them more intelligently. It might come in handy here.

Community
  • 1
  • 1
Paul Williams
  • 16,585
  • 5
  • 47
  • 82
0

This isn't how MouseLeave is supposed to behave. You should get the MouseLeave event even if the mouse cursor moves our of your application window entirely.

I'm guessing you're not calling the base method in your MouseLeave handler.

Anyway, on MouseEnter you can set a timer that fires every 0.25 second, and in it check if the mouse is still over the control. If it isn't, kill the timer and change the control's color.

zmbq
  • 38,013
  • 14
  • 101
  • 171
  • I don't need to call the base method, since I don't override it, I just listen to the event of myself. And the timer solution is obviously not what I'm looking for. I know I should get the MouseLeave event if it gets out no matter what, the problem is that I don't. – SimpleVar Oct 26 '12 at 21:53
  • How do you listen to the event without overriding MouseLeave? – zmbq Oct 26 '12 at 21:54
  • I just do `this.MouseLeave += ...` – SimpleVar Oct 26 '12 at 21:57