我有一个C#.NET 2.0 WinForms应用程序。我的应用程序有一个控件,该控件是两个子控件的容器:一个标签和某种编辑控件。您可以这样想,外部框是父控件:
+ --------------------------------- + | [标签控件] [编辑控件] | + --------------------------------- +
当鼠标进入或离开父控件时,我正在尝试执行某些操作,但是我不在乎鼠标是否移入其子控件中的一个。我想要一个标志来表示“鼠标位于父级或子级内部的某个位置”和“鼠标已移出父级控件范围之外”。
我已经尝试在父控件和两个子控件上处理MouseEnter和MouseLeave,但这意味着当鼠标在控件上移动时,该操作开始和结束多次。换句话说,我得到这个:
Parent.OnMouseEnter(开始做某事) Parent.OnMouseLeave(停止) Child.OnMouseEnter(开始做某事) Child.OnMouseLeave(停止) Parent.OnMouseEnter(开始做某事) Parent.OnMouseLeave(停止)
中间的OnMouseLeave事件会导致一些不良后果,因为我正在做的事情开始然后停止。我想避免这种情况。
我不想在父控件移开鼠标时捕获鼠标,因为子控件需要其鼠标事件,并且我希望菜单和其他快捷键能够正常工作。
是否可以在.NET框架内执行此操作?还是我需要使用Windows鼠标钩?
经过更多研究,我发现了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; } }