将子控制MouseMove事件无缝转发给父级

我有一个使用GDI +绘制的自定义UserControl。 它是一个透明控件,在父控件的顶部绘制小形状。

所有父窗口都创建控件,为其绘制一个Rectangle以在其中绘制自身,然后在用户单击非透明区域时接收事件。

绘图部分工作正常,但现在我需要做的是尽可能无缝地将所有MouseMove,MouseClick等事件转发到父控件,如果这些事件发生在形状之外。

使用GraphicsPath绘制形状,我已经能够使用GraphicsPath.IsVisible()检测鼠标位置是否在形状上。

我希望以一种在父级上需要零或最少额外代码的方式执行此操作。 父母不一定知道MouseMove事件是否是从子控件转发的,它应该平等对待它们。

我必须使用pinvoke / SendMessage()来执行此操作吗? 或者使用.NET框架有更简单的方法吗?

这在winapi中是可能的,窗口管理器发送WM_NCHITTEST消息以询问鼠标位于控件的哪个部分。 你可以做的是返回HTTRANSPARENT,它将询问父窗口。 这是一个实现此function的UserControl示例。 捕获消息需要覆盖WndProc():

public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); paths = new List(); GraphicsPath example = new GraphicsPath(); example.AddEllipse(new Rectangle(10, 10, 50, 30)); paths.Add(example); } List paths; protected override void OnPaint(PaintEventArgs e) { foreach (var path in paths) e.Graphics.FillPath(Brushes.Blue, path); base.OnPaint(e); } protected override void WndProc(ref Message m) { base.WndProc(ref m); // Trap WM_NCHITTEST on the client area if (m.Msg == 0x84 && m.Result == (IntPtr)1) { Point pos = new Point(m.LParam.ToInt32()); pos = this.PointToClient(pos); bool oncurve = false; foreach (var path in paths) if (path.IsVisible(pos)) oncurve = true; if (!oncurve) m.Result = (IntPtr)(-1); // HTTRANSPARENT } } } 

测试代码的forms如下:

  private void userControl11_MouseMove(object sender, MouseEventArgs e) { Console.WriteLine("On shape {0}", e.Location); } private void Form1_MouseMove(object sender, MouseEventArgs e) { Console.WriteLine("On form {0}", e.Location); }