c++formswinforms

Open new forms in C++ Windows Forms Application


I'm using visual studio 2012 to work with windows form in C++. I've gotten help from this link Can't find Windows Forms Application for C++

I want to have multiple forms. I've designed Form2 and included Form2.h into Form1.h . But when I open form2, it appears and fades immediately. This is my code:

#include "Form2.h"
...

private: System::void button_Click(System::Object^ sender, System::EventArgs^ e){
    Form2 frm2;
    frm2.Show();
    //this->Hide();
    //this->Close();
}

If i use

this->Hide();

the two forms will hide, and if I close form1

this->Close();

the form2 will close too.

I want to open and close forms independent. What must I do?

Any help would be appreciated


Solution

  • It is rather striking how removing the project template in VS2012 instantly made everybody write the wrong code. You are using "stack semantics", it is an emulation of the RAII pattern in C++. Or in other words, your Form2 instance gets immediately destroyed when your button_Click() returns. Proper code looks like:

       Form2^ frm2 = gcnew Form2;
       frm2->Show();
    

    The exact same bug is present in the code that creates the Form1 instance, visible from you having to pass %form1. It is a bit less obvious because your Main() method keeps executing for the lifetime of the app. Nevertheless, the destructor of the Form1 class will be called twice. Tends to cause havoc when you alter the default one. Same recipe, don't use stack semantics:

       Form1^ mainWindow = gcnew Form1;
       Application::Run(mainWindow);
    

    Or just simply:

       Application::Run(gcnew Form1);
    

    Your app terminates instantly when you call this->Close() because you are closing the main window of your app. Which happens because you passed the Form1 instance to Application::Run(). That's compatible with the way the vast majority of Windows apps behave, closing the "main window" ends the application.

    But that's not what you want so don't pass the form instance to Run(). You need another exit condition for your app, usually you'll want a "when there are no more windows left" condition. Alter your Main() method to look like this:

    void OnFormClosed(System::Object ^sender, System::Windows::Forms::FormClosedEventArgs ^e) {
        Form^ form = safe_cast<Form^>(sender);
        form->FormClosed -= gcnew FormClosedEventHandler(&OnFormClosed);
        if (Application::OpenForms->Count == 0) Application::Exit();
        else Application::OpenForms[0]->FormClosed += gcnew FormClosedEventHandler(&OnFormClosed);
    }
    
    [STAThread]
    int main(array<System::String ^> ^args) {
        Application::EnableVisualStyles();
        Application::SetCompatibleTextRenderingDefault(false);
        Form1^ startupWindow = gcnew Form1;
        startupWindow->FormClosed += gcnew FormClosedEventHandler(&OnFormClosed);
        startupWindow->Show();
        Application::Run();
        return 0;
    }