从子控件移动到父级父级时,MouseLeave不会触发

时间:2012-10-26 21:28:05

标签: c# winforms user-controls

我有一个UserControl,它会监听它自己的MouseLeave,以便改变它的背景颜色以及它的一些儿童可见性。 应该失去知名度的孩子,也要听他们自己的MouseLeave以改变他们的背景颜色。

一切正常的场景是:

  1. 将鼠标移动到UserControl。
  2. 将鼠标移动到Child。
  3. 将鼠标从Child移出到UserControl。
  4. 有问题的情况是:

    1. 将鼠标移动到UserControl。
    2. 将鼠标移动到Child。
    3. 将鼠标移出Child,而不是移到UserControl中,而是直接移出它。
    4. 这种情况一直发生,因为Child位于UserControl的最边缘。 请注意,不仅UserControl的MouseLeave不会触发,而且Child的MouseLeave也不会触发。

      为了确定鼠标是否实际上已离开该区域,我必须听其他控件的MouseEnter,然后通知UserControl和Child,但我真的想避免这个解决方案,因为它很难看而不是OOPish。

      此外,Child必须位于UserControl的最边缘,并且无法移动。

      有人能想出这个问题的巧妙解决方案吗?

3 个答案:

答案 0 :(得分:5)

我的测试显示这是一个有效的解决方案。只需要一个自定义用户控件。

    public class MyPanel : Panel
    {
        protected override void OnControlAdded(ControlEventArgs e)
        {
            e.Control.MouseLeave += DidMouseReallyLeave; 
            base.OnControlAdded(e);
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            DidMouseReallyLeave(this, e);
        }
        private void DidMouseReallyLeave(object sender, EventArgs e)
        {
            if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
                return;
            base.OnMouseLeave(e);
        }
    }

答案 1 :(得分:1)

之前我见过同样的行为。您的.NET版本是最新的吗?确保您使用的是最新的服务包。

您是否看过活动Application.AddMessageFilter?我在answer here中使用它来捕获鼠标消息并更智能地处理它们。它可能在这里派上用场。

答案 2 :(得分:0)

这不是MouseLeave的行为方式。即使鼠标光标完全移动了我们的应用程序窗口,您也应该获得MouseLeave事件。

我猜你没有在MouseLeave处理程序中调用基本方法。

无论如何,在MouseEnter上你可以设置一个每0.25秒触发一次的计时器,并在其中检查鼠标是否仍然在控件之上。如果不是,请终止计时器并更改控件的颜色。