WPF ReleaseMouseCapture function does not release capture of Mouse events

DonBaechtel-7903 101 Reputation points
2023-03-05T17:11:40.1333333+00:00

I have a C# WPF application with a MainWindow. On this MainWindow, part of the area is covered by a Canvas. In XAML, the Canvas MouseEneter and MouseLeave events are set to the canvas. Whenever the Mouse Enters the Canvas, the Mouse events are captured and whenever the Mouse Leaves the canvas, then the Mouse events are supposed to be Released, as you can see from the code below.

The Mouse.Capture (cnv) works just fine. but even though the cnv.ReleaseMouse() statement is being executed, after the Mouse leaves the canvas, no other Mouse events are sent to the other controls on the MainWindow.

If I re-enter the canvas, the Mouse events continue to be sent to the Canvas.

Even the Mouse.Capture(null) statement does not release the Mouse.Capture(cnv) from the Canvas.

If I avoid entering the Canvas from the start, the Mouse events are sent to other MainWidow controls properly.

How can I get this to work so that when I enter the Canvas, mouse events are sent to cnv, and when I leave cnv, the Mouse.Capture is released and returns Mouse events to other controls on the MainWindow.

        private void CanvasEnter(object sender, MouseEventArgs e)
        {
            Canvas cnv = sender as Canvas;
            Mouse.Capture(cnv);
        }

        private void CanvasLeave(object sender, MouseEventArgs e)
        {
            Canvas cnv = sender as Canvas;
            Canvas ch = null;
            foreach (UIElement ui in area.Children)
            {
                if (ui.Uid == "croshairs")
                {
                    ch = ui as Canvas;
                    ch.Visibility = Visibility.Hidden;
                    break;
                }
            }
            cnv.ReleaseMouseCapture();
            Mouse.Capture(null);
        }            

Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
6,633 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,274 questions
No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Hui Liu-MSFT 16,001 Reputation points Microsoft Vendor
    2023-03-06T07:38:47.0266667+00:00

    Hi,@Don Baechtel. Welcome Microsoft Q&A.

    In my experience, it seems to take a mouse click to realize that the mouse pointer has actually left a control. You could write cnv.ReleaseMouseCapture() in the cnv_MouseLeftButtonDown method.

     private void Canvas_MouseEnter(object sender, MouseEventArgs e)
            {
                Canvas cnv = sender as Canvas;
                Mouse.Capture(cnv);
                croshairs.Visibility = Visibility.Visible;
            }
    
            private void Canvas_MouseLeave(object sender, MouseEventArgs e)
            {
                Canvas ch = null;
    
                foreach (UIElement ui in area.Children)
                {
                    if (ui.Uid == "croshairs")
                    {
                        ch = ui as Canvas;
                        ch.Visibility = Visibility.Hidden;
                        break;
                    }
                }
                canvas.Background =Brushes.Green ;
    
            }
            private void cnv_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                Canvas cnv = sender as Canvas;
                cnv.ReleaseMouseCapture();
    
            }
    
    

    The result:

    9


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. DonBaechtel-7903 101 Reputation points
    2023-03-10T13:22:44.79+00:00

    About the MouseLeave event, Microsoft states:

    "MouseLeave is a routed event that uses the direct event handling routing strategy. Direct routed events are not raised along a route; instead, they are handled in the same element where they are raised. However, they do enable other aspects of routed event behavior, such as event triggers in styles.

    Although MouseLeave tracks when the mouse leaves an element, this event more literally reports that the IsMouseOver property value has changed from true to false on this element."

    Working with Microsoft support, we determined that this is not entirely true. There are some conditions under which the MouseLeave event is NOT fired when "the IsMouseOver property value has changed from true to false on this element." One of these conditions is when the Mouse is MouseCaptured. You cannot trust the MouseLeave event to report when the above conditions happen.

    What I and Microsoft decided to do as a workaround is:

    1. Leave the Mouse.Capture(cnv); statement in the Canvas object's MouseEnter event handler.
    2. Remove the MouseLeave handler declaration from the XAML for the Canvass event since it could not be trusted to always work as documented.
    3. Add code to the Canvass MouseMove event handler to detect when the Mouse position had moved outside of the Canvass object area,
    4. If the MouseMove event detects that the Mouse is no longer over the Canvass object. the MouseMove event handler calls the previous MouseLeave event handler code to do any processing required for this condition, which includes Mouse.Capture(null);
    5. We are essentially using the MouseMove event handle to do double duty: to act on a MouseMove event, detect a MouseLeave condition, and call the appropriate code for MouseLeave.

    I tested this workaround and it works OK. The workaround is fairly simple and clean in this instance.

    It is too bad that Microsoft's MouseLeave event does not always work as documented.

    It is too bad that the Microsoft documentation failed to fully describe the functionality of the MouseLeave event, specially when it could not be relied upon to work as expected.

    Huge thanks to all here that attempted to help with this.