C# 如何为表单设置点击事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/180452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:51:57  来源:igfitidea点击:

How do I set a click event for a form?

c#winforms

提问by Mykroft

I have a c# form (let's call it MainForm) with a number of custom controls on it. I'd like to have the MainForm.OnClick() method fire anytime someone clicks on the form regardless of whether the click happened on the form or if the click was on one of the custom controls. I'm looking for behavior similar to the KeyPreview feature of forms except for mouse clicks rather than key presses.

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

采纳答案by OwenP

In the form's ControlAdded event, add a MouseClick handler to the control, with the Address of the form's click event. I haven't tested this, but it might work.

在窗体的 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

回答by James Curran

Catching a click on an open space on the form is easy, but to get a click that's actually on a control, you'll need the cooperation of that control to send it to the form.

捕捉对窗体上空白区域的点击很容易,但要获得实际上在控件上的点击,您需要该控件的合作将其发送到窗体。

One possibility is to place a transparent control over the entire form, and accept clicks onto that, deal with them, and then pass them onto the proper control underneath.

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

回答by Tim Jarvis

This is a common pattern in development, its called the Observer pattern. There are lots of examples of Observer patterns and c# here is 1 example http://msdn.microsoft.com/en-us/library/ms954621.aspxbut have a good google around.

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

回答by OwenP

The only way I've ever managed to do this is to handle the [c]Click[/c] event of every control. I don't believe the event is raised before the control processes it.

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

In WPF, there are "tunneling" preview events that provide this functionality, but that doesn't really help you in WinForms.

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

回答by Andrew Backer

You can hook all the control's events, if you like, and then monitor that way. I assume there is some uber fancy Win32 api way to trap them all, but that is beyond me at the moment.

如果您愿意,您可以挂钩所有控件的事件,然后以这种方式进行监视。我认为有一些超级花哨的 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
            );
    }

The output is something like this, showing all the events and who "sent" them up:

输出是这样的,显示所有事件以及谁“发送”它们:

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.

哈。

回答by ChéDon

I recommend creating a base form for the other forms in your application to inherit. Add this code to your base form to create a new event called GlobalMouseClickEventHandler:

我建议为应用程序中的其他表单创建一个基本表单以进行继承。将此代码添加到您的基本表单以创建一个名为 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);
            }
        }
    }
}

This solution will work not only for top-level controls, but also nested controls such as controls placed inside of panels.

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