FormClosed 事件实际上是在窗体关闭后被调用吗?

huangapple go评论63阅读模式
英文:

Is FormClosed Event actually called after form closed?

问题

抱歉,我只翻译代码部分,以下是您提供的代码的翻译:

非常抱歉,如果此问题之前已经提出,但我在互联网上找不到合适的答案。我有一个主窗体,其中包含一个用户控件,该用户控件使用以下代码打开另一个窗体:

public partial class OldForm : UserControl
{
    public OldForm(FocusMoreMenu myFocusMore)
    {
        InitializeComponent();
    }

    private void createNewForm(object sender, EventArgs e)
    {
        NewForm newForm = new NewForm(this);
        newForm.Show();
    }

    public void handleCloseEvent(object sender, FormClosedEventArgs e)
    {
        CustomToolTip notifyError = new CustomToolTip();
        notifyError.Show("某些通知", this, Xposition, Yposition, 2000);
    }
}

在我的新窗体中,我填充一个字符串变量,按下按钮,关闭窗体并尝试将该字符串变量传递给我的旧窗体。

public partial class NewForm : Form
{
    OldForm oldFormObject;

    public NewForm(OldForm oldFormObject)
    {
        this.oldFormObject = oldFormObject;
        InitializeComponent();
    }

    private void closeButton(object sender, EventArgs e)
    {
        oldFormObject.passedVariable = someTextBox.Text;
        this.Close();
    }
}

我可以处理所有这些部分,没有任何问题。我还添加了一个FormClosed事件,如下所示:

this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(oldFormObject.handleCloseEvent);

我可以调用handleCloseEvent而没有任何问题。但是当我在该函数内添加断点时,我发现NewForm仍然可见。换句话说,handleCloseEvent在窗体关闭后没有被调用。

您可能会问为什么这是一个问题,这应该不会太重要。然而,这很重要,因为我创建了一个自定义ToolTip类,用于创建通知,如果另一个窗体仍然存在,通知将不会显示。至少这是我问题的高级理解。我是否遗漏了什么?

我该如何找到一种使我的工具提示可见的方法?如果我不像这样创建一个新窗体,使它可见没有任何问题。

英文:

I am really sorry if this question asked before, but I couldn't find a proper answer in internet. I have a main form inside there is a usercontrol that opens another form with below code:

public partial class OldForm: UserControl
{

        public OldForm(FocusMoreMenu myFocusMore)
        {
            InitializeComponent();
        }
        private void createNewForm(object sender, EventArgs e)
        {
            NewForm newForm = new NewForm (this);
            newForm .Show();
        }
        public void handleCloseEvent(object sender, FormClosedEventArgs e) 
        {
             CustomToolTip notifyError = new CustomToolTip();
             notifyError.Show("Some notification ", this, Xposition, Yposition, 2000);
        
        }
}

In my new form I fill a string variable. Press a button, close a form and try to transfer that string variable to my old form.

public partial class NewForm : Form
{

    OldForm oldFormObject;

    public NewForm(OldForm oldFormObject)
    {
        this.oldFormObject = oldFormObject;
        InitializeComponent();
	}
	
	private void closeButton(object sender, EventArgs e)
	{
		oldFormObject.passedVariable = someTextBox.Texts;
		this.Close();
	}

}

I can handle all these parts with out any problem. I also added a ClosedEvent as below:

this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(oldFormObject.handleCloseEvent);

I can call the handleCloseEvent with out any problem also. However when I add a breakpoint inside that function, I saw that NewForm is still visible. In other words the handleCloseEvent doesn't called after the form closed.

You may say why this is a problem, It shouldn't matter that much. However it matters, because I created a Custom ToolTip class which creates a notification and it doesn't appear if another form is still exists. At least this is the high level understanding of my problem. Am I missing something?

How can I find a way to make my tooltip visible? There is no problem on making it visible if I don't create a new form like this.

答案1

得分: 2

我正在仔细阅读你的代码,以查看我是否能够理解你实际想要做什么。如果我理解正确,有两个主要目标:

  1. 显示一个表单,让用户填写字符串。
  2. 当该表单关闭时,在自定义工具提示中显示一些消息。

你在帖子末尾提到了如何找到一种使我的工具提示可见的方法。如果这是你的主要关注点,这 "可能" 被认为是一个 X-Y 问题,因为使工具提示可见不一定要依赖于 FormClosed 事件的顺序。如果我理解错了,请给我留言,我只是发表意见,希望能帮助你完成你想要做的事情。

用户输入表单

这个最小的表单示例显示了一个用于用户输入的文本框,并公开了一个公共属性,以便可以检索 "填充字符串":

public partial class FillStringForm : Form
{
    public FillStringForm()
    {
        InitializeComponent();
        buttonOK.Click += (sender, e) =>
        {
            DialogResult = DialogResult.OK;
        };
        textBoxFillString.KeyDown += (sender, e) =>
        {
            if (e.KeyData.Equals(Keys.Return))
            {
                DialogResult = DialogResult.OK;
            }
        };
    }
    public string StringValue => textBoxFillString.Text;
}

主窗体

一个最小的主窗体,用于显示用户提示,可以这样编写:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonShowFillStringForm.Click += onClickShowFillStringForm;
    }
    private void onClickShowFillStringForm(object? sender, EventArgs e)
    {
        using (var fillStringForm = new FillStringForm())
        {
            if (DialogResult.OK == fillStringForm.ShowDialog(this))
            {
                if (!string.IsNullOrWhiteSpace(fillStringForm.StringValue))
                {
                    // 用户点击了确定。显示输入的值。
                    _customToolTip.Show(fillStringForm.StringValue, this, buttonShowFillStringForm.Location, 1000);
                }
            }
            else
            {
                _customToolTip.Show("填写字符串已取消。", this, buttonShowFillStringForm.Location, 1000);
            }
        }
    }
    CustomToolTip _customToolTip = new CustomToolTip();
}

如果用户输入表单被取消,这段代码会产生一个不同的工具提示。

这段代码在用户输入表单被取消时产生不同的工具提示。

英文:

I'm reading your code carefully to see if I can follow what you're actually trying to do. If I understand it correctly there are two main objectives:

  1. Show a form where the user can fill in a string.
  2. When that form closes, display some kind of message in a custom tool tip.

FormClosed 事件实际上是在窗体关闭后被调用吗?

You end your post by asking How can I find a way to make my tooltip visible? If this is your main concern, this "might" be considered an X-Y problem because making the tool tip visible doesn't have to rely on the sequencing of the FormClosed event to begin with. Please leave me a comment if this is way off, I'm just posting in case it helps you with what you're trying to do.


User Input Form

This minimal form example shows a textbox for user input and exposes a public property so that the "filled string" can be retrieved:

public partial class FillStringForm : Form
{
    public FillStringForm()
    {
        InitializeComponent();
        buttonOK.Click += (sender, e) => DialogResult = DialogResult.OK;
        textBoxFillString.KeyDown += (sender, e) =>
        {
            if(e.KeyData.Equals(Keys.Return))
            {
                DialogResult = DialogResult.OK;
            }
        };
    }
    public string StringValue => textBoxFillString.Text;
}

Main Form

A minimal main form that displays the user prompt can be coded like this:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonShowFillStringForm.Click += onClickShowFillStringForm;
    }
    private void onClickShowFillStringForm(object? sender, EventArgs e)
    {
        using (var fillStringForm = new FillStringForm())
        {
            if (DialogResult.OK == fillStringForm.ShowDialog(this))
            {
                if (!string.IsNullOrWhiteSpace(fillStringForm.StringValue))
                {
                    // User clicked OK. Show the entered value.
                    _customToolTip.Show(fillStringForm.StringValue, this, buttonShowFillStringForm.Location, 1000);
                }
            }
            else
            {
                _customToolTip.Show("Fill string was cancelled.", this, buttonShowFillStringForm.Location, 1000);
            }
        }
    }
    CustomToolTip _customToolTip = new CustomToolTip();
}

This code produces a different tooltip if the user input form is cancelled:

FormClosed 事件实际上是在窗体关闭后被调用吗?

答案2

得分: 2

FormClosed事件实际上在窗体关闭后才被调用吗?

答案可能会令人惊讶,但答案是,无论你如何显示窗体,该事件都会在窗体仍然可见时触发。
窗体的实际关闭(在模态情况下是隐藏,在非模态情况下是销毁)会稍后发生。

要查看源代码并自行跟踪,请参阅.NET Framework的源代码中的WmCloseShowDialog

很容易看出,它在窗体实际关闭之前就会被触发。假设你的窗体上有一个button1,只需将以下代码添加为该按钮的单击事件处理程序:

var f = new Form();
f.FormClosed += (obj, args) => MessageBox.Show(f.Visible.ToString());
f.Show(); // f.ShowDialog();

现在当你运行这段代码时,如果你点击按钮以打开窗体,然后通过点击X按钮来关闭窗体,消息框将出现,而窗体仍然在后台显示。

如何确保代码在窗体实际关闭后运行?

你可以使用Disposed事件:

var f = new Form();
f.Disposed += (obj, args) =>  MessageBox.Show(f.Visible.ToString());
f.Show();

或者你可以使用BeginInvoke来调用在处理WM_CLOSE后要运行的代码,像这样:

var f = new Form();
f.FormClosed += (obj, args) => f.BeginInvoke(
    new Action(() => MessageBox.Show(f.Visible.ToString())));
f.Show();

你真的需要处理Closed事件吗?

好吧,这取决于情况,如果你可以使用模态方式,最好使用ShowDialog来显示窗体,然后在此之后运行逻辑:

using (var f = new Form())
{
    f.ShowDialog();
    MessageBox.Show(f.Visible.ToString());
};
英文:

Is FormClosed event actually called after form closed?

The answer is gonna be surprising, but the answer is No, it doesn't, no matter how you show the form, the event raises while the form is still visible.
The actual closing of the form (hiding in case of modal, or destroying in case of non-modal) happens later.

To see the source and trace it yourself see WmClose and ShowDialog in source code of .NET Framework.

It's pretty simple to show it raises before the form actually closes. Assuming you have a button1, on your form, just add the following code as click event handler for the button:

var f = new Form();
f.FormClosed += (obj, args) => MessageBox.Show(f.Visible.ToString());
f.Show(); // f.ShowDialog();

Now when you run the code, if you click on the button to open the form, and then simply close the form by click on X, the message box appears, while the form is still there in the background.

How can I make sure the code runs after the form is actually closed?

You can use Disposed event:

var f = new Form();
f.Disposed += (obj, args) =>  MessageBox.Show(f.Visible.ToString());
f.Show();

Or you can use call the code that you want run after processing WM_CLOSE, using BeginInvoke like this:

var f = new Form();
f.FormClosed += (obj, args) => f.BeginInvoke(
    new Action(() => MessageBox.Show(f.Visible.ToString())));
f.Show();

Do you really need to handle Closed?

Well, it depends, if you can use a modal, the it's better to show the form using ShowDialog, and run the logic after that:

using (var f = new Form())
{
    f.ShowDialog();
    MessageBox.Show(f.Visible.ToString());
};

huangapple
  • 本文由 发表于 2023年1月9日 01:20:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75049880.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定