c# - 将子控件 MouseMove 事件无缝转发给父控件

标签 c# winforms parent mousemove

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

所有父窗口所做的就是创建控件,给它一个 Rectangle 来绘制它自己,然后如果用户点击非透明区域它会接收事件。

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

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

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

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

最佳答案

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

public partial class UserControl1 : UserControl {
    public UserControl1() {
        InitializeComponent();
        paths = new List<GraphicsPath>();
        GraphicsPath example = new GraphicsPath();
        example.AddEllipse(new Rectangle(10, 10, 50, 30));
        paths.Add(example);
    }
    List<GraphicsPath> 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
        }
    }
}

表单中的测试代码:

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

关于c# - 将子控件 MouseMove 事件无缝转发给父控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7692267/

相关文章:

c# - 是否可以在 C# 中处理单个位?尝试实现 SHA256 生成器

c# 打开一个新窗体然后关闭当前窗体?

C# CheckListBox - 如何添加对象并让该对象显示文本

c# - 将表单的父级设置为 "FindWindow"

c# - SFML 3D 鼠标外观

c# - 不是保存 pdf 文件,而是显示目录列表

c# - 为什么要在 WinForm 对话框上使用 InitializeLifetimeService?

Python super(Class, self).method vs super(Parent, self).method

html - 如何避免带有 "#"的 iframe 中的链接使父 View 转到顶部

c# - Entity Framework : Multiple Where Statements Execution Plan