开发者

Winforms : Intercepting Mouse Event on Main Form first, not on Controls

开发者 https://www.devze.com 2023-02-11 09:58 出处:网络
There is certainly a convenient way to do this : 开发者_Go百科I have implemented a \"Move Window\" on mouse drag behavior on my main form, and I would like the MouseClick/Move event to be intercepte

There is certainly a convenient way to do this :

开发者_Go百科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 ?


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.


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.


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


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).

0

精彩评论

暂无评论...
验证码 换一张
取 消