QA@IT

C# 複数のメインフォームを同時に表示したい(AddOwnedForm)

9412 PV

お世話になっております、ハンです。

下記機能を実現したいですが、
FORM1(メイン画面)、FORM2、FORM3
①FORM1を最小化する時、FORM2とFORM3を一緒に最小化します。
②FORM1を閉じる時、FORM2とFORM3を一緒に閉じます。
③FORM1を後ろから前へ表示する時(または最小化状態から表示する時)、FORM2とFORM3を一緒に表示します。

一番やりやすいのは多分AddOwnedFormだと思いますが、
FORM1.AddOwnedForm(FORM2);
FORM1.AddOwnedForm(FORM3);
この場合、FORM1は必ずFORM2とFORM3の後ろに表示します。

どうしてもFORM1をFORM2とFORM3の前面に表示できるようにしたいですが、
なにかいい方法があるでしょうか。

どうぞよろしくお願いいたします。

回答

お世話になります。

実装する時に、タスクバーに表示の不具合がなくなりました。
原因は:
FORM4のSHOWNイベントに:

FORM4.AddOwnedForm(FORM1);
FORM4.AddOwnedForm(FORM2);
FORM4.AddOwnedForm(FORM3);
FORM1.Show();    // FORM2とFORM3の表示はFORM1の中に制御します。
this.Visible = false;

FORM1のFORM_LOADイベントに「起動中」の子画面があって、初期化処理は2~3秒ぐらいかかります。

多分「起動中」の子画面の表示処理のせいで、フォーカスがFORM1とこの子画面の間に切り替えました。
ですので、FORM1がタスクバーに表示するようになりました。

以上で、この質問は終了されていただきます。

みなさんのアドバイス、ありがとうございます。

編集 履歴 (0)

hidoriさん、flied_onionさん
返事遅くて、申し訳ございません。

hidoriさん と flied_onionさんのやりかたは、
AddOwnedFormを使わなくて、自分でFROM2とFORM3を制御しますね。
最小化と閉じる処理は大丈夫だと思いますが、アクティブ処理はなかなか難しいみたいです。
仕様の説明について、また漏れ点がありますが、
1、最小化はFORM1だけできます。FORM2とFORM3は最小化最大化ボタンを表示しません。
2、FORM1を閉じる時、FORM2とFORM3を一緒に閉じますが、FORM2またはFORM3を閉じる時に、
  FORM1は閉じません。
以上の二点は大丈夫です。
3、FORM1、FORM2、FORM3の中に一つのフォームがアクティブ(一番前に表示)になった時、
  別の二つフォームは2番目と3番目に表示したいです。
これがちょっと難しいです。
例:FORM1のACTIVEDのイベントにFORM2とFORM3を表示するように書いたら、
FORM1をクリックし続けて移動する時、フォーカスがFORM1から離れて、FORM2またはFORM3に行きました。

今はとりあえず、AddOwnedFormを使って続けて、
偽のメインフォームFORM4を追加して、VISIBLE = FALSE、SHOWINTASKBAR = FALSEで設定して、
FORM4.AddOwnedForm(FORM1);
FORM4.AddOwnedForm(FORM2);
FORM4.AddOwnedForm(FORM3);
最小化処理と閉じる処理は自分で制御して、大体の仕様は実現することができますが、
また一つの不具合が残っています。
FORM1のSHOWINTASKBARだけTRUEに設定して、別のフォームはFALSEに設定したら、
実行する時、タスクバーにはなにも表示してません。
フォーカスをFORM1から離れて、FORM1へ戻る時に、FORM1がタスクバーに表示するようになりました。
=。= 難しいなぁ。。。。

編集 履歴 (0)

一例として、以下の様にコンストラクタでForm1を受け取り、
イベントで処理するというやり方もあるかと思います。

あくまでサンプルなので不完全です(たとえば Form2だけ最小化してForm1をアクティブにしても出てこないとか)。

ちなみに②については、Form1がメインフォームになっていれば放っておいてもそうなるんじゃないかと思います。

Form2.cs ( using System.Runtime.InteropServices;を追加してください。)

namespace WindowsFormsApplication1 {
    public partial class Form2 : Form {

        private Form2() {
            InitializeComponent();
        }

        public Form2(Form1 f) {
            f.Resize += new EventHandler(f_Resize);
            f.FormClosed += new FormClosedEventHandler(f_FormClosed);
            f.Activated += new EventHandler(f_Activated);
        }

        void f_Resize(object sender, EventArgs e) {

            if (WindowState == FormWindowState.Minimized) {
                // 自身が最小化しているがForm1が最小化でないなら通常表示に
                if (sender is Form1) {
                    if (((Form1)sender).WindowState != FormWindowState.Minimized) {
                        WindowState = FormWindowState.Normal;
                    }
                }
            }
            else {
                if (sender is Form1) {
                    if (((Form1)sender).WindowState == FormWindowState.Minimized) {
                        // Form1が最小化されているなら自身を最小化
                        WindowState = FormWindowState.Minimized;
                    }
                }
            }
        }

        void f_FormClosed(object sender, FormClosedEventArgs e) {
            Close();
        }

        [DllImport("user32.dll")]
        private static extern int ShowWindow(IntPtr handle, int command);
        private const int SW_SHOWNA = 0x08; // アクティブ化せずにSHOWする

        void f_Activated(object sender, EventArgs e) {
            ShowWindow(this.Handle, SW_SHOWNA);
        }
    }
}

Form1.cs

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        // ボタンを1つ配置してそのクリックイベントにしてください。
        private void button1_Click(object sender, EventArgs e) {
            Form2 f = new Form2(this);
            f.Show();
        }
    }
}
編集 履歴 (0)

Form1.WndProc() をオーバーライドして Windows メッセージを監視すれば、Form1 の「最大化」「復元」などを検知することが出来るはずなので、そこで Form2, Form3 の状態を明示的に制御してみてはどうでしょう?

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。