C# 如何检测鼠标是否在整个窗体和子控件内?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/986529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:57:20  来源:igfitidea点击:

How to detect if the mouse is inside the whole form and child controls?

c#winformsmouseeventdetection

提问by rfgamaral

I need to detect when the user moves the mouse over the Form and all its child controls and also when it leaves the Form. I tried the MouseEnterand MouseLeaveevents of the Form, I tried the WM_MOUSEMOVE& WM_MOUSELEAVEand WM_NCMOUSEMOVE& WM_NCMOUSELEAVEpairs of windows messages but none seem to work as I want...

我需要检测用户何时将鼠标移到 Form 及其所有子控件上,以及何时离开 Form。我尝试了窗体的MouseEnterMouseLeave事件,我尝试了WM_MOUSEMOVE&WM_MOUSELEAVEWM_NCMOUSEMOVE&WM_NCMOUSELEAVE对 Windows 消息,但似乎没有一个像我想要的那样工作......

Most of my Form is occupied by child controls of many sorts, there's not much client area visible. This means that if I move the mouse very quickly the mouse movement will not be detected, although the mouse is inside the Form.

我的大部分表单都被各种子控件占用,没有多少客户区可见。这意味着如果我非常快速地移动鼠标,则不会检测到鼠标移动,尽管鼠标在窗体内。

For instance, I have a TextBox that is docked at the bottom and between the desktop and the TextBox, there's only a very small border. If I quickly move the mouse from the bottom into the TextBox, the mouse movement won't be detected, but the mouse is inside the TextBox, therefore, inside the Form.

例如,我有一个文本框,它停靠在桌面和文本框的底部和之间,只有一个非常小的边框。如果我将鼠标从底部快速移动到 TextBox 中,则不会检测到鼠标移动,但鼠标在 TextBox 内,因此,在 Form 内。

How can I achieve what I need?

我怎样才能达到我所需要的?

采纳答案by TcKs

You can hook the main message loop and preprocess/postprocess any (WM_MOUSEMOVE) message what you want.

您可以挂钩主消息循环并根据需要预处理/后处理任何 (WM_MOUSEMOVE) 消息。

public class Form1 : Form {
    private MouseMoveMessageFilter mouseMessageFilter;
    protected override void OnLoad( EventArgs e ) {
        base.OnLoad( e );

        this.mouseMessageFilter = new MouseMoveMessageFilter();
        this.mouseMessageFilter.TargetForm = this;
        Application.AddMessageFilter( this.mouseMessageFilter );
    }

    protected override void OnClosed( EventArgs e ) {
        base.OnClosed( e );

        Application.RemoveMessageFilter( this.mouseMessageFilter );
    }

    class MouseMoveMessageFilter : IMessageFilter {
        public Form TargetForm { get; set; }

        public bool PreFilterMessage( ref Message m ) {
            int numMsg = m.Msg;
            if ( numMsg == 0x0200 /*WM_MOUSEMOVE*/) {
                this.TargetForm.Text = string.Format( "X:{0}, Y:{1}", Control.MousePosition.X, Control.MousePosition.Y );
            }

            return false;
        }

    }
}

回答by NascarEd

How about this: In your form's OnLoad, recursively go through all of the child controls (and their children) and hook up the MouseEnter event.

怎么样:在表单的 OnLoad 中,递归遍历所有子控件(及其子控件)并连接 MouseEnter 事件。

Then whenever the mouse enters any descendant, the event handler will be called. Similarly, you could hook up MouseMove and/or MouseLeave events.

然后每当鼠标进入任何后代时,将调用事件处理程序。同样,您可以连接 MouseMove 和/或 MouseLeave 事件。

protected override void OnLoad()
{
   HookupMouseEnterEvents(this);
}

private void HookupMouseEnterEvents(Control control)
{
   foreach (Control childControl in control.Controls)
   {
      childControl.MouseEnter += new MouseEventHandler(mouseEnter);

      // Recurse on this child to get all of its descendents.
      HookupMouseEnterEvents(childControl);
   }
}

回答by fkerrigan

On your user control create a mousehover Event for your control like this, (or other event type) like this

在您的用户控件上为您的控件创建一个鼠标悬停事件,(或其他事件类型)像这样

private void picBoxThumb_MouseHover(object sender, EventArgs e)
{
    // Call Parent OnMouseHover Event
    OnMouseHover(EventArgs.Empty);
}

On your WinFrom which hosts the UserControl have this for the UserControl to Handle the MouseOver in your Designer.cs

在承载 UserControl 的 WinFrom 上,UserControl 可以在 Designer.cs 中处理 MouseOver

this.thumbImage1.MouseHover += new System.EventHandler(this.ThumbnailMouseHover);

Which calls this method on your WinForm

在您的 WinForm 上调用此方法

private void ThumbnailMouseHover(object sender, EventArgs e)
{

    ThumbImage thumb = (ThumbImage) sender;

}

Where ThumbImage is the type of usercontrol

其中 ThumbImage 是用户控件的类型

回答by Defkon1

Quick and dirty solution:

快速而肮脏的解决方案:

private bool MouseInControl(Control ctrl)
{
    return ctrl.Bounds.Contains(ctrl.PointToClient(MousePosition));
}