我正在尝试处理特定表单上的 mouseclick 事件,如果鼠标光标落在一组坐标之间应该触发 - 比如说一个正方形。
我知道如果我有一个空表单,我可以简单地绑定到 mousemove 事件然后我就走了。但实际上可能有多达 10 个不同的重叠控件,并且在我的测试应用程序中,mousemove 事件仅在光标位于实际表单本身而不是在子控件上方时才会触发。
当设计时有未知数量的子控件时,有谁知道如何处理此事件?
我可以使用简单的单线吗?
试试这个:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
AddMouseMoveHandler(this);
}
private void AddMouseMoveHandler(Control c)
{
c.MouseMove += MouseMoveHandler;
if(c.Controls.Count>0)
{
foreach (Control ct in c.Controls)
AddMouseMoveHandler(ct);
}
}
private void MouseMoveHandler(object sender, MouseEventArgs e)
{
lblXY.Text = string.Format("X: {0}, Y:{1}", e.X, e.Y);
}
}
我知道这篇文章已经很老了,但在我看来,最简单的方法是让表单实现IMessageFilter
. 在您调用的构造函数(或 in OnHandleCreated
)中
Application.AddMessageFilter(this);
然后你可以在你的实现中捕获所有窗口的消息IMessageFilter.PreFilterMessage
。
您可能需要对 WIN32 IsChild 方法使用 P/Invoke
[DllImport("user32.dll")]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
以及表单的Handle
属性,以确保您处理正确的消息。
为什么不直接使用控件的 mouseover 事件处理程序?
恕我直言,这里有一点二元情况:并且没有“单线”。我能看到的唯一解决方案是将不实现事件的控件放入实现的.NET 容器中。
当任何控件获得点击时,正常的预期行为是它将成为窗体的活动控件(始终可以通过 this.ActivceControl 访问)。
但是,特别是如果您单击的控件捕获了鼠标,则必须引发事件,因为 .NET 没有实现事件“冒泡”(如 WPF 那样)。
处理任何密封对象的扩展行为的常用方法是编写扩展方法,我发现为 Control 编写扩展非常容易,但我不知道在这种情况下这是否对您有所帮助。不幸的是,我现在不在我的祖国,也没有 Visual Studio 可以玩。
您可以用来确定窗体上的给定点是否落入任何控件的范围内的一种策略是通过'forall of the Forms Control.Collection (this.Controls) 枚举窗体上所有控件的区域(边界)。但是,如果您有重叠的控件,那么您就会遇到多个控件可能包含给定点的问题。
最好的,比尔
我知道我有点迟到了,但是今天早些时候我在使用面板作为标题栏时遇到了麻烦。我有一个标签来显示一些文本,一个图片框和几个按钮都嵌套在面板中,但无论如何我都需要捕获 MouseMove 事件。
我决定做的是实现一个递归方法处理程序来执行此操作,因为我只有 1 级嵌套控件,当您开始接近可笑的嵌套级别时,这可能无法很好地扩展。
我是这样做的:
protected virtual void NestedControl_Mousemove(object sender, MouseEventArgs e)
{
Control current = sender as Control;
//you will need to edit this to identify the true parent of your top-level control. As I was writing a custom UserControl, "this" was my title-bar's parent.
if (current.Parent != this)
{
// Reconstruct the args to get a correct X/Y value.
// you can ignore this if you never need to get e.X/e.Y accurately.
MouseEventArgs newArgs = new MouseEventArgs
(
e.Button,
e.Clicks,
e.X + current.Location.X,
e.Y + current.Location.Y,
e.Delta
);
NestedControl_Mousemove(current.Parent, newArgs);
}
else
{
// My "true" MouseMove handler, called at last.
TitlebarMouseMove(current, e);
}
}
//helper method to basically just ensure all the child controls subscribe to the NestedControl_MouseMove event.
protected virtual void AddNestedMouseHandler(Control root, MouseEventHandler nestedHandler)
{
root.MouseMove += new MouseEventHandler(nestedHandler);
if (root.Controls.Count > 0)
foreach (Control c in root.Controls)
AddNestedMouseHandler(c, nestedHandler);
}
然后设置起来比较简单:
定义您的“真正”处理程序:
protected virtual void TitlebarMouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Text = string.Format("({0}, {1})", e.X, e.Y);
}
}
然后设置控件事件订阅者:
//pnlDisplay is my title bar panel.
AddNestedMouseHandler(pnlDisplay, NestedControl_Mousemove);
使用起来相对简单,我可以保证它的工作原理:)