Keep Mouse Events bubbling from WindowsFormsHost on

4.2k views Asked by At

I have Winforms control within a WPF WindowsFormsHost. The Winforms control is passive and must not handle any mouse event. Mouse events should be raised as usual from the most inner WPF control in the WPF visual tree, so the WindowsFormsHost (or the next one). But no event is triggered at all.

How should I configure the WindowsFormsHost, the Winforms control, in order to achieve this?

Remark: KeyDown and KeyUp behave as expected. But Mouse Events don't, as illustrated by the following Snoop screenshot:

enter image description here

1

There are 1 answers

2
jeromerg On

Indeed the Winforms Control keeps the mouse event for himself and doesn't forward the event to its host. The solution is to subscribe to the winforms MouseDown event and generate programmatically the Routed Event.

I overrided the WindowsFormsHost as following and it rocks:

(remark: a behavior may be more flexible)

public class ExtendedWindowsFormsHost : WindowsFormsHost
{
    public ExtendedWindowsFormsHost()
    {
        ChildChanged += OnChildChanged;
    }

    private void OnChildChanged(object sender, ChildChangedEventArgs childChangedEventArgs)
    {
        var previousChild = childChangedEventArgs.PreviousChild as Control;            
        if (previousChild != null)
        {
            previousChild.MouseDown -= OnMouseDown;
        }
        if (Child != null)
        {
            Child.MouseDown += OnMouseDown;
        }
    }

    private void OnMouseDown(object sender, MouseEventArgs mouseEventArgs)
    {
        MouseButton? wpfButton = ConvertToWpf(mouseEventArgs.Button);
        if (!wpfButton.HasValue)
            return;

        RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, wpfButton.Value)
        {
            RoutedEvent = Mouse.MouseDownEvent,
            Source = this,
        });
    }

    private MouseButton? ConvertToWpf(MouseButtons winformButton)
    {
        switch (winformButton)
        {
            case MouseButtons.Left:
                return MouseButton.Left;
            case MouseButtons.None:
                return null;
            case MouseButtons.Right:
                return MouseButton.Right;
            case MouseButtons.Middle:
                return MouseButton.Middle;
            case MouseButtons.XButton1:
                return MouseButton.XButton1;
            case MouseButtons.XButton2:
                return MouseButton.XButton2;
            default:
                throw new ArgumentOutOfRangeException("winformButton");
        }
    }
}