2

我正在使用 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();            
    }

但是有了这个我或多或少有同样的问题,离开该区域后检查它仍然返回true,rec.Contains(point)仅在一秒钟后他将执行if代码,但有时他会立即得到它。

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

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

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

4

3 回答 3

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 处理程序,我就能够重现您所看到的行为。如果我将鼠标从 label1(橙色)缓慢移动到表单(绿色)和外部,事件就会触发。如果我将鼠标从 label1 快速移动到表单外部,则不会触发该事件。

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

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

于 2012-04-20T12:42:13.117 回答
2
  1. 对于鼠标离开部分,我不太确定。也许您可以尝试通过 MouseMove 事件来处理?
  2. 对于无效的跨线程操作问题,您根本无法访问由另一个线程拥有的控件(在您的情况下是 UI 线程)。请改用Control.BeginInvokeControl.Invoke
于 2012-04-20T11:45:34.280 回答
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. 把它放在表单加载事件中

    timer1.Tick += timer1_Tick;
    

代码将运行得非常快和容易,你再也不会看到这样的问题了

于 2017-01-30T09:38:38.037 回答