14

I'm building a Windows Presentation Foundation control with Microsoft Blend.

When I leave my control by pressing the left-mouse-button, the MouseLeave-Event is not raised. Why not?

Michael Currie
  • 13,721
  • 9
  • 42
  • 58
freakinpenguin
  • 831
  • 14
  • 24
  • What is inside your control? I'm thinking that this is because the object (e.g. a Button) inside your control that received the MouseDown event has set the "Mouse.IsCaptured" to true so it's exclusively handling the MouseEvents. – ASanch Sep 26 '10 at 17:36
  • That's just a Border, Grid, Image an 2 Labels. Is that possible? – freakinpenguin Sep 28 '10 at 20:28
  • We are experiencing the same problem (see the question: http://stackoverflow.com/questions/15970248/wpf-mouse-leave-event-doesnt-trigger-with-mouse-down). So I have started a bounty here to draw attention. – SiberianGuy Apr 12 '13 at 13:26

4 Answers4

7

This is intended behaviour: When you are doing mousedown on a control and leaving the control, the control STILL retains its "capture" on the mouse, meaning the control won't fire the MouseLeave-Event. The Mouse-Leave Event instead will be fired, once the Mousebutton is released outside of the control.

To avoid this, you can simple tell your control NOT to capture the mouse at all:

private void ControlMouseDown(System.Object sender, System.Windows.Forms.MouseEventArgs e)
{
    Control control = (Control) sender;
    control.Capture = false; //release capture.
}

Now the MouseLeave Event will be fired even when moving out while a button is pressed.

If you need the Capture INSIDE the Control, you need to put in more effort:

  • Start tracking the mouseposition manually, when the mousekey is pressed

  • Compare the position with the Top, Left and Size Attributes of the control in question.

  • Decide whether you need to stop the control capturing your mouse or not.

    public partial class Form1 : Form
    {
    private Point point;
    private Boolean myCapture = false;
    
    public Form1()
    {
        InitializeComponent();
    }
    
    private void button1_MouseDown(object sender, MouseEventArgs e)
    {
        myCapture = true;
    }
    
    private void button1_MouseMove(object sender, MouseEventArgs e)
    {
        if (myCapture)
        {
            point = Cursor.Position;
    
            if (!(point.X > button1.Left && point.X < button1.Left + button1.Size.Width && point.Y > button1.Top && point.Y < button1.Top + button1.Size.Height))
            {
                button1.Capture = false; //this will release the capture and trigger the MouseLeave event immediately.
                myCapture = false;
            }
        }
    }
    
    private void button1_MouseLeave(object sender, EventArgs e)
    {
        MessageBox.Show("Mouse leaving");
    }
    

    }

of course you need to stop the own tracking ( myCapture=false;) on MouseUp. Forgot that one :)

dognose
  • 20,360
  • 9
  • 61
  • 107
  • 1
    But what if I need to raise MouseLeave when mouse leaves the whole window? I guess I won't receive MouveMouve events when mouse is out of Window so your MouseMove based solution won't work. Or am I wrong? – SiberianGuy Apr 12 '13 at 15:14
  • @Idsa It Works for Forms also. – dognose Apr 15 '13 at 08:53
  • 1
    But we are talking about WPF here. I doubt it will work for WPF Window – SiberianGuy Apr 15 '13 at 11:34
  • @Idsa Fogot to update my answer. I testet it, it doesn't work for windows, you are right. Reason is that the mouseMove Event won't update when leaving the form with the cursor. Not sure, if this is related to the question, as the TC statet to have the Problem for "Controls". – dognose Apr 15 '13 at 13:07
  • 2
    Control does not have Capture property! – Tim Robbins Jul 30 '15 at 11:52
  • @TimRobbins `System.Windows.Forms.Control` has a Capture Property. `System.Web.Ui.Control` or `System.Windows.controls.Control` has not. Thus you are right, this answer is actually not suitable for `WPF`. Maybe `UiElement.CaptureMouse()` might help with that: https://msdn.microsoft.com/en-us/library/ms598907(v=vs.110).aspx – dognose Jul 30 '15 at 12:14
1

And for completeness and historical reasons (not the bounty - it doesn't make sense having two duplicate questions - you should probably move it into one if not too late)...

I made a thorough solution using global mouse hook here (approach 2)
WPF: mouse leave event doesn't trigger with mouse down

And simplified its use - you can use it by binding to commands in your view-model - e.g.

my:Hooks.EnterCommand="{Binding EnterCommand}"
my:Hooks.LeaveCommand="{Binding LeaveCommand}"
my:Hooks.MouseMoveCommand="{Binding MoveCommand}"

...more details in there

Community
  • 1
  • 1
NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51
1

When I don't get mouse events I expect I typically use Snoop to help me understand what is happening.

Here are a couple of links:

1- Snoop (a WPF utility)
2- CodePlex project for Snoop

Zamboni
  • 7,897
  • 5
  • 43
  • 52
0

Old question but I came across the same problem with a Button (MouseLeave does not fire while MouseDown because MouseDown Captures the Mouse...)

This is how I solved it anyway:

element.GotMouseCapture += element_MouseCaptured;

static void element_MouseCaptured(object sender, MouseEventArgs e)
{
    FrameworkElement element = (FrameworkElement)sender;
    element.ReleaseMouseCapture();
}

Hope that helps someone looking for a quick fix :P

Drax
  • 11
  • 3