Scott Chantry
Scott Chantry

Reputation: 1125

Handling a click event anywhere inside a panel in C#

I have a panel in my Form with a click event handler. I also have some other controls inside the panel (label, other panels, etc.). I want the click event to register if you click anywhere inside the panel. The click event works as long as I don't click on any of the controls inside the panel but I want to fire the event no matter where you click inside the panel. Is this possible without adding the same click event to all of the controls inside the panel?

Upvotes: 5

Views: 18365

Answers (5)

Torsten
Torsten

Reputation: 1

a simple solution: every control inside the usercontrol gets the same click-event "ControlClick". The usercontrol event click works with any controls inside.

private void ControlClick(Object sender, EventArgs e)
 {
    if (sender is UC_Vorgang uC_vorgang)
    {
        uC_vorgang.OnClick(e);
    }
    else
    {
        ControlClick(((Control)sender).Parent, e);
    }
}

Upvotes: 0

Sushant VS
Sushant VS

Reputation: 101

Bit late to the party, But What I did was to map all the click event of all the controls inside of the panel to panel click event. I know its nasty approach. but hey!!

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 942358

Technically it is possible, although it is very ugly. You need to catch the message before it is sent to the control that was clicked. Which you can do with IMessageFilter, you can sniff an input message that was removed from the message queue before it is dispatched. Like this:

using System;
using System.Drawing;
using System.Windows.Forms;

class MyPanel : Panel, IMessageFilter {
    public MyPanel() {
        Application.AddMessageFilter(this);
    }
    protected override void Dispose(bool disposing) {
        if (disposing) Application.RemoveMessageFilter(this);
        base.Dispose(disposing);
    }
    public bool PreFilterMessage(ref Message m) {
        if (m.HWnd == this.Handle) {
            if (m.Msg == 0x201) {  // Trap WM_LBUTTONDOWN
                Point pos = new Point(m.LParam.ToInt32());
                // Do something with this, return true if the control shouldn't see it
                //...
                // return true
            }
        }
        return false;
    }
}

Upvotes: 4

Marius
Marius

Reputation: 9674

I needed the exact same functionality today, so this is tested and works:

1: Create a subclasser which can snatch your mouseclick:

internal class MessageSnatcher : NativeWindow
{
    public event EventHandler LeftMouseClickOccured = delegate{};

    private const int WM_LBUTTONDOWN = 0x201;
    private const int WM_PARENTNOTIFY = 0x210;

    private readonly Control _control;

    public MessageSnatcher(Control control)
    {
        if (control.Handle != IntPtr.Zero)
            AssignHandle(control.Handle);
        else
            control.HandleCreated += OnHandleCreated;

        control.HandleDestroyed += OnHandleDestroyed;
        _control = control;
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_PARENTNOTIFY)
        {
            if (m.WParam.ToInt64() == WM_LBUTTONDOWN)
                LeftMouseClickOccured(this, EventArgs.Empty);
        }

        base.WndProc(ref m);
    }

    private void OnHandleCreated(object sender, EventArgs e)
    {
        AssignHandle(_control.Handle);
    }

    private void OnHandleDestroyed(object sender, EventArgs e)
    {
        ReleaseHandle();
    }
}

2: Initialize the snatcher to hook into the panel WndProc:

    private MessageSnatcher _snatcher;

    public Form1()
    {
        InitializeComponent();

        _snatcher = new MessageSnatcher(this.panel1);
    }

3: The Message snatcher will get the WM_PARENTNOTIFY if you click on a child control.

Upvotes: 1

Craig Edmunds
Craig Edmunds

Reputation: 56

You used to be able to override the OnBubbleEvent method on the control. In WPF the mechanism is called Routed events : http://weblogs.asp.net/vblasberg/archive/2010/03/30/wpf-routed-events-bubbling-several-layers-up.aspx

Upvotes: 0

Related Questions