2012-11-15 57 views
6

私のC#アプリケーションにはForm1、Form2、Form3という3つのフォームがあります。現在私のアプリケーションが起動すると、Form1がロードされます。アプリケーションの起動時に3つのフォームをすべて開くようにします。C#アプリケーションの起動時に複数のフォームを表示する

私はProgram.csでこれをやってみました:

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

が、Form1が閉じた後Form2がのみ表示されます。

3つのフォームをすべてアプリケーションの起動直後に同時に表示させるにはどうすればよいですか?

答えて

10

Form.Loadイベントから他のフォームを開始してForm1としてください。

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

これは唯一のことですが、プログラムの終了時期はどのようにわかりますか?ユーザーは、いつでもウィンドウを閉じることができます。 –

+0

@DJBurb彼はどこで望ましいクローズド・ビヘイビアを指定しますか? * all * 3が閉じられたとき、* * 3が閉じられたとき、または特定のフォームが閉じられたときにアプリケーションが終了する必要がありますか? 1つ、または任意の2つは簡単です。すべては、より多くの仕事が必要です。 – Servy

+0

私はあなた自身でそれを理解する必要があると思いますが、['Form.FormClosing'](http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosing)を使用することができます。フォームが閉じられたときを見つけて、終了を中止し、代わりにフォームを非表示にすることができます。すべてのフォームが非表示になったら、アプリケーションを閉じます。 –

-2

また、あなたは一つの形の代わりに3つの形態の一般

16

、アプリケーションがデフォルト以外の何かを持っているための正しい方法(、それがクローズするのを待ち、フォームを開き、聖霊降臨祭の3つのタブを使用することができますexit)は、ApplicationContextを継承するクラスを作ることです。次に、クラスのインスタンスをApplication.Runメソッドに渡します。アプリケーションを終了するときは、クラス内からExitThread()に電話してください。

この場合、アプリケーションの読み込み時に3つのフォームのインスタンスを作成し、イベントのハンドラを登録することができます。各フォームが閉じられると、ハンドラはまだ開いている他のフォームがあるかどうかをチェックし、そうでなければアプリケーションを終了します。

The example on MSDNは2つのことをやっている:

  1. は、複数のフォームを開くと、彼らはすべてしているときにアプリケーションを終了する各フォームが閉じているときに、フォームの最後のサイズと位置を保存
  2. を閉じました。

のみすべてのフォームが閉じられた後にアプリケーションを閉じシンプルな例:

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

はその後、あなたのProgramクラスは次のようになります。

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

アプリケーション閉鎖ロジックすることができます明らかにカスタマイズされています - まだ開いているフォームでも、これらの3つのタイプのうちの1つだけでも、最初の3つのインスタンス(最初の3つのインスタンスへの参照を保持する必要があります。)。

Re:各フォーム作成時のグローバルイベント - thisは有望そうです。

同様の例here

+0

回答が間違っています。これは、form1を先頭にします。これにより、すべてのフォームが削除されるまで各フォームがアプリケーションになります。あなたが絶対に心配しなければならない場合、Race-Conditionのスポークは決して起こりません。ロックステートメントをremoveステートメントの周りに置いてください。 – jerrylagrou

+1

フォームはすべて同じスレッド上に作成されるため、競合条件はありません。 UIイベント処理は、UIスレッドで順番に行われます。 –

-1

私はZev Spitzの答えを少し修正して解決策を見出しました。

注:このバージョンは、フォームリストで指定された最初のフォームのみを開始します。

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

このバージョンではすべてが起動します。

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

'FormsCollectionToList'関数は必要ありません。あなたは 'var openForms = Application.OpenForms.Cast

().ToList();'と書くことができます。 –

+0

また、コンストラクタで 'Forms.Count'をチェックする際のポイントは何ですか?それはいつまで0ですか? –

+0

'Application.OpenForms'を使用すると、私的な' List 'フィールドを取り除くことが可能です。私の更新された答えを見てください。 –

関連する問題