События MouseEnter и MouseLeave от Panel и ее дочерних элементов управления - PullRequest
13 голосов
/ 05 апреля 2010

У меня есть Panel, который содержит дочерние элементы управления.

Если я обработаю Panel и MouseEnter и MouseLeave события, а также его дочерние MouseEnter и MouseLeave события, события возникают в следующем порядке:

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

Но мне нужен следующий порядок:

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

Это возможно?

Ответы [ 9 ]

21 голосов
/ 07 сентября 2010

Если вы не возражаете против создания пользовательского элемента управления (полученного из панели или другого родительского контейнера, который вы хотите), Переопределите метод OnMouseLeave вашего родителя, чтобы он выглядел следующим образом ..

protected override void OnMouseLeave(EventArgs e)
{

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

Тогда повышение события будет в требуемом порядке.

5 голосов
/ 05 апреля 2010

Мышь «покидает» панель при входе в дочерний элемент управления, поэтому она запускает событие.

Вы могли бы добавить что-то в следующие строки на панели 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 голосов
/ 14 октября 2013

Ответ Мэтью не будет работать всегда. Особенно, если дочерний элемент управления установлен на краю его контейнера, и мышь перемещает элементы управления в этом направлении. Вы никогда не обнаружите событие MouseLeave.

Наилучшим подходом является создание контейнера пользовательского элемента управления, а затем перехватывание всех событий MouseEnter и MouseLeave дочерних элементов управления, чтобы вы могли правильно определять, где и когда находится мышь. ТОГДА, если он входит в границы вашего контейнера, вы можете запустить собственное событие MouseEnter и когда оно покинет событие MouseLeave.

2 голосов
/ 31 марта 2011

Решение состоит в том, чтобы отслеживать количество поступлений / листьев. В ваш общий контроль добавьте счетчик:

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 для ВСЕХ дочерних элементов управления, а также содержащего объект.

1 голос
/ 26 июля 2010

Возможно, это не самое элегантное решение, но вы можете установить свойство на родительской панели управления (панель подкласса), которое будет иметь значение типа bool, например "bool selected" Затем, когда MouseEnter для панели запускается, установите его в значение true ... затем остановите срабатывание логики отпускания мыши, если не установлено значение false.

пример

bool selected;

MouseEnter(..,..)
{
 if (!selected)
   selected = true;
 else
   selected = false;

  if (selected)
   /.. Logic Here ../
}

MouseLeave()
{
  if (selected)
   return;

/.. Logic Here ../
}

На самом деле я бы просто установил параметр MouseLeave дочернего элемента.

Example:

Parent:
  bool doLeave;

  MouseLeave(..,..)
  {
    if (doLeave)
    {
     /.. Logic ../
     doLeave = false;
  }

Child:
 MouseLeave(..., ...)
  {
    DerivedPanel parent = this.Parent as DerivedPanel;
    if (parent != null)
      parent.doLeave = true;
  }

Ни один из них не элегантен, но он будет работать.

0 голосов
/ 17 февраля 2016

Джимми Т. прав. Будут проблемы, если нет (или небольшого) пробела между ребром родительского контроля (панели) и дочерним контролем.

Вот как я решаю эту проблему в классе, производном от 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
    }
0 голосов
/ 15 ноября 2015

Проверьте дочерний компонент ..

if (panel1.GetChildAtPoint(panel1.PointToClient(Cursor.Position)) == null)
{
    // mouse leave panel and children
}
0 голосов
/ 27 июля 2010

Это сложная задача, и ее трудно будет надежно кодировать. Одна из идей состоит в том, чтобы «захватить» 3 входящих события в списке и выполнить нужный код после того, как список будет завершен (в списке 3 требуемых события). Затем, когда вы закончите выполнение любого кода (или, возможно, перехватите комбо событий в обратном порядке), вы можете очистить свой список и подготовить его к следующему конкретному комбо-событию. Не идеал, а просто мысль.

Конечно, это не преодолевает потенциальные проблемы с разрешением и возможные пропущенные события, поднятые Гансом. Возможно, больше контекста в порядке.

0 голосов
/ 05 апреля 2010

Я верю в это.Хороший инструмент для проверки событий вашего приложения WinForms.

Порядок событий Windows.Forms

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

  • Создано с помощью EventSpy, написанного Урсом Эйхманом( ftp: //missico.net/EventSpy.zip)
  • Использование .NET Framework 3.5 и с включенной прикладной средой Visual Basic.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...