C# 将鼠标事件传递给父控件

C# 将鼠标事件传递给父控件,c#,winforms,mouseevent,C#,Winforms,Mouseevent,环境:.NET Framework 2.0,与2008年相比 我正在尝试创建某些.NET控件(标签、面板)的子类,这些控件将通过某些鼠标事件(MouseDown、MouseMove、MouseUp)传递到其父控件(或者顶级窗体)。我可以通过在标准控件的实例中为这些事件创建处理程序来实现这一点,例如: public class TheForm : Form { private Label theLabel; private void InitializeComponent()

环境:.NET Framework 2.0,与2008年相比

我正在尝试创建某些.NET控件(标签、面板)的子类,这些控件将通过某些鼠标事件(
MouseDown
MouseMove
MouseUp
)传递到其父控件(或者顶级窗体)。我可以通过在标准控件的实例中为这些事件创建处理程序来实现这一点,例如:

public class TheForm : Form
{
    private Label theLabel;

    private void InitializeComponent()
    {
        theLabel = new Label();
        theLabel.MouseDown += new MouseEventHandler(theLabel_MouseDown);
    }

    private void theLabel_MouseDown(object sender, MouseEventArgs e)
    {
        int xTrans = e.X + this.Location.X;
        int yTrans = e.Y + this.Location.Y;
        MouseEventArgs eTrans = new MouseEventArgs(e.Button, e.Clicks, xTrans, yTrans, e.Delta);
        this.OnMouseDown(eTrans);
    }
}
我无法将事件处理程序移动到控件的子类中,因为在父控件中引发事件的方法受到保护,并且我没有父控件的限定符:

无法通过类型为System.Windows.Forms.Control的限定符访问受保护的成员System.Windows.Forms.Control.OnMouseDown(System.Windows.Forms.MouseEventArgs);限定符的类型必须为Project.NoCaptureLabel(或从中派生)


我正在研究重写我的子类中控件的
WndProc
方法,但希望有人能给我一个更干净的解决方案。

您需要在基类中编写一个公共/受保护的方法,它将为您引发事件。然后从派生类调用此方法

这是你想要的吗

public class MyLabel : Label
{
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        //Do derived class stuff here
    }
}

WS_EX_TRANSPARENT
扩展窗口样式实际上就是这样做的(它是就地工具提示使用的)。您可能想考虑使用这种样式,而不是编写大量的处理程序来为您做。 为此,请重写
CreateParams
方法:

protected override CreateParams CreateParams
{
  get
  {
    CreateParams cp=base.CreateParams;
    cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
    return cp;
  }
}
进一步阅读:


  • 是的。经过大量搜索,我找到了这篇文章,它使用
    WndProc
    将消息从
    WM\u nchitest
    更改为
    HTTRANSPARENT
    ,使
    控件对鼠标事件透明

    要实现这一点,请创建一个继承自
    Label
    的控件,并简单地添加以下代码

    protected override void WndProc(ref Message m)
    {
        const int WM_NCHITTEST = 0x0084;
        const int HTTRANSPARENT = (-1);
    
        if (m.Msg == WM_NCHITTEST)
        {
            m.Result = (IntPtr)HTTRANSPARENT;
        }
        else
        {
            base.WndProc(ref m);
        }
    }
    

    我已经在Visual Studio 2010中使用.NET Framework 4客户端配置文件对此进行了测试。

    我不这么认为。OnMouseDown引发事件,但不处理它。我需要一个将事件传递给其父级的事件处理程序。我不能做你的第一个建议b/c基类是一个标准的Windows控件,不是我写的类。@SandepDatta,父控件和基类是不同的,对吧?谢谢你的建议。我试过了,但对我来说不起作用。也许它只适用于顶级窗口?这是该代码的正确错误消息吗?一个是MouseUp,另一个是MouseDown。我也不太清楚“通过”是什么意思。错误消息不正确,应该是MouseDown。我所说的“传递”是指,当在控件上引发某些事件时,我会在控件的父控件上以编程方式引发它们。感谢akatran--我已经前进了一步,我甚至不记得我自己是如何解决这个问题的,但看起来你已经解决了。非常感谢,这也帮助了我-清晰、简洁,解决了这个问题!值得注意的是,这将使false transparent控件脱离事件循环-它们没有机会自己处理MouseMove事件,因为它直接钻取到父级的处理程序。为了在将事件传递给父控件之前保持每个控件本身处理事件的能力,您可以执行以下操作:顺便说一句,将条件更改为
    (m.Msg==WM|NCHITTEST | m.Msg==WM|MOUSEHOVER)
    允许鼠标移动行为传递给下面的控件。也许这对其他人也有帮助。