• ベストアンサー

[.NET]可変個のウィンドウを持つアプリケーション

言語はC#,C++/CLI、環境はVS(バージョン不問) フォームアプリケーションを作るとデフォルトで1つのフォームが作られますが、ウィンドウを複数持ったり或いは持たなかったりするアプリケーションの場合、一般にどのように実装すればいいですか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

#1 Wizard_Zeroです。補足します。 > 複数のフォームをメッセージループに入れる事は出来ませんか? これは出来ないと思います。 > 或いは自前でメッセージループの組む事は出来ますか? C#では試したことないので分かりかねます。 メッセージループを特定のフォームに限定せず、実行時に動的に切り替えるにはApplicationContextを使うことで実現できます。 ApplicationContextのMainFormで指定したフォームが生きている限り、アプリケーションは実行し続けます。 アプリケーション開始後はひとまずどれかをMainFormに設定し、そのフォームが閉じられたら残っているフォームをMainFormにすれば、フォームを閉じる順番は自由にできます。残っているフォームはApplication.OpenFormからFormCollectionを取得することで調べられます。 この方法だと、全てのウィンドウに対しフォームが閉じられたときに次のフォームを指定する手続きが必要ですが、イベントハンドラを動的に指定することである程度自動化することができます。 > 実装が若干ゴリ押しになる気がしますが・・・ ゴリ押してみました。 static class Program { // Application.Runに使用するアプリケーションコンテキスト private static ApplicationContext ctxApp; /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // Application.Run(new Form1()); // アプリケーションコンテキストを作成 ctxApp = new ApplicationContext(); // フォームを複数生成(この辺はカスタマイズしてください) for (int i = 1; i <= 4; i++) { Form1 frmNew = new Form1(); // イベントハンドラを追加 frmNew.FormClosed += new FormClosedEventHandler(Form_Closed); frmNew.Text = "フォーム" + i.ToString() + "個目"; frmNew.Show(); } // ひとまずメインフォームをコレクション先頭のフォームにする ctxApp.MainForm = Application.OpenForms[0]; // ApplicationContextでメッセージループ Application.Run(ctxApp); } // フォームを閉じたときに呼び出される private static void Form_Closed(object sender, System.EventArgs e) { // イベントハンドラを解除 ((Form)sender).FormClosed -= new FormClosedEventHandler(Form_Closed); // 開いているフォームが残っていたらコレクション先頭のフォームをメインフォームにする if (Application.OpenForms.Count > 0) { ctxApp.MainForm = Application.OpenForms[0]; } } }

yurume
質問者

お礼

ありがとうございます。 参考になりました。

その他の回答 (2)

回答No.3

0個の場合,Application.Runを実行しないことが多いです。 複数個の場合,ApplicationContextクラスのインスタンスをApplication.Runに渡します。 具体的な例は,MSDNのApplicationContextクラスのヘルプにあります。 MSDN: ApplicationContext クラス (System.Windows.Forms) http://msdn.microsoft.com/ja-jp/library/system.windows.forms.applicationcontext.aspx 複数個のフォームの例としてはごちゃごちゃし過ぎている感じもしますので,不要な部分を取り去ってみました。 // csc qa5036914.cs using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; namespace MyApplication {  // A simple form that represents a window in our application  public class AppForm2 : System.Windows.Forms.Form  {   public AppForm2()   {    this.Size = new Size(300,300);    this.Text = "AppForm2";   }  }  // A simple form that represents a window in our application  public class AppForm1 : Form  {   public AppForm1()   {    this.Size = new Size(300,300);    this.Text = "AppForm1";   }  }  // The class that handles the creation of the application windows  class MyApplicationContext : ApplicationContext  {   private int formCount;   private AppForm1 form1;   private AppForm2 form2;   private MyApplicationContext()   {    formCount = 0;    // Create both application forms and handle the Closed event    // to know when both forms are closed.    form1 = new AppForm1();    form1.FormClosed += OnFormClosed;    formCount++;    form2 = new AppForm2();    form2.FormClosed += OnFormClosed;    formCount++;    // Show both forms.    form1.Show();    form2.Show();   }   private void OnFormClosed(object sender, FormClosedEventArgs e)   {    // When a form is closed, decrement the count of open forms.    // When the count gets to 0, exit the app by calling    // ExitThread().    formCount--;    if (formCount == 0)    {     ExitThread();    }   }   [STAThread]   static void Main(string[] args)   {    // Create the MyApplicationContext, that derives from ApplicationContext,    // that manages when the application should exit.    MyApplicationContext context = new MyApplicationContext();    // Run the application with the specific context. It will exit when    // all forms are closed.    Application.Run(context);   }  } }

yurume
質問者

お礼

ありがとうございます。参考になりました。 #2と同様にApplicationContextですね。 余談ですが、ExitThread()でapp終了していることに驚きました。

回答No.1

C#の場合(VS2005しかないので、他のバージョンは分かりませんが、たぶん同じかな?) Program.csのエントリポイント static void Main() でフォームをひとつ作成していますので、ここを書き換えてフォームのインスタンスを複数作ります。 static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // 「デフォルトで1つのフォームが作られます」の正体がこれ // Application.Run(new Form1()); // 一つ目のインスタンス Form1 frmFormA; frmFormA = new Form1(); frmFormA.Show(); frmFormA.Text = "オーナーフォーム"; // 二つ目のインスタンス Form1 frmFormB; frmFormB = new Form1(); frmFormB.Show(); frmFormB.Text = "サブフォーム"; // オーナーフォームでメッセージループを行う Application.Run(frmFormA); } } 今回のケースでは、オーナーフォームを閉じると、サブフォームも強制的に閉じられます。このあたりは調整してください。 ウィンドウを持たない場合は、単純にフォームのインスタンスを作らず・表示せずにすればよいです。 プロジェクトの作成時にコンソールアプリケーションを選ぶのが手っ取り早いです。

yurume
質問者

お礼

回答ありがとうございます。 複数のフォームをメッセージループに入れる事は出来ませんか?或いは自前でメッセージループの組む事は出来ますか? このケースだと、サブフォームからアプリケーションを終了したり、オーナーフォームのみ閉じサブフォームを残す場合の実装が若干ゴリ押しになる気がしますが・・・

関連するQ&A

専門家に質問してみよう