我已经想出了如何捕捉整个表单上的鼠标点击,但这种方法对于MouseEnter
和MouseLeave
不太适用。我的表单布局由许多Panels
和TableLayoutPanels
组成,因此没有一个可以监视事件的全包含控件,显然,对于按钮的MouseLeave
事件并不意味着光标离开了整个表单。有没有人想出了一个好的方法来解决这个问题?
我已经想出了如何捕捉整个表单上的鼠标点击,但这种方法对于MouseEnter
和MouseLeave
不太适用。我的表单布局由许多Panels
和TableLayoutPanels
组成,因此没有一个可以监视事件的全包含控件,显然,对于按钮的MouseLeave
事件并不意味着光标离开了整个表单。有没有人想出了一个好的方法来解决这个问题?
一个开始的方法是检查 ClientRectangle 是否包含当前鼠标位置。例如,在你的 MouseMove 处理程序中,你可以这样写:
if (ClientRectangle.Contains(e.Location))
{
bool mouseIsOverThisControl = true;
}
我找到了一些与我想要的接近的答案,但最终我做了一些不同的事情。我想检测鼠标是否离开了表单区域(包括标题栏),这对我有用:
在表单构造函数中,我添加了一个计时器:
time.Interval = 250;
time.Tick += time_Tick;
time.Start();
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;
}
}
在表单中添加一个合理的间隔计时器(可能是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;
}
}
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;
}
}
}
在表单和表单控件上执行鼠标进入和鼠标离开事件;使用布尔值确定鼠标是进入还是离开。
示例:
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");
}
}
如果表单上有许多对象,这可能会变得很繁琐。
MouseEnter
事件,但是当鼠标离开表单时,它停止调用MouseMove
事件,因此它不会检查它是否已经离开表单,对吧? - dlras2