Capturing mouse events from every component

I have a problem with MouseEvents on my WinForm C# application.

I want to get all mouse clicks on my application, but I don't want to put a listener in every child component neither use Windows mouse hook.

On Flash I could put a listener on Stage to get all the MouseEvents on the movie.

Is there such thing on C#? A global MouseListener?


Edit:

I create this class from IMessageFilter ans used Application.AddMessageFilter.

public class GlobalMouseHandler : IMessageFilter{

    private const int WM_LBUTTONDOWN = 0x201;

    public bool PreFilterMessage(ref Message m){
        if (m.Msg == WM_LBUTTONDOWN) {
            // Do stuffs
        }
        return false;
    }
}

And put this code on the Controls that need listen global clicks:

GlobalMouseHandler globalClick = new GlobalMouseHandler();
Application.AddMessageFilter(globalClick);

Solution 1:

One straightforward way to do this is to add a message loop filter by calling Application.AddMessageFilter and writing a class that implements the IMessageFilter interface.

Via IMessageFilter.PreFilterMessage, your class gets to see any inputs messages that pass through your application's message loop. PreFilterMessage also gets to decide whether to pass these messages on to the specific control to which they're destined.

One piece of complexity that this approach introduces is having to deal with Windows messages, via the Message struct passed to your PreFilterMessage method. This means referring to the Win32 documention on WM\_LBUTTONDOWN, WM\_MOUSEMOVE, WM\_LBUTTONUP etc, instead of the conventional MouseDown, MouseMove and MouseUp events.

Solution 2:

Sample Class

class CaptureEvents : IMessageFilter
{
    #region IMessageFilter Members
    public delegate void Callback(int message);
    public event Callback MessageReceived;

    IntPtr ownerWindow;
    Hashtable interestedMessages = null;
    CaptureEvents(IntPtr handle, int[] messages)
    {
        ownerWindow = handle;
        for(int c = 0; c < messages.Length ; c++)
        {
            interestedMessages[messages[c]] = 0;
        }
    }
    public bool PreFilterMessage(ref Message m)
    {
        if (m.HWnd == ownerWindow && interestedMessages.ContainsKey(m.Msg))
        {
            MessageReceived(m.Msg);
        }
        return true;
    }

    #endregion
}