Обработчик событий MouseLeave работает слишком медленно

Я использую событие MouseLeave, чтобы проверить, покинул ли пользователь мою форму и закрыть мое окно, но использование this.MouseLeave += new System.EventHandler(this.InvisibleForm_Leave); слишком медленно, только если я собираюсь медленно покидать свою форму, событие запускается, перемещая его обычным способом / немного быстрее Я не получаю отпуск.

Поэтому я попытался самостоятельно проверить, покинула ли моя форма указатель мыши или нет:

private void checkPos()
    {
        Rectangle rec = this.Bounds;
        while (true)
        {
            Point point = new Point(Cursor.Position.X, Cursor.Position.Y);
            if (!rec.Contains(point))
            {
                Console.WriteLine("leaving");
                this.Close();                    
            }
            Thread.Sleep(100);
        }
    }

запустился в собственном потоке после создания формы:

public MyForm()
    {
        InitializeComponent();
        Thread m_mouseListenerThread = new Thread(new ThreadStart(this.checkPos));
        m_mouseListenerThread.Start();            
    }

Но с этим у меня более или менее та же проблема: выход из области по-прежнему возвращает истину после проверки с помощью rec.Contains(point), только через секунду он собирается выполнить код if, но иногда он получает это мгновенно.

Вторая проблема заключается в том, что я получаю исключение потока в строке this.Close(); в методе checkPost():

Межпоточная операция недействительна: элемент управления MyForm доступен из потока, отличного от потока, в котором он был создан.

Сейчас я толком не знаю, как по-другому реализовать выходящую часть мыши.


person dontcare    schedule 20.04.2012    source источник
comment
Причина, по которой это может быть медленным, заключается в том, что Thread.Sleep(500); не ловит вашу мышь в этот период времени.   -  person Sandeep Bansal    schedule 20.04.2012
comment
у меня было 100 мс, 500 мс было только для проверки   -  person dontcare    schedule 20.04.2012
comment
возможный дубликат постепенного появления и исчезновения формы   -  person Hans Passant    schedule 20.04.2012


Ответы (3)


  1. Что касается выхода мыши, я не совсем уверен. Может быть, вы можете попытаться справиться с этим с помощью события MouseMove?
  2. Из-за проблемы с недопустимой межпотоковой операцией вы просто не можете получить доступ к элементу управления, который принадлежит другому потоку (в вашем случае это поток пользовательского интерфейса). Используйте Control.BeginInvoke или Control.Invoke вместо этого.
person Hailei    schedule 20.04.2012
comment
1. Я думаю, что у меня проблема, я меняю размер из формы, и при проверке записи он сохранил старые границы, а не новые границы после изменения 2. попробует - person dontcare; 20.04.2012

Я не думаю, что здесь проблема с производительностью MouseLeave. Я использовал MouseLeave (в сочетании с MouseEnter и MouseMove) для автоматического появления / исчезновения форм. Оно работает :). Вот образец формы только с меткой:

Если MouseLeave обрабатывается как для метки, так и для формы, обработчик событий всегда срабатывает независимо от того, насколько быстро я перемещаю мышь. Например:

this.label1.MouseLeave += new System.EventHandler(this.HandleMouseLeave);
this.MouseLeave += new System.EventHandler(this.HandleMouseLeave);

private void HandleMouseLeave(object sender, EventArgs e)
{
   Debug.WriteLine(string.Format("MouseLeave: {0}", DateTime.Now));
}

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

Итак, я думаю, что происходит то, что дочерний элемент управления вашей формы запускает событие MouseLeave, а вы не обрабатываете это событие. Причина, по которой вы видите срабатывание события при медленном перемещении мыши, заключается в том, что вы наведены на область формы достаточно долго, чтобы вызвать событие.

Кроме того, создание отдельного потока для отслеживания событий MouseLeave - не лучший подход. Ваша производительность будет страдать, поскольку этот поток опрашивает состояние события (в отличие от ожидания события), вы создаете ненужную головную боль запуска / остановки потоков, и вам нужно будет снова вызывать поток пользовательского интерфейса всякий раз, когда вы хотите делать что-нибудь с формой (как вы уже узнали). Если у вас есть время вернуться к подходу к событию MouseLeave, я настоятельно рекомендую вам это сделать. Удачи!

person Steve Wong    schedule 20.04.2012
comment
пробовал, пока у меня есть граница, она работает нормально, но при использовании this.FormBorderStyle = FormBorderStyle.None; для моей формы такие же проблемы - person dontcare; 23.04.2012
comment
Можете выложить небольшой образец с проблемой? Обычно я делаю это для исчезающих всплывающих окон без полей, и это отлично работает. Я не думаю, что стиль границы формы должен каким-либо образом влиять на события MouseLeave. - person Steve Wong; 23.04.2012

Я столкнулся с той же проблемой, сделайте это:

  1. поставить таймер в форму.
  2. Поместите свой код в событие таймера, например, отпуск мыши:

    Label1.BackColor=Color.PaleGreen;
    
  3. Установите интервал таймера менее 30

  4. Используйте эту функцию

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        timer1_Tick(label1(example), e); 
    }
    
  5. Поместите это в событие загрузки формы

    timer1.Tick += timer1_Tick;
    

код будет работать очень быстро и легко, вы больше никогда не увидите такой проблемы

person ياسر عامر الخفاجي    schedule 30.01.2017
comment
Обычно использовать таймеры для подобных задач - плохая идея. У вас уже есть событие, которое вы можете обработать, поэтому его следует придерживаться. - person Lukas Körfer; 30.01.2017