【问题标题】:Can I get a MouseLeave event while Mouse.Capture() is active?当 Mouse.Capture() 处于活动状态时,我可以获得 MouseLeave 事件吗?
【发布时间】:2012-04-01 01:00:09
【问题描述】:

我有一个按钮。在 Button.MouseRightButtonDown 上,我调用的是 Mouse.Capture(button),因为我想检测是否有人在 Button 之外释放了右键单击。

我还注册了一个 Button.MouseLeave 事件。如果有人右键单击并拖动鼠标离开按钮,我希望触发此事件。

不幸的是,Mouse.Capture 似乎以某种方式阻止了 MouseLeave 的发生。

有谁知道解决方法,或者可以指出我哪里出错了?

(顺便说一句,如果有人好奇我这样做是为了什么,请参阅my other question。)

【问题讨论】:

    标签: c# wpf mouse capture mouseleave


    【解决方案1】:

    当鼠标被捕获时,您可以使用 MouseMove 和命中测试来确定鼠标是在您的元素内还是在另一个元素内。

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
    
        if (this.IsMouseCaptured)
        {
            HitTestResult ht = VisualTreeHelper.HitTest(this, e.GetPosition(this));
            if (ht != null)
            {
                DependencyObject current = ht.VisualHit;
                while (current != this && current != null)
                {
                    current = VisualTreeHelper.GetParent(current);
                }
    
                if (current == this)
                {
                    Debug.WriteLine("Inside");
                    return;
                }
            }
    
            Debug.WriteLine("Outside");
        }
    }
    

    下面的代码可以用来避免tree walk:

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
    
        if (this.IsMouseCaptured)
        {
            bool isInside = false;
    
            VisualTreeHelper.HitTest(
                this,
                d =>
                {
                    if (d == this)
                    {
                        isInside = true;
                    }
    
                    return HitTestFilterBehavior.Stop;
                },
                ht => HitTestResultBehavior.Stop,
                new PointHitTestParameters(e.GetPosition(this)));
    
            if (isInside)
            {
                Debug.WriteLine("Inside");
            }
            else
            {
                Debug.WriteLine("Outside");
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      根据我对您相关问题的回答,如果您使用 CaptureMouse() from UIElement 代替 Mouse.Capture(...) 那么您将看到正确的行为。

      public class MyButton : Button
      {
          protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
          {
              base.OnMouseRightButtonDown(e);
              CaptureMouse();
          }
      
          protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
          {
              base.OnMouseRightButtonUp(e);
              ReleaseMouseCapture();
          }
      
          protected override void OnMouseEnter(MouseEventArgs e)
          {
              base.OnMouseEnter(e);
              Debug.WriteLine("Mouse enter");
          }
      
          protected override void OnMouseLeave(MouseEventArgs e)
          {
              base.OnMouseLeave(e);
              Debug.WriteLine("Mouse leave");
          }
      }
      

      【讨论】:

      • 在我现有的代码中,将 Mouse.Capture() 更改为 CaptureMouse() 似乎没有改变任何行为。
      • 在我的简单测试中,我有一个窗口和一个自定义按钮(如上)。如果我右键单击按钮,然后将鼠标从按钮上松开,我会收到一条“鼠标离开”调试消息。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 2013-09-12
      • 2019-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多