MouseLeave事件处理程序太慢了

时间:2012-04-20 11:40:28

标签: c# .net events 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();            
    }

但是有了这个,我或多或少有同样的问题,只有在他要执行if代码的一秒钟之后用rec.Contains(point)检查它之后,该区域仍然返回true,但有时他会在瞬间。

第二个问题是我在this.Close();方法的checkPost()行中遇到了线程异常:

  

跨线程操作无效:控制从其创建的线程以外的线程访问的“MyForm”。

现在我真的不知道如何以另一种方式实现鼠标离开部分。

3 个答案:

答案 0 :(得分:3)

我不认为MouseLeave性能是这里的问题。我已经使用MouseLeave(与MouseEnter和MouseMove结合使用)自动淡入/淡出表单。有用 :)。 这是一个只有标签的示例表单:

如果同时处理Label和Form的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));
}

但是,如果我删除label1的MouseLeave处理程序,我可以重现您看到的行为。如果我将标签从标签1(橙色)缓慢移动到表格(绿色)和外部,则事件将触发。如果我将鼠标从label1快速移动到窗体外部,则事件不会触发。

所以,我认为正在发生的事情是,您的表单的子控件正在触发MouseLeave事件,而您没有处理该事件。当您慢慢移动鼠标时看到事件触发的原因是因为您将鼠标悬停在表单区域上足以产生事件。

此外,产生一个单独的线程来监视MouseLeave事件并不是一个好方法。当这个线程轮询一个事件状态(而不是等待一个事件)时,你的性能会受到影响,你正在创建一个不必要的启动/停止线程的头痛,你需要随时调用UI线程对表格做任何事情(如你所知)。如果您有时间重新访问MouseLeave事件方法,我强烈建议您这样做。祝你好运!

答案 1 :(得分:2)

  1. 对于鼠标离开部分,我不太确定。也许你可以尝试通过MouseMove事件处理它?<​​/ li>
  2. 对于无效的跨线程操作问题,您根本无法访问另一个线程所拥有的控件(它是您的案例中的UI线程)。请改用Control.BeginInvokeControl.Invoke

答案 2 :(得分:0)

我遇到同样的问题,那样做:

  1. 将计时器放入表格。
  2. 将您的代码放入计时器刻度事件,例如鼠标离开:

    Label1.BackColor=Color.PaleGreen;
    
  3. 将计时器间隔设置为小于30

  4. 使用此功能

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        timer1_Tick(label1(example), e); 
    }
    
  5. 将此信息放入formload事件

    timer1.Tick += timer1_Tick;
    
  6. 代码将非常快速和简单地运行,你再也不会看到这样的问题了