如何为窗体设置单击事件
本文关键字:单击 事件 设置 窗体 | 更新日期: 2023-09-27 17:47:47
我有一个带有许多自定义控件的c#表单(我们称之为MainForm)。我希望每当有人点击表单时,无论点击是在表单上还是在其中一个自定义控件上,都能激发MainForm.OnClick()方法。我正在寻找类似于窗体的KeyPreview功能的行为,除了鼠标单击而不是按键。
我建议为应用程序中的其他表单创建一个要继承的基本表单。将此代码添加到基本表单以创建一个名为GlobalMouseLickEventHandler的新事件:
namespace Temp
{
public delegate void GlobalMouseClickEventHander(object sender, MouseEventArgs e);
public partial class TestForm : Form
{
[Category("Action")]
[Description("Fires when any control on the form is clicked.")]
public event GlobalMouseClickEventHander GlobalMouseClick;
public TestForm()
{
InitializeComponent();
BindControlMouseClicks(this);
}
private void BindControlMouseClicks(Control con)
{
con.MouseClick += delegate(object sender, MouseEventArgs e)
{
TriggerMouseClicked(sender, e);
};
// bind to controls already added
foreach (Control i in con.Controls)
{
BindControlMouseClicks(i);
}
// bind to controls added in the future
con.ControlAdded += delegate(object sender, ControlEventArgs e)
{
BindControlMouseClicks(e.Control);
};
}
private void TriggerMouseClicked(object sender, MouseEventArgs e)
{
if (GlobalMouseClick != null)
{
GlobalMouseClick(sender, e);
}
}
}
}
此解决方案不仅适用于顶级控件,还适用于嵌套控件,例如放置在面板内的控件。
在窗体的ControlAdded事件中,向控件添加MouseClick处理程序,其中包含窗体的click事件的Address。我还没有测试过,但它可能会起作用。
Private Sub Example_ControlAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles Me.ControlAdded
AddHandler e.Control.MouseClick, AddressOf Example_MouseClick
End Sub
Private Sub Example_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
MessageBox.Show("Click")
End Sub
我做到这一点的唯一方法是处理每个控件的[c]Click[/c]事件。我不相信该事件是在控制处理之前引发的。
在WPF中,有一些"隧道"预览事件提供了这一功能,但这对WinForms并没有真正的帮助。
如果您愿意,您可以挂接控件的所有事件,然后以这种方式进行监视。我认为有一些非常奇特的Win32 api方法可以捕获它们,但目前我还无法做到这一点。
public Form1()
{
InitializeComponent();
HookEvents();
}
private void HookEvents() {
foreach (Control ctl in this.Controls) {
ctl.MouseClick += new MouseEventHandler(Form1_MouseClick);
}
}
void Form1_MouseClick(object sender, MouseEventArgs e)
{
LogEvent(sender, "MouseClick");
}
// and then this just logs to a multiline textbox you have somwhere on the form
private void LogEvent(object sender, string msg) {
this.textBox1.Text = string.Format("{0} {1} ({2}) 'n {3}",
DateTime.Now.TimeOfDay.ToString(),
msg,
sender.GetType().Name,
textBox1.Text
);
}
输出是这样的,显示所有事件以及谁"发送"了它们:
14:51:42.3381985 MouseClick (Form1)
14:51:40.6194485 MouseClick (RichTextBox)
14:51:40.0100735 MouseClick (TextBox)
14:51:39.6194485 MouseClick (Form1)
14:51:39.2131985 MouseClick (RichTextBox)
14:51:38.8694485 MouseClick (Button)
HTH。
点击表单上的开放空间很容易,但要点击控件,需要该控件的配合才能将其发送到表单。
一种可能性是在整个表单上放置一个透明的控件,并接受点击,处理它们,然后将它们传递到下面的适当控件上。
这是开发中的一种常见模式,称为Observer模式。有很多Observer模式的例子,c#是一个例子http://msdn.microsoft.com/en-us/library/ms954621.aspx但是有一个好的谷歌。