保持鼠标事件在WindowsFormsHost上的冒泡

4
我有一个Winforms控件嵌在WPF的WindowsFormsHost中。 Winforms控件是被动的,不应该处理任何鼠标事件。 鼠标事件应该像通常一样从WPF可视树中最内层的控件触发,因此是WindowsFormsHost(或下一个)。 但是没有事件被触发。 为了实现这一点,我应该如何配置WindowsFormsHost以及Winforms控件呢? 注:KeyDown和KeyUp的行为符合预期。但是,正如以下Snoop截图所示,鼠标事件并不会触发:

enter image description here


Winforms对Windows生成和路由通知的方式几乎没有什么改变,除了处理键盘快捷键和将某些消息从父级反射回子级。MouseWheel会冒泡到父级,其他事件则不会。WindowsFormsHost也无法改变这一点。所以这是完全可以预料的。如果一个控件不应该接收输入事件,那么它的Enabled属性应该被设置为false。你可能也不喜欢这个 :) - Hans Passant
谢谢!请解释一下...如果您用一个简单的WPF UserControl替换WindowsFormsHost,那么冒泡就会起作用,MouseDown事件会冒泡并在上升过程中引发订阅者的事件处理程序。似乎Winforms控件将鼠标事件保留给自己,并不将事件转发给其宿主。这是正确的吗? - jeromerg
1个回答

7

Winforms控件会独占鼠标事件,不会将事件转发给其宿主。解决方案是订阅Winforms MouseDown事件,并在程序中生成路由事件。

覆盖WindowsFormsHost的方法如下,并且效果非常好:

(备注:行为可能更加灵活)

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

请问您能否添加此文件的头文件?有些参数是否属于Windows Forms或Input存在混淆。 - Sorush
以下头文件应该可以工作:using System.Windows.Forms; using System.Windows.Forms.Integration; using System.Windows.Input; + 完全限定的 System.Windows.Forms.MouseButtons - niyou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接