如何捕获子控件下的mousemove事件

时间:2009-11-12 03:09:03

标签: c# winforms events handle mousemove

我正在尝试处理特定表单上的mouseclick事件,如果鼠标光标位于一组坐标之间,则应触发该事件 - 比如说一个正方形。

我明白,如果我有一个空的表格,我可以简单地绑定到mousemove事件,然后离开。但实际上可能有多达10个不同的重叠控件,在我的测试应用程序中,mousemove事件仅在光标位于实际表单本身时触发,而不是在其通过子控件时触发。

当设计时存在未知数量的子控件时,是否有人知道如何处理此事件?

我可以使用简单的单行程吗?

5 个答案:

答案 0 :(得分:7)

试试这个:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        AddMouseMoveHandler(this);
    }

    private void AddMouseMoveHandler(Control c)
    {
        c.MouseMove += MouseMoveHandler;
        if(c.Controls.Count>0)
        {
            foreach (Control ct in c.Controls)
                AddMouseMoveHandler(ct);
        }
    }

    private void MouseMoveHandler(object sender, MouseEventArgs e)
    {
        lblXY.Text = string.Format("X: {0}, Y:{1}", e.X, e.Y);
    }
}

答案 1 :(得分:7)

我知道这篇文章很老了,但在我看来,最简单的方法是实现IMessageFilter的形式。在构造函数中(或在OnHandleCreated中),您可以调用

Application.AddMessageFilter(this);

然后您可以在IMessageFilter.PreFilterMessage的实现中捕获所有窗口的消息。

您可能需要为WIN32 IsChild方法使用P / Invoke

[DllImport("user32.dll")]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);

以及表单的Handle属性,以确保您处理正确的邮件。

答案 2 :(得分:0)

为什么不直接使用控件的鼠标悬停事件处理程序?

答案 3 :(得分:0)

imho这里有一些二元情况:并没有“一线”。我能看到的唯一解决方案是将没有实现事件的控件放入.NET容器中。

当任何控件获得单击时,正常的预期行为是它将成为表单的活动控件(可以始终通过this.ActivceControl访问)。

但是,特别是如果您单击的控件捕获鼠标,则必须引发事件,因为.NET未实现事件“冒泡”(如WPF所做的那样)。

处理任何密封对象的扩展行为的常用方法是编写扩展方法,我发现为Control编写扩展非常容易,但我不知道这是否会对你有所帮助案件。不幸的是,我现在不在我的国家,也没有Visual Studio可以玩。

您可以使用一种策略来确定表单上的给定Point是否属于任何Control的范围,是通过Forms Control.Collection(此处)的forall枚举表单上所有控件的区域(Bounds)。控制)。但是,如果您有重叠的控件,那么您可能会遇到多个可能包含给定点的控件的问题。

最好,比尔

答案 4 :(得分:0)

我知道我有点迟到了,但今天早些时候我使用Panel作为标题栏时遇到了麻烦。我有一个标签显示一些文本,一个图片框和一些嵌套在Panel中的按钮,但我需要捕获MouseMove事件。

我决定要做的是实现一个递归方法处理程序来执行此操作,因为我只有1级嵌套控件,当你开始接近荒谬的嵌套级别时,这可能无法很好地扩展。

我是这样做的:

    protected virtual void NestedControl_Mousemove(object sender, MouseEventArgs e)
    {
        Control current = sender as Control;
        //you will need to edit this to identify the true parent of your top-level control. As I was writing a custom UserControl, "this" was my title-bar's parent.
        if (current.Parent != this) 
        {
            // Reconstruct the args to get a correct X/Y value.
            // you can ignore this if you never need to get e.X/e.Y accurately.
            MouseEventArgs newArgs = new MouseEventArgs
            (
                e.Button, 
                e.Clicks, 
                e.X + current.Location.X, 
                e.Y + current.Location.Y, 
                e.Delta
            );
            NestedControl_Mousemove(current.Parent, newArgs);
        }
        else
        {
            // My "true" MouseMove handler, called at last.
            TitlebarMouseMove(current, e);
        }
    }

    //helper method to basically just ensure all the child controls subscribe to the NestedControl_MouseMove event.
    protected virtual void AddNestedMouseHandler(Control root, MouseEventHandler nestedHandler)
    {
        root.MouseMove += new MouseEventHandler(nestedHandler);
        if (root.Controls.Count > 0)
            foreach (Control c in root.Controls)
                AddNestedMouseHandler(c, nestedHandler);
    }

然后设置起来相对简单:

定义“真正的”处理程序:

    protected virtual void TitlebarMouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            this.Text = string.Format("({0}, {1})", e.X, e.Y);
        }
    }

然后设置控件事件订阅者:

//pnlDisplay is my title bar panel.
AddNestedMouseHandler(pnlDisplay, NestedControl_Mousemove);

使用相对简单,我可以保证它的工作原理:)