什么是判断鼠标是否在表单上方的最佳方法?

时间:2010-05-20 14:33:53

标签: c# .net winforms mouseover

我在整个表单中找到how to capture mouse clicks,但此方法对MouseEnterMouseLeave的转换效果不佳。我的表单布局由许多PanelsTableLayoutPanels组成,因此我无法监控事件的全方位控制,显然按钮的MouseLeave事件并不意味着光标离开了整个表格。有没有人想出一个解决这个问题的好方法?

5 个答案:

答案 0 :(得分:3)

开始的地方是检查ClientRectangle是否包含当前鼠标位置。因此,例如,在MouseMove处理程序上,您可以:

if (ClientRectangle.Contains(e.Location))
{
    bool mouseIsOverThisControl = true;
}

答案 1 :(得分:0)

使用合理的Interval(可能是50ms)向表单添加一个计时器。在Tick事件处理程序中使用此代码以查看鼠标是否在表单上:

// Check if mouse is currently over the form
    bool temp_mof = ClientRectangle.Contains(
       Form.MousePosition.X - Location.X,
       Form.MousePosition.Y - Location.Y);

编辑:这是一个更完整的解决方案,用于检测鼠标是否在表单上并且单击了按钮。 timer1Tick()是表单上Timer的Tick事件处理程序。没有必要为表单上的其他控件添加其他事件处理程序。这将使您的表单成为“一个巨大的按钮”:)

bool m_mouse_over_form = false;
// Assume the left button is down at onset
bool m_left_button_down = true;

void timer1Tick (object sender, EventArgs e)
{
   // Check if mouse is currently over the form
   bool temp_mof = ClientRectangle.Contains(
      Form.MousePosition.X - Location.X,
      Form.MousePosition.Y - Location.Y);

   // were we already over the form before this tick?
   if (temp_mof && m_mouse_over_form)
   {
       // we need to detect the mouse down and up to avoid
       // repeated calls if the mouse button is held down for more
       // than our Tick interval

       // was the mouse button up prior to now?
       if (!m_left_button_down)
       {
           // is the button down now?
           m_left_button_down = (MouseButtons == MouseButtons.Left);

           if (m_left_button_down)
           {
               // the button was down and has now been released
               LeftButtonClickHandler();
           }
           else
           {
               // do nothing, the button has not been release yet
           }
       }
       else
       {
           // update the button state
           m_left_button_down = (MouseButtons == MouseButtons.Left);
       }
   }
   else if (temp_mof)
   {
       // the mouse just entered the form

       m_mouse_over_form = true;

       // set the initial state of the left button
       m_left_button_down = MouseButtons == MouseButtons.Left);
   }
   else
   {
       // the mouse is not currently over the form
       m_mouse_over_form = false;
       m_left_button_down = true;
   }
}

答案 2 :(得分:0)

正如有人指出here,可以使用SetWindowsHookEx()或将MouseMove事件挂接到表单中的所有控件上。后者对我很好。唯一的缺点是如果在运行时添加/删除控件,则可能需要另一种解决方案。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsForms_MouseEvents
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            MouseMove += OnMouseMove;
            MouseLeave += OnMouseLeave;

            HookMouseMove(this.Controls);
        }

        private void HookMouseMove(Control.ControlCollection ctls)
        {
            foreach (Control ctl in ctls)
            {
                ctl.MouseMove += OnMouseMove;
                HookMouseMove(ctl.Controls);
            }
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            BackColor = Color.Plum;

            Control ctl = sender as Control;
            if (ctl != null)
            {
                // Map mouse coordinate to form
                Point loc = this.PointToClient(ctl.PointToScreen(e.Location));
                Console.WriteLine("Mouse at {0},{1}", loc.X, loc.Y);
            }
        }

        private void OnMouseLeave(object sender, EventArgs e)
        {
            BackColor = Color.Gray;
        }

    }
}

答案 3 :(得分:0)

我找到了一些接近我想要的答案,但我做了不同的事情。我想检测鼠标是否离开了表单区域(包括标题栏),这对我有用:

在表单构造函数中,我添加了一个计时器:

Inherited

然后在tick方法中,我执行以下操作:

time.Interval = 250;
time.Tick += time_Tick;
time.Start();

答案 4 :(得分:0)

在表单和表单控件上执行MouseEnter和MouseLeave事件;使用布尔值来确定鼠标是输入还是离开。

一个例子是

    private static bool mouseEnteredForm

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        mouseEnteredForm = true;
        Form.MouseLeave += Form1_MouseLeave;
        CheckMouseLocation();
    }

    private void Form1_MouseLeave(object sender, MouseEventArgs e)
    {
        mouseEnteredForm = false
        CheckMouseLocation();
    }

    private static void CheckMouseLocation()
    {
        if(!mouseOverForm)
        {
            MessageBox.Show("Mouse Not Over Form!);
        }
        else if(mouseOverForm) //else if is optional. You could also use else in this case. I used else if for the sake of the example.
        {
            MessageBox.Show("Mouse Is Over Form");
        }
    }

如果表单上有很多对象,这可能会很繁琐