处理表单中所有控件的点击事件

10

我有一个 .NET UserControl (FFX 3.5)。 这个控件包含几个子控件 - 一个面板,几个标签,几个文本框和另一个自定义控件。 我想处理在基础控件上的鼠标右键单击事件 - 所以单击任何子控件(或 Panel 的子控件)上的右键都会触发该事件。我希望这样做是可维护的,如果有人更改了控件而不必为新控件连线处理程序。

首先,我尝试重写 WndProc,但正如我所怀疑的那样,我只能获取直接在窗体上点击的消息,而不能获取任何子控件的消息。作为一种半黑客方式,我在 InitializeComponent 后添加了以下内容:

  foreach (Control c in this.Controls)
  {
    c.MouseClick += new MouseEventHandler(
      delegate(object sender, MouseEventArgs e)
      {
        // handle the click here
      });
  }

现在,支持此事件的控件将被点击,但是例如标签(Label)仍然不会有任何反应。 是否有我忽略的简单方法可以解决这个问题?

2个回答

23

如果标签在子控件中,则必须进行递归处理:

void initControlsRecursive(ControlCollection coll)
 { 
    foreach (Control c in coll)  
     {  
       c.MouseClick += (sender, e) => {/* handle the click here  */});  
       initControlsRecursive(c.Controls);
     }
 }

/* ... */
initControlsRecursive(Form.Controls);

1
太明显了,以至于我看不到树林。谢谢。 - ctacke

1
处理自定义上所有控件的右键事件:

public class MyClass : UserControl
{
    public MyClass()
    {
        InitializeComponent();

        MouseClick += ControlOnMouseClick;
        if (HasChildren)
            AddOnMouseClickHandlerRecursive(Controls);
    }

    private void AddOnMouseClickHandlerRecursive(IEnumerable controls)
    {
        foreach (Control control in controls)
        {
            control.MouseClick += ControlOnMouseClick;

            if (control.HasChildren)
                AddOnMouseClickHandlerRecursive(control.Controls);
        }
    }

    private void ControlOnMouseClick(object sender, MouseEventArgs args)
    {
        if (args.Button != MouseButtons.Right)
            return;

        var contextMenu = new ContextMenu(new[] { new MenuItem("Copy", OnCopyClick) });
        contextMenu.Show((Control)sender, new Point(args.X, args.Y));
    }

    private void OnCopyClick(object sender, EventArgs eventArgs)
    {
        MessageBox.Show("Copy menu item was clicked.");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接