如何为表单设置单击事件?

时间:2008-10-07 21:12:53

标签: c# winforms

我有一个c#表单(我们称之为MainForm),上面有许多自定义控件。我想在任何人点击表单的时候触发MainForm.OnClick()方法,无论表单上是否发生了点击,或者点击是否在其中一个自定义控件上。我正在寻找类似于表单的KeyPreview功能的行为,除了鼠标点击而不是按键。

6 个答案:

答案 0 :(得分:6)

我建议为要继承的应用程序中的其他表单创建基本表单。将此代码添加到基本表单以创建名为GlobalMouseClickEventHandler的新事件:

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

此解决方案不仅适用于顶级控件,还适用于嵌套控件,例如放置在面板内的控件。

答案 1 :(得分:3)

在窗体的ControlAdded事件中,使用窗体的单击事件的地址向控件添加MouseClick处理程序。我没有对此进行过测试,但它可能会有效。

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

答案 2 :(得分:1)

我设法做到这一点的唯一方法是处理每个控件的[c] Click [/ c]事件。我不相信在控制过程之前会引发事件。

在WPF中,有“隧道”预览事件提供此功能,但这对WinForms并没有真正的帮助。

答案 3 :(得分:1)

如果愿意,您可以挂钩所有控件的事件,然后以这种方式进行监控。我假设有一些超级奇特的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。

答案 4 :(得分:0)

单击表单上的空白区域很容易,但要获得实际在控件上的单击,您需要该控件的合作才能将其发送到表单。

一种可能性是对整个表单进行透明控制,并接受对它的点击,处理它们,然后将它们传递到下面的适当控件上。

答案 5 :(得分:0)

这是一种常见的开发模式,它被称为Observer模式。观察者模式有很多例子,c#这里有1个例子http://msdn.microsoft.com/en-us/library/ms954621.aspx,但谷歌周围很好。