将子控件MouseMove事件无缝转发到父控件 [英] Forwarding child control MouseMove events to the parent seamlessly

查看:99
本文介绍了将子控件MouseMove事件无缝转发到父控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a custom UserControl that I am drawing using the GDI+. It is a transparent control which draws small shapes on top of the parent control.

父窗口所做的全部工作就是创建控件,为其提供一个可在其中绘制自身的矩形,然后,如果用户单击非透明区域,它将接收事件.

All the parent window does is creates the control, gives it a Rectangle in which to draw itself, and then it receives events if the user clicks on the non-transparent areas.

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

The drawing part works perfectly, but right now what I need to do is to as seamlessly as possible forward all MouseMove, MouseClick, etc. events to the parent control IF those events occurred outside the shapes.

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

The shapes are drawn using GraphicsPath, and I am already able to detect if the mouse position is over a shape using GraphicsPath.IsVisible().

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

I want to do this in a way that requires zero or minimal extra code on the parent. The parent should not necessarily know whether the MouseMove event was forwarded from the child control or not, it should treat them all equally.

我是否必须pinvoke/SendMessage()才能做到这一点?还是有使用.NET框架的更简单方法?

Do I have to pinvoke/SendMessage() to do this? Or is there an easier way using the .NET framework?

推荐答案

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

This is possible in the winapi, the WM_NCHITTEST message is sent by the window manager to ask what part of the control the mouse is on top of. What you can do is return HTTRANSPARENT and it will ask the parent window. Here's a sample UserControl that implements this. Catching the message requires overriding 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);
    }

这篇关于将子控件MouseMove事件无缝转发到父控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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