代码之家  ›  专栏  ›  技术社区  ›  dlras2

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

  •  3
  • dlras2  · 技术社区  · 15 年前

    我想出来了 how to capture mouse clicks 但这个方法不能很好地翻译 MouseEnter MouseLeave . 我的窗体布局由多个 Panels TableLayoutPanels 所以我无法监控事件,显然 鼠标器 按钮的事件并不意味着光标离开整个窗体。有人想出一个解决这个问题的好办法吗?

    5 回复  |  直到 8 年前
        1
  •  0
  •   SlavaGu    15 年前

    正如有人指出的那样 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;
            }
    
        }
    }
    
        2
  •  3
  •   bentsai    15 年前

    开始的地方是检查 ClientRectangle 包含当前鼠标位置。例如,关于 MouseMove 处理程序,您可以有:

    if (ClientRectangle.Contains(e.Location))
    {
        bool mouseIsOverThisControl = true;
    }
    
        3
  •  0
  •   Jerry Fernholz    15 年前

    在窗体中添加一个具有合理间隔(可能为50毫秒)的计时器。在勾选事件处理程序中使用此代码查看鼠标是否位于窗体上:

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

    编辑:这里有一个更完整的解决方案来检测鼠标是否在窗体上以及按钮是否已被单击。 timer1Tick() 是窗体上计时器的勾选事件处理程序。表单上的其他控件不需要有其他事件处理程序。这将使您的表单成为“一个巨大的按钮”:)

    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;
       }
    }
    
        4
  •  0
  •   IgnusFast    9 年前

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

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

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

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

    void time_Tick(object sender, EventArgs e)
    {
        switch (RectangleToScreen(Bounds).Contains(PointToScreen(Cursor.Position))) {
            case true:
                if (Opacity != .9999D)
                    Opacity = .9999D;
                break;
            case false:
                if (Opacity != .5D)
                    Opacity = .5D;
                break;
        }
    }
    
        5
  •  0
  •   Bradley William Elko    8 年前

    在窗体和窗体控件上执行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");
            }
        }
    

    如果表单上有许多对象,这可能会变得单调乏味。