2012-11-15 17 views
6

Mam 3 formularze w mojej aplikacji C# - Form1, Form2 i Form3. Obecnie, gdy moja aplikacja się uruchamia, ładuje się Form1. Chcę, aby wszystkie trzy formularze otwierały się podczas uruchamiania aplikacji.Wyświetlanie wielu formularzy po uruchomieniu aplikacji C#

Próbowałem robić to na Program.cs:

static void Main() 
{  
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    Application.Run(new Form1()); 
    Application.Run(new Form2()); 
} 

ale Form2 pojawia się dopiero po Form1 jest zamknięta.

Jak mogę utworzyć wszystkie 3 formularze jednocześnie, zaraz po uruchomieniu aplikacji?

Odpowiedz

10

Rozpocznij inne formularze od zdarzenia Form.LoadForm1.

private void Form1_Load(object sender, EventArgs e) 
{ 
    Form2 form2 = new Form2(); 
    form2.Show(); 
} 
+0

Jedyna rzecz z tym, to skąd on wie, kiedy program ma się zamknąć? Według użytkownika, może on zamknąć każde okno w dowolnym momencie. –

+0

@DJBurb Gdzie on określa pożądane zachowanie zamknięcia? Czy aplikacja kończy się, gdy * wszystkie * 3 zostaną zamknięte, gdy * any * 3 zostaną zamknięte, lub gdy określony formularz zostanie zamknięty? Jeden lub dowolny, oba są łatwe. Wszystko byłoby odrobinę więcej pracy. – Servy

+0

Wydaje mi się, że musisz to sobie wyobrazić, ale możesz skorzystać z ['Form.FormClosing'] (http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosing. aspx), aby dowiedzieć się, kiedy formularz jest zamknięty, przerwij zamykanie i ukryj formularz. Kiedy wszystkie formularze są ukryte, zamknij aplikację. –

-2

również można użyć 3 Tabs odrobina jeden formularz zamiast 3 formy

16

Generalnie sposób prawo mieć swoją aplikację zrobienia czegoś innego niż domyślny (otworzyć formularz, czekać na to, aby zamknąć, następnie zakończ) jest utworzenie klasy, która dziedziczy po ApplicationContext. Następnie przekazujesz instancję klasy do metody Application.Run. Gdy aplikacja powinna się zamknąć, zadzwoń pod numer ExitThread() z poziomu swojej klasy.

W takim przypadku można utworzyć wystąpienia trzech formularzy po załadowaniu aplikacji i zarejestrować procedurę obsługi dla ich zdarzeń Closed. Kiedy każdy formularz zostanie zamknięty, przewodnik sprawdzi, czy są jeszcze jakieś inne formularze, a jeśli nie, zamknie aplikację.

The example on MSDN robi dwie rzeczy:

  1. otwierania wielu form i wychodzenia z aplikacji, gdy są one zamknięte
  2. zapisując ostatni rozmiar i położenie każdej postaci, gdy forma jest zamknięta.

prostszy przykład, który zamyka aplikację tylko po wszystkie formy są zamknięte:

class MyApplicationContext : ApplicationContext { 
    private void onFormClosed(object sender, EventArgs e) { 
     if (Application.OpenForms.Count == 0) { 
      ExitThread(); 
     } 
    } 

    public MyApplicationContext() { 
     //If WinForms exposed a global event that fires whenever a new Form is created, 
     //we could use that event to register for the form's `FormClosed` event. 
     //Without such a global event, we have to register each Form when it is created 
     //This means that any forms created outside of the ApplicationContext will not prevent the 
     //application close. 

     var forms = new List<Form>() { 
      new Form1(), 
      new Form2(), 
      new Form3() 
     }; 
     foreach (var form in forms) { 
      form.FormClosed += onFormClosed; 
     } 

     //to show all the forms on start 
     //can be included in the previous foreach 
     foreach (var form in forms) { 
      form.Show(); 
     } 

     //to show only the first form on start 
     //forms[0].Show(); 
    } 
} 

Następnie klasa Program wygląda następująco: logika zamykanie

