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

发布于 2024-09-01 23:21:22 字数 355 浏览 7 评论 0原文

我想出了如何捕获鼠标点击 覆盖整个表单,但此方法对于 MouseEnterMouseLeave 的转换效果不佳。我的表单布局由许多 PanelsTableLayoutPanels 组成,因此没有可以监视事件的包罗万象的控件,显然还有一个 MouseLeave 事件按钮并不意味着光标离开了整个表单。有没有人想出一个好方法来解决这个问题?

I figured out how to capture mouse clicks over the entire form, but this method doesn't translate well for MouseEnter and MouseLeave. My form layout is made up from many Panels and TableLayoutPanels so there's no all-encompassing control I can monitor events for, and obviously a MouseLeave event for a button doesn't mean the cursor left the entire form. Has anyone figured out a good way to get around this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

眼睛会笑 2024-09-08 23:21:25

正如有人指出此处可以使用 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;
        }

    }
}

As someone pointed out here it's possible to use SetWindowsHookEx() or just hook up MouseMove event onto all controls in the form. The latter works for me fine. The only downside is if you add/remove controls at runtime you might need another solution.

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;
        }

    }
}
翻身的咸鱼 2024-09-08 23:21:25

在表单中添加一个计时器,并设置合理的时间间隔(可能是 50 毫秒)。在 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() 是表单上计时器的 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;
   }
}

Add a timer to the form with a reasonable Interval (maybe 50ms). Use this code in the Tick event handler to see if the mouse is over the form:

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

EDIT: Here is a more complete solution to detecting that the mouse is over the form and that the button has been clicked. timer1Tick() is the Tick event handler for a Timer on the form. There is no need to have additional event handlers for the other controls on the form. This will make your form "one giant button" :)

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;
   }
}
诠释孤独 2024-09-08 23:21:25

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

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

Do A MouseEnter and MouseLeave event over the Form and Form Controls; use a boolean to determine whether the mouse entered or left.

An example would be

    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");
        }
    }

This may get tedious if you have many objects over the form

行雁书 2024-09-08 23:21:24

首先检查 ClientRectangle 是否 包含当前鼠标位置。例如,在您的 MouseMove 处理程序,您可以:

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

A place to start is to check if the ClientRectangle contains the current mouse position. So, for example, on your MouseMove handler, you could have:

if (ClientRectangle.Contains(e.Location))
{
    bool mouseIsOverThisControl = true;
}
梦言归人 2024-09-08 23:21:24

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

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

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;
    }
}

I found a few answers that were close to what I wanted, but I wound up doing something different. I wanted to detect if the mouse left the form area (including the title bar) and this worked for me:

In the form constructor, I add a timer:

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

Then in the tick method, I do the following:

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文