WPF Mousedown => No MouseLeave Event

2019-04-20 00:33发布

问题:

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?

回答1:

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 :)



回答2:

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



回答3:

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



标签: wpf events mouse