static class Program { 
    [STAThread] 
    static void Main() { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new MyApplicationContext()); 
    } 
} 

aplikacja może oczywiście być spersonalizowane - czy formularze są nadal otwarte, czy tylko jeden z tych trzech typów, lub tylko pierwsze trzy instancje (które wymagałyby odniesienia do pierwszych trzech instancji, ewentualnie w List<Form>).

Re: globalne wydarzenie dla każdego tworzenia formularza - this wygląda obiecująco.

Podobny przykład: here.

+0

Przyjęta odpowiedź jest błędna. Powoduje, że formularz 1 jest formą wiodącą. Dzięki temu każdy formularz może być aplikacją, dopóki wszystkie nie zostaną usunięte. The Race-Condition, o którym mówiono, prawdopodobnie nigdy się nie wydarzy, umieść obiekt blokady wokół instrukcji remove, jeśli musisz się tym martwić. – jerrylagrou

+1

Ponieważ wszystkie formularze są tworzone w tym samym wątku, nie ma warunków wyścigu. Przetwarzanie zdarzeń interfejsu użytkownika odbywa się sekwencyjnie w wątku interfejsu użytkownika. –

-1

Znalazłem moje rozwiązanie nieznacznie modyfikując odpowiedź Zev Spitz.

Uwaga: ta wersja uruchamia tylko pierwszy formularz określony na liście formularzy.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Windows.Forms; 

class MyApplicationContext : ApplicationContext 
{ 
    public List<Form> Forms = new List<Form>() { 
     new Form1() 
    }; 

    private List<Form> FormCollectionToList(FormCollection fc) 
    { 
     List<Form> ff = new List<Form>(); 
     foreach (Form f in fc) 
     { 
      ff.Add(f); 
     } 
     return ff; 
    } 

    private void onFormClosed(object sender, EventArgs e) 
    { 
     Forms = FormCollectionToList(Application.OpenForms); 
     if (Forms.Count == 0) 
     { 
      ExitThread(); 
     } 
     foreach (var form in Forms) 
     { 
      form.FormClosed -= onFormClosed; 
      form.FormClosed += onFormClosed; 
     } 
    } 

    public MyApplicationContext() 
    { 
     if (Forms.Count == 0) 
     { 
      Process.GetCurrentProcess().Kill(); 
     } 
     Forms[0].FormClosed += onFormClosed; 
     Forms[0].Show(); 
    } 
} 

Ta wersja uruchamia je wszystkie.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Windows.Forms; 

class MyApplicationContext : ApplicationContext 
{ 
    public List<Form> Forms = new List<Form>() { 
     new Form1() 
    }; 

    private List<Form> FormCollectionToList(FormCollection fc) 
    { 
     List<Form> ff = new List<Form>(); 
     foreach (Form f in fc) 
     { 
      ff.Add(f); 
     } 
     return ff; 
    } 

    private void onFormClosed(object sender, EventArgs e) 
    { 
     Forms = FormCollectionToList(Application.OpenForms); 
     if (Forms.Count == 0) 
     { 
      ExitThread(); 
     } 
     foreach (var form in Forms) 
     { 
      form.FormClosed -= onFormClosed; 
      form.FormClosed += onFormClosed; 
     } 
    } 

    public MyApplicationContext() 
    { 
     if (Forms.Count == 0) 
     { 
      Process.GetCurrentProcess().Kill(); 
     } 
     foreach (var form in Forms) 
     { 
      form.FormClosed += onFormClosed; 
      form.Show(); 
     } 
    } 
} 
+0

Nie potrzebujesz funkcji 'FormsCollectionToList'. Możesz napisać 'var openForms = Application.OpenForms.Cast

() .ToList();'. –

+0

Ponadto, jaki jest sens sprawdzania 'Forms.Count' w konstruktorze? Kiedy będzie kiedykolwiek 0? –

+0

Używanie 'Application.OpenForms' sugeruje, że można pozbyć się prywatnego pola' List '. Zobacz moją zaktualizowaną odpowiedź. –

Powiązane problemy