1

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.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Meric Ozcan
  • 678
  • 5
  • 25
  • Which form is `oldFormObject.handleCloseEvent` in, and can you show the code in your question? – stuartd Jan 08 '23 at 17:23
  • It is inside the main form which calls the new form. @stuartd Let me put that code too. – Meric Ozcan Jan 08 '23 at 17:24
  • @stuartd Do you think my code is enough? – Meric Ozcan Jan 08 '23 at 17:33
  • 1
    `OldForm` is a `UserControl`, not a Form, so it's not clear what your are "closing". You should re-think this form passing thing though. The NewForm should raise an event or just provide a public property to provide the information to the listener. – LarsTech Jan 08 '23 at 17:50
  • `The FormClosed event occurs after the form has been closed by the user or by the Close method or the Exit method of the Application class.` from [this](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.form.formclosed?view=windowsdesktop-7.0), provide more code like how do you instantiate OldForm, CustomToolTip class etc. – Mike93041 Jan 08 '23 at 18:07
  • @LarsTech newForm is closed not oldForm. – Meric Ozcan Jan 08 '23 at 18:23
  • The following may be helpful: https://stackoverflow.com/questions/69711574/send-data-within-child-forms/69743297 – Tu deschizi eu inchid Jan 08 '23 at 18:35

2 Answers2

2

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.

flow-with-ok

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:

flow-with-cancel

IVSoftware
  • 5,732
  • 2
  • 12
  • 23
  • Thank you for your effort I upvoted your answer let me check it really fast and return to you. – Meric Ozcan Jan 09 '23 at 07:34
  • 1
    Ok it works, you handled the form opening and closing inside one function, with lamda function right? That's something I wouldn't be able to do with my narrow c# knowledge. Thank you. – Meric Ozcan Jan 09 '23 at 08:09
2

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());
};
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398