【问题标题】:.NET: How to check if the mouse is in a control?.NET:如何检查鼠标是否在控件中?
【发布时间】:2011-11-16 22:18:36
【问题描述】:

我想知道鼠标是否在 .NET 中的特定控件中

private void panel1_MouseLeave(object sender, EventArgs e)
{
   if (MouseIsInControl((Control)sender)
      return; //the mouse didn't leave, don't fire a MouseLeave event

   ...
}

public Boolean MouseIsInControl(Control control)
{
    //return (control.Bounds.Contains(MousePosition));
    return control.Bounds.Contains(control.PointToClient(MousePosition))
}

但我需要有人摆弄四个不同的坐标系才能使其工作.

相关问题

【问题讨论】:

  • 好的,你的问题是什么?你刚刚自己说了怎么解决……
  • 这不是多余的吗?如果鼠标没有离开控件,它不会触发 mouseleave 事件。我错过了什么吗?
  • @LarsTech 检测鼠标何时在表单内,我只需要对表单进行控制。
  • WinForms 中有一个“怪癖”:如果将鼠标移到 面板内 的另一个控件上,则会触发 MouseLeave 事件(表示鼠标已离开控制板)。有点像我离开家时我家的警报系统会启动 - 而实际上我还在我家,就在浴室里。

标签: .net winforms


【解决方案1】:

不需要挂钩或子类化。

private bool MouseIsOverControl(Button btn) => 
    btn.ClientRectangle.Contains(btn.PointToClient(Cursor.Position))

如果鼠标位于包含控件的表单之外,此方法也可以使用。它使用按钮对象,但您可以使用任何 UI 类

您可以像这样轻松测试该方法:

private void button1_Click(object sender, EventArgs e)
{
    // Sleep to allow you time to move the mouse off the button
    System.Threading.Thread.Sleep(900); 

    // Try moving mouse around or keeping it over the button for different results
    if (MouseIsOverControl(button1))
         MessageBox.Show("Mouse is over the button.");
    else MessageBox.Show("Mouse is NOT over the button.");
}

【讨论】:

    【解决方案2】:

    这个Hans Passant Answer可以适应你想要的:

    private bool mEntered;
    private Timer timer1;
    
    public Form1() {
      InitializeComponent();
    
      timer1 = new Timer();
      timer1.Interval = 200;
      timer1.Tick += timer1_Tick;
      timer1.Enabled = false;
    }
    
    private void panel1_MouseEnter(object sender, EventArgs e) {
      timer1.Enabled = true;
    }
    
    private void timer1_Tick(object sender, EventArgs e) {
      bool entered = panel1.ClientRectangle.Contains(panel1.PointToClient(Cursor.Position));
      if (entered != mEntered) {
        mEntered = entered;
        if (!entered) {
          timer1.Enabled = false;
          // OK, Do something, the mouse left the parent container
        }
      }
    }
    

    【讨论】:

    • 缺点是 UI 中引入的延迟。
    【解决方案3】:

    我也为此解决方案使用 System.Windows.Forms.Timer,但我不再使用进入/离开鼠标事件。他们给我带来了太多的悲伤。相反,我在我需要知道鼠标已结束的组件上使用 MouseMove 事件。我在这个类中有 2 个成员变量。

    bool Hovering = false;
    System.Drawing.Point LastKnownMousePoint = new System.Drawing.Point();
    

    就我而言,我想切换标签周围的边框。我处理知道鼠标是否在我关心的标签控件上如下:

        private void label1_MouseMove(object sender, MouseEventArgs e)
        {
            // Mouse Position relative to the form... not the control
            LastKnownMousePoint = Cursor.Position; 
    
            label1.BorderStyle = BorderStyle.Fixed3D;
            timer1.Stop();
            timer1.Interval = 50; // Very fast (Overkill?  :) )
            timer1.Start();
        }
    
        private void timer1_Tick(object sender, EventArgs e)
        {
            System.Drawing.Point point = Cursor.Position;
            if (LastKnownMousePoint.Equals(point))
            {
                // If the mouse is somewhere on the label, I'll call that Hovering.  
                // Though not technically the MS definition, it works for me.
                Hovering = true;
            }
            else if (Hovering == false)
            {
                label1.BorderStyle = BorderStyle.None;
                timer1.Stop();
            }
            else
            {
                Hovering = false;
                // Next time the timer ticks, I'll stop the timer and
                // Toggle the border.
            }
        }
    

    这是因为我只在鼠标悬停在控件上时才更新 LastKnownMousePoint(本例中为标签)。因此,如果鼠标移出控件,我将不会更新 LastKnownMousePoint,我会知道是时候切换边框样式了。

    【讨论】:

      猜你喜欢
      • 2011-05-28
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多