9

There is certainly a convenient way to do this :

I have implemented a "Move Window" on mouse drag behavior on my main form,
and I would like the MouseClick/Move event to be intercepted by the form, not by controls that are in it.

I would like to find an Equivalent to/replicate the "KeyPreview" property for Mouse Events

Besides I want to avoid Redirecting the Mouse Event to the Main Form Method 12 times in 12 Controls' Mouse events individually (which is the ugly workaround I have Found so far)

Any Ideas ?

Mehdi LAMRANI
  • 11,289
  • 14
  • 88
  • 130
  • Do the child controls also handle the mouse click/move events? – tzup Feb 14 '11 at 10:35
  • Some of them, not all. And I certainly want to avoid Redirecting the Mouse Event to the Main Form Method 12 times in 12 Controls – Mehdi LAMRANI Feb 14 '11 at 10:38
  • 1
    You can use a [message filter](http://stackoverflow.com/questions/4279732/). (Trivial answer converted to comment automatically.) – ulatekh Sep 05 '14 at 17:39

4 Answers4

6

Subscribe to all controls MouseMove events (consider do it recursively for nested controls)

foreach (Control control in Controls)
    control.MouseMove += RedirectMouseMove;

And raise MouseMove inside this event handler

private void RedirectMouseMove(object sender, MouseEventArgs e)
{
    Control control = (Control)sender;
    Point screenPoint = control.PointToScreen(new Point(e.X, e.Y));
    Point formPoint = PointToClient(screenPoint);
    MouseEventArgs args = new MouseEventArgs(e.Button, e.Clicks, 
        formPoint.X, formPoint.Y, e.Delta);
    OnMouseMove(args);
}

Keep in mind that controls receive MouseEvents with local coordinates of control. So you need to convert it to form coordinates. There are could be drawbacks with nested controls, but I leave it to you (e.g. call Parent.PointToClient)

UPDATE: You are still will be able to handle events of control - just subscribe to event one more time.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
1

You can use GlobalMouseKeyHook library to easily intercept system wide mouse position.

On mouse click you should then check if mouse location point intersects your form OR if the windows under your mouse is your form.

To do the latter thing you need WindowFromPoint API function:

    [DllImport( "user32.dll", SetLastError = true )]
    public static extern IntPtr WindowFromPoint( [In] POINTAPI Point );

    private void _mouseListener_MouseClick( object sender, MouseEventArgs e )
    {
        var localPoint = this.PointToClient( e.Location );
        bool containsPoint = this.ClientRectangle.Contains( localPoint );

        var windowHandle = WindowFromPoint( e.Location );
        var ctl = (Form)Form.FromHandle( windowHandle );
        bool mainFormClicked = ctl != null && ctl.Handle == this.Handle;

        if( containsPoint && mainFormClicked  )
        {
              //form click is intercepted!
        }
    }

Actually I use this when i want to intercept click outside my form (there is no other way). In your case i'd bind to every control's MouseClick for performance sake (global hook is heavy).

Mauro Sampietro
  • 2,739
  • 1
  • 24
  • 50
1

Based on your comments,

Implement the redirect functionality of the Mouse Event in a base class, then make all controls derive from that base class.

Thus, you only implement the functionality once and then all your controls will "rethrow" the mouse event to be caught by the Main Form.

Hope this helps.

tzup
  • 3,566
  • 3
  • 26
  • 34
  • 1
    Yup I did think Of that... But this makes me change legacy code more than what I am willing to. Just was wondering if there was not a way to completely bypass controls... – Mehdi LAMRANI Feb 14 '11 at 11:23
1

Override the Control.PreProcessMessage Method:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.preprocessmessage.aspx

Edit:

It seems PreProcessMessage might not work for mouse events. Try overriding WndPrc instead. It can intercept mouse messages for sure, but you need to see if it intercepts them in the order you want:

http://bytes.com/topic/c-sharp/answers/752144-preprocessmessage

Pedery
  • 3,632
  • 1
  • 27
  • 39