父控制鼠标输入/离开事件与子控件 [英] Parent Control Mouse Enter/Leave Events With Child Controls

查看:138
本文介绍了父控制鼠标输入/离开事件与子控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 
+ ---------- ----------------------- +
| [标签控制] |
+ --------------------------------- +

当鼠标进入或离开父控件时,我正在尝试做一些事情,但是我不在乎鼠标是否移动到其中一个孩子。我想要一个单一的标志来表示鼠标在父母或孩子的某处,鼠标移到父控件界限之外。



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

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

中间的OnMouseLeave事件会引起一些不希望的影响,因为我正在做的事情开始然后停止。我想避免这种情况。



我不想捕捉鼠标,因为父母将鼠标移开,因为子控件需要鼠标事件,我想菜单和其他快捷键可以正常工作。



有没有办法在.NET框架内执行此操作?或者我需要使用Windows鼠标钩子吗?

解决方案

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

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

public void Dispose()
{
StopFiltering();
}

#region IMessageFilter成员

public bool PreFilterMessage(ref Message m)
{
//调用相应的事件
返回false;
}

#endregion

#region活动

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;
}
}


I have a C# .NET 2.0 WinForms app. My app has a control that is a container for two child controls: a label, and some kind of edit control. You can think of it like this, where the outer box is the parent control:

+---------------------------------+ 
| [Label Control]  [Edit Control] |
+---------------------------------+

I am trying to do something when the mouse enters or leaves the parent control, but I don't care if the mouse moves into one of its children. I want a single flag to represent "the mouse is somewhere inside the parent or children" and "the mouse has moved outside of the parent control bounds".

I've tried handling MouseEnter and MouseLeave on the parent and both child controls, but this means the action begins and ends multiple times as the mouse moves across the control. In other words, I get this:

Parent.OnMouseEnter      (start doing something)
Parent.OnMouseLeave      (stop)
Child.OnMouseEnter       (start doing something)
Child.OnMouseLeave       (stop)
Parent.OnMouseEnter      (start doing something)
Parent.OnMouseLeave      (stop)

The intermediate OnMouseLeave events cause some undesired effects as whatever I'm doing gets started and then stopped. I want to avoid that.

I don't want to capture the mouse as the parent gets the mouse over, because the child controls need their mouse events, and I want menu and other shortcut keys to work.

Is there a way to do this inside the .NET framework? Or do I need to use a Windows mouse hook?

解决方案

After more research, I discovered the Application.AddMessageFilter method. Using this, I created a .NET version of a mouse hook:

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);
    }
}

Then, I can handle the MouseMove event in my container control, check to see if the mouse is inside my parent control, and start the work. (I also had to track the last moused over parent control so I could stop the previously started parent.)

---- Edit ----

In my form class, I create and hookup the filter:

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;
    }   
}

这篇关于父控制鼠标输入/离开事件与子控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