【问题标题】:Forwarding child control MouseMove events to the parent seamlessly将子控件 MouseMove 事件无缝转发给父控件
【发布时间】:2011-10-07 19:56:09
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: c# winforms parent mousemove


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2021-06-13
      • 2016-01-20
      • 1970-01-01
      • 2010-12-15
      • 2010-10-07
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多