Handling a Click for all controls on a Form
Asked Answered
C

2

10

I have a .NET UserControl (FFX 3.5). This control contains several child Controls - a Panel, a couple Labels, a couple TextBoxes, and yet another custom Control. I want to handle a right click anywhere on the base Control - so a right click on any child control (or child of a child in the case of the Panel). I'd like to do it so that it's maintainable if someone makes changes to the Control without having to wire in handlers for new Controls for example.

First I tried overriding the WndProc, but as I suspected, I only get messages for clicks on the Form directly, not any of its children. As a semi-hack, I added the following after InitializeComponent:

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

This now gets clicks for controls that support the event, but Labels, for example, still don't get anything. Is there a simple way to do this that I'm overlooking?

Chladek answered 29/10, 2008 at 18:45 Comment(0)
K
23

If the labels are in a subcontrol then you'd have to do this recursively:

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

/* ... */
initControlsRecursive(Form.Controls);
Kickapoo answered 29/10, 2008 at 19:5 Comment(1)
So damned obvious that I couldn't see the forest for the trees. Thanks.Chladek
S
1

To handle a MouseClick event for right click on all the controls on a custom UserControl:

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.");
    }
}
Shirr answered 14/7, 2016 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.