winforms 窗体关闭后是否实际调用了FormClosed事件?

9avjhtql  于 2023-01-09  发布在  其他
关注(0)|答案(2)|浏览(171)

我真的很抱歉,如果这个问题问之前,但我无法找到一个适当的答案在互联网上。我有一个主窗体内有一个用户控件,打开另一个窗体与下面的代码:

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

在我的新表单中我填充了一个string变量。按下一个按钮,关闭一个表单,并尝试将那个string变量转移到我的旧表单中。

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

}

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

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

我也可以调用handleCloseEvent,没有任何问题。但是,当我在该函数中添加断点时,我看到NewForm仍然可见。换句话说,handleCloseEvent在窗体关闭后没有被调用。
你可能会说为什么这是个问题,这不应该那么重要。但是它很重要,因为我创建了一个Custom ToolTip类,它创建了一个通知,如果另一个表单仍然存在,它就不会出现。至少这是对我的问题的高层理解。我错过了什么吗?
我怎样才能使我的工具提示可见呢?如果我不创建这样的新表单,使它可见是没有问题的。

5f0d552i

5f0d552i1#

我正在仔细阅读你的代码,看看我是否能理解你实际上想做的事情。如果我理解正确的话,有两个主要目标:
1.显示用户可在其中填写字符串的窗体。
1.当窗体关闭时,在自定义工具提示中显示某种消息。

你在文章结尾问**我怎样才能找到一种方法让我的工具提示可见?**如果这是你主要关心的问题,那么这个“可能”被认为是X-Y problem,因为让工具提示可见并不一定要依赖于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))
                {
                    // 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();
}

如果用户输入表单被取消,此代码将生成不同的工具提示:

mkh04yzy

mkh04yzy2#

窗体关闭后是否实际调用FormClosed事件?

答案可能会令人惊讶,但答案是,不可能,无论你如何显示窗体,窗体仍然可见时,事件都会引发。窗体的实际关闭(模态时隐藏,非模态时销毁)发生在稍后。
要查看源代码并自己跟踪它,请参阅.NET Framework源代码中的WmClose和ShowDialog。
在窗体实际关闭之前显示它的上升非常简单。假设你有一个button1,在你的窗体上,只需要添加下面的代码作为这个按钮的click事件处理程序:

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

是否确实需要处理已关闭?

当然,这要看情况而定,如果可以使用模态,最好使用ShowDialog显示表单,然后运行逻辑:

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

相关问题