Panel中的MouseEnter和MouseLeave事件及其子控件

时间:2010-04-04 21:53:31

标签: c# .net winforms mouseevent

我有一个包含子控件的Panel

如果我处理Panel的{​​{1}}和MouseEnter事件及其子项的MouseLeaveMouseEnter事件,则会按此顺序引发事件:

MouseLeave

但我需要以下顺序:

Panel.MouseEnter
Panel.MouseLeave
Child1.MouseEnter
Child1.MouseLeave
Panel.MouseEnter
Panel.MouseLeave

这可能吗?

10 个答案:

答案 0 :(得分:21)

如果你不介意创建一个usercontrol(派生自你想要的面板或其他父容器), 覆盖父项的OnMouseLeave方法,如下所示..

protected override void OnMouseLeave(EventArgs e)
{

    if(this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
         return;
    else
    {
        base.OnMouseLeave(e);
    }
}

然后,事件提升将按所需顺序进行。

答案 1 :(得分:5)

鼠标在进入子控件时“离开”面板,这就是它触发事件的原因。

您可以在面板MouseLeave事件处理程序中添加以下行中的内容:

// Check if really leaving the panel
if (Cursor.Position.X < Location.X ||
    Cursor.Position.Y < Location.Y ||
    Cursor.Position.X > Location.X + Width - 1 ||
    Cursor.Position.Y > Location.Y + Height - 1)
{
    // Do the panel mouse leave code
}

答案 2 :(得分:2)

解决方案是跟踪进入/离开的数量。 在你的整体控制中添加一个计数器:

private int mouseEnterCount = 0;

在MouseEnter处理程序中执行以下操作:

if (++mouseEnterCount == 1)
{
   // do whatever needs to be done when it first enters the control.
}

在MouseLeave处理程序中执行以下操作:

if (--mouseEnterCount == 0)
{
   // do whatever needs to be done when it finally leaves the control.
}

为所有子控件以及包含对象执行上述MouseEnter和MouseLeave事件处理程序。

答案 3 :(得分:2)

马修的答案永远不会奏效。特别是如果将子控件设置为其容器的边缘,并且鼠标在该方向上移出控件。您永远不会检测到MouseLeave事件。

最好的方法是创建一个用户控件容器,然后挂钩所有子控件的MouseEnter和MouseLeave事件,以便您可以随时正确地检测鼠标的位置和位置。那么,如果它进入容器的边界,你可以触发一个自定义的MouseEnter事件,当它离开MouseLeave事件时。

答案 4 :(得分:1)

答案 5 :(得分:0)

我相信。用于验证WinForms应用程序事件的好工具。

Windows.Forms事件顺序

http://missico.spaces.live.com/blog/cns!7178D2C79BA0A7E3!186.entry

  • 由Urs Eichmann编写的EventSpy创建。 (ftp://missico.net/EventSpy.zip
  • 启用.NET Framework 3.5并启用Visual Basic的Application Framework。

答案 6 :(得分:0)

这是一个棘手的问题,并且难以可靠地编码。一个想法是“捕获”列表中的3个传入事件,并在列表完成后执行所需的代码(列表中有3个所需事件)。然后,当您完成执行任何代码(或者可能反过来捕获事件组合)时,您可以清空列表并准备好下次特定组合事件发生时。不理想,但只是一个想法。

当然,这并没有克服潜在的解决问题。汉斯提出可能错过的事件。也许更多的背景是有序的。

答案 7 :(得分:0)

检查子组件..

if (panel1.GetChildAtPoint(panel1.PointToClient(Cursor.Position)) == null)
{
    // mouse leave panel and children
}

答案 8 :(得分:0)

Jimmy T.是对的。如果父控制(面板)边缘和儿童控制之间没有(或小)空间,则会出现问题。

这就是我在UserControl派生类中解决这个问题的方法:

    public CSStackPanelItem()
    {
        InitializeComponent();

        MouseEnter += new EventHandler(CSStackPanelItem_MouseEnter);

        foreach (Control child in Controls)
        {
            child.MouseEnter += (s, e) => CSStackPanelItem_MouseEnter(s, e);
            child.MouseLeave += (s, e) => OnMouseLeave(e);
        }
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
            return; //suppress mouse leave event handling

        if (m_bIsHover)
        {
            m_bIsHover = false;
            Invalidate(); //actually my mouse Enter/Leave event
        }

        base.OnMouseLeave(e);
    }

    void CSStackPanelItem_MouseEnter(object sender, EventArgs e)
    {
        m_bIsHover = true;
        Invalidate(); //actually my mouse Enter/Leave event
    }

答案 9 :(得分:0)

我的解决方案是为面板和该面板的父窗体创建一个 MouseEnter 事件。我不参与任何 MouseLeaving 事件。

当光标进入面板时,MouseEnter 会触发。我可以访问所有面板子控件,但没有任何反应(这是我想要的)。当我离开面板时,父表单的 MouseEnter 会触发。