Могу ли я получить событие MouseLeave, когда Mouse.Capture () активен? - PullRequest
1 голос
/ 01 апреля 2012

У меня есть кнопка. На Button.MouseRightButtonDown я вызываю Mouse.Capture (button), потому что я хочу определить, отпускает ли кто-нибудь правый щелчок за пределами Button.

У меня также зарегистрировано событие Button.MouseLeave. Если кто-то щелкнет правой кнопкой мыши по кнопке, я хочу, чтобы это событие сработало.

К сожалению, похоже, что Mouse.Capture каким-то образом блокирует MouseLeave.

Кто-нибудь знает обходной путь, или, может быть, может указать, где я иду не так?

(Кстати, если кому-то интересно, зачем я это делаю, см. мой другой вопрос .)

Ответы [ 2 ]

4 голосов
/ 01 апреля 2012

Когда мышь захвачена, вы можете использовать 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");
    }
}

Чтобы избежать обхода дерева, можно использовать следующий код:

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");
        }
    }
}
0 голосов
/ 01 апреля 2012

Исходя из моего ответа на ваш связанный вопрос, если вместо Mouse.Capture (...) вы используете CaptureMouse() из UIElement, то вы увидите правильное поведение.

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");
    }
}
...