一尘不染

父控件鼠标输入/离开带有子控件的事件

c#

我有一个C#.NET 2.0
WinForms应用程序。我的应用程序有一个控件,该控件是两个子控件的容器:一个标签和某种编辑控件。您可以这样想,外部框是父控件:

+ --------------------------------- + 
| [标签控件] [编辑控件] |
+ --------------------------------- +

当鼠标进入或离开父控件时,我正在尝试执行某些操作,但是我不在乎鼠标是否移入其子控件中的一个。我想要一个标志来表示“鼠标位于父级或子级内部的某个位置”和“鼠标已移出父级控件范围之外”。

我已经尝试在父控件和两个子控件上处理MouseEnter和MouseLeave,但这意味着当鼠标在控件上移动时,该操作开始和结束多次。换句话说,我得到这个:

Parent.OnMouseEnter(开始做某事)
Parent.OnMouseLeave(停止)
Child.OnMouseEnter(开始做某事)
Child.OnMouseLeave(停止)
Parent.OnMouseEnter(开始做某事)
Parent.OnMouseLeave(停止)

中间的OnMouseLeave事件会导致一些不良后果,因为我正在做的事情开始然后停止。我想避免这种情况。

我不想在父控件移开鼠标时捕获鼠标,因为子控件需要其鼠标事件,并且我希望菜单和其他快捷键能够正常工作。

是否可以在.NET框架内执行此操作?还是我需要使用Windows鼠标钩?


阅读 197

收藏
2020-05-19

共1个答案

一尘不染

经过更多研究,我发现了Application.AddMessageFilter方法。使用此工具,我创建了.NET版本的鼠标钩:

class MouseMessageFilter : IMessageFilter, IDisposable
{
    public MouseMessageFilter()
    {
    }

    public void Dispose()
    {
        StopFiltering();
    }

    #region IMessageFilter Members

    public bool PreFilterMessage(ref Message m)
    {
         // Call the appropriate event
         return false;
    }

    #endregion

    #region Events

    public class CancelMouseEventArgs : MouseEventArgs
    {...}

    public delegate void CancelMouseEventHandler(object source, CancelMouseEventArgs e);
    public event CancelMouseEventHandler MouseMove;
    public event CancelMouseEventHandler MouseDown;
    public event CancelMouseEventHandler MouseUp;

    public void StartFiltering()
    {
        StopFiltering();
        Application.AddMessageFilter(this);
    }

    public void StopFiltering()
    {
        Application.RemoveMessageFilter(this);
    }
}

然后,我可以在容器控件中处理MouseMove事件,检查鼠标是否在父控件中,然后开始工作。(我还必须跟踪上一次鼠标移到父控件上,以便可以停止先前启动的父控件。)

-—编辑----

在表单类中,我创建并连接了过滤器:

public class MyForm : Form
{
   MouseMessageFilter msgFilter;

   public MyForm()
   {...
       msgFilter = new MouseMessageFilter();
       msgFilter.MouseDown += new MouseMessageFilter.CancelMouseEventHandler(msgFilter_MouseDown);
       msgFilter.MouseMove += new MouseMessageFilter.CancelMouseEventHandler(msgFilter_MouseMove);
    }

    private void msgFilter_MouseMove(object source, MouseMessageFilter.CancelMouseEventArgs e)
    {
        if (CheckSomething(e.Control)
            e.Cancel = true;
    }   
}
2020-05-19