- PR -

MDI親フォームのToolBarを切り替えるには?

投稿者投稿内容
high4
会議室デビュー日: 2005/08/23
投稿数: 7
投稿日時: 2005-10-24 18:04
先ほどのコードを投稿した後に気が付いたまどかさんの直前の文書にある、
> 普通にShow、最小化+X、別Form.Showで現れますね。現象も再現します。
でやっとわかりました。
Form A,B,C を Load で Show 後、FormCを最小化、クローズ(実際はHide)、FormAのShow で、おっしゃるとおりFormCが表示されました。
失礼しました。

不思議なことに気が付きました。
先ほどのプログラムをスタート、
FormABCの枠の下の部分を、FormC が十分見えるまで下に引き伸ばす。
FormCを最小化、
FormCのクローズボタンを押す。
消えていますね。
再びFormABCの下枠をちょっと動かしてみる。
HideしたはずのFormCが突然、出現します。

つまり、FormAを表示したからFormCが出現したのではなく、FormCがそもそも正式には消えていないことになります。

なぜでしょうか、わかりません。何か FormC の window の style bit が欠けている状態じゃないかと思うのですが。その辺を探っていけば理由がわかるかもしれません。
以上が悪いニュース。
良いニュースは、この現象は前回述べたVS2005 のコードでは生じませんでした。

追記
----
これはそもそも toolbar の問題は関係していないのではと気が付きました。
VS2003 のコードで toolbar の部分を全部取り除いても、先ほどのFormCがFormABCの枠を動かすと突然出現する症状が出ます。
そうすると、FormC の Closing のときに、 e.Cancel して Hide() するというギアチェンジをしている点に焦点が絞られます。 もし本当にそうなら、後は spy++ を使った推理小説の世界です。



[ メッセージ編集済み 編集者: high4 編集日時 2005-10-24 18:17 ]

[ メッセージ編集済み 編集者: high4 編集日時 2005-10-24 18:19 ]

[ メッセージ編集済み 編集者: high4 編集日時 2005-10-24 18:40 ]

[ メッセージ編集済み 編集者: high4 編集日時 2005-10-24 18:44 ]
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2005-10-24 18:41
high4さん、お世話になります。

high4さんのコードを試してみました。
結果はやはり、同じ現象が再現しました。

high4さんのコードを全くコピーしただけですので、
そちらで再現しないということであれば環境の問題も考えられます。

取り敢えず、再現する方法を以下に示します。

 1. アプリケーションを起動して、同時に開かれるFormA、FormB、FormCを
  一先ず閉じます。
 2. 「A1」ボタンより、FormAを開き、最小化して閉じます。
 3. 「A2」ボタンより、FormBを開きます。
 4. すると、FormBの陰にFormAが最小化された状態で現れます。
 5. FormAをクリックしてもアクティベートされていないように見えます。
 6. FormAを最大化してもFormABCとドッキングされず、親フレーム内で
  最大化されたように見えます。

もし、上記操作でも再現しないのであれば、

環境の違いを確認したいのですが、どこを確認すれば良いのか
ご教授お願いできますでしょうか。

よろしくお願いします。
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-10-24 23:20
追加情報です。

特に最小化は関係ないようです。
標準状態でも、XボタンのあとVisible=Trueで再現しました。
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-10-24 23:28
続けざまにすいません。

Closingイベントやe.Cancelも関係ないようです。Visible=Falseでも再現しました。
また再表示する際に
x.MDIParent=Nothing
x.MDIParent=Me
としても無駄でした。
high4
会議室デビュー日: 2005/08/23
投稿数: 7
投稿日時: 2005-10-25 00:27
この投稿がこのスレッドに対する4回目になりますが、多分これが最後です。
VS2003 の前回のコードの FormABC_Load を次のようにして実行してみてください。
コード:
		private void FormABC_Load(object sender, System.EventArgs e)
		{
			toolBarA.Visible = false;
			toolBarB.Visible = false;
			toolBarC.Visible = false;

			ShowFormA();
			ShowFormB();
			ShowFormC();

			// この2行を追加
               frmC.WindowState = FormWindowState.Minimized;
			frmC.Hide();
		}


frmC は Hide されるはずが、されません。
では、
frmC.WindowState = FormWindowState.Minimized;
の行をコメントアウトして実行すると、正しく Hide されています。
つまり、今回の問題のポイントは
「最小化設定した window に Hide() を命令しても Hide されない」という症状にのみ絞られます。
ですから、FormA,B,C の Closing の部分を訂正してやればよいことになります。
ちなみに VS2005 では最小化していても正しく Hide されます。

では、FormABC_Loadをオリジナルに戻してから、FormA,B,C の Closing を次のように書き換えてください。
コード:
		private void FormA_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			e.Cancel = true;
			this.WindowState = System.Windows.Forms.FormWindowState.Normal;	// この行を追加	
			Hide();
		}


実行しても、前回、あぶぼんさが述べたチェック手順でも症状はでません。つまり正しく動いています。
この方法の欠点があります。
1. Closing の際、一瞬、ウィンドゥがResizeされるのが見える。
2. 最小化->クローズしたFormA,B,C をボタンから Show() すると、最小化した状態ではなく、ノーマルな大きさで出現する。

2の問題は、擬似的に直前の状態を保持しておいて、Show の命令のときに強制するとか、色々な方法が考えられるでしょうし、
本当は前回に言った window の状態の bit data を追いかければもっと根本的な解決があるかもしれませんし、徒労に終わるかもしれません。
あれこれ考えるうちに VS2005 で置き換えること検討されるようになるかもしれません。
私は、VS2005 世代の人間ですから後者です。
では頑張ってください。
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2005-10-26 21:25
みなさん、たくさんの意見を有り難うございました。

引用:

1. Closing の際、一瞬、ウィンドゥがResizeされるのが見える。


Hide()した後にNormalを設定しても良いようです。

基本的にVisible=falseになっているフォームは全てNormalになって
いるように見えますが、

やはり、明示的に設定してやらないと件の障害が発生します。

引用:

2. 最小化->クローズしたFormA,B,C をボタンから Show() すると、最小化した状態ではなく、ノーマルな大きさで出現する。


いろいろ、試みましたがいずれもうまくいきません。

Hide()中にNormalを設定すると、サイズの情報が失われます。
その他、表示面での問題があり、結局、この方法は不採用です。

また、別スレッドにしようかと思っていますが、
システムの使用上、ClosingのタイミングでアクティブなMDI子ウィンドウを
最背面に持っていくようにしようかと思っています。

しかし、また、問題に直面してしまいました。

SendToHide()で最背面に持っていくのは簡単にできましたが、
前面に出てきたフォームがアクティブになりません。

Zオーダーが取れないようなのでどのフォームをアクティブにすれば
良いか分からず困っています。

今日は帰る時間が迫っているので乱文で済みませんでした。
ジブ
大ベテラン
会議室デビュー日: 2005/09/22
投稿数: 135
投稿日時: 2005-10-28 20:22
クローズボタンで閉じないのもひどいので、とりあえずHideするものを作ってみました。

基本的に子フォームが別の子ファームを制御しようとしていることに問題があって
親フォームが制御すれば大丈夫だろうとやってみました。

簡単のためInterfaceを定義しといて
コード:
Public Interface IhaveToolbar
    ReadOnly Property ToolBar() As ToolBar
End Interface



さて、まず子フォーム

コード:
    Implements IhaveToolbar
    Public ReadOnly Property ToolBar() As System.Windows.Forms.ToolBar Implements IhaveToolbar.ToolBar
        Get
            ToolBar = ToolBar1
        End Get
    End Property



子フォームでは、私は親に渡せるToolbarを持っていますよと言っているだけで
特に何もしていません。

さて親フォームの方には少し工夫をします。

Panel1をDockStyle.Topでおいて、
そのPanel1の上にPanel2をDockStyle.Leftで置いて、ここに子フォームを開くためのToolBar1を配置。
もうひとつPanel1の上にPanel3をDockStyle.Fullで置いて、子フォーム固有のツールバー用にする。

そして
コード:
    Private WithEvents formA As formA
    Private WithEvents formB As formB
    Private WithEvents formC As formC

    Private _MdiChildren As New System.Collections.ArrayList
    Private _curForm As Form

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        formA = New formA
        formA.MdiParent = Me
        formA.Text = "A"
        formA.Show()
        _MdiChildren.Add(formA)

        formB = New formB
        formB.MdiParent = Me
        formB.Text = "B"
        formB.Show()
        _MdiChildren.Add(formB)

        formC = New formC
        formC.MdiParent = Me
        formC.Text = "C"
        formC.Show()
        _MdiChildren.Add(formC)

    End Sub


    Private Sub Form1_MdiChildActivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.MdiChildActivate

        'ToolBarの処理
        SuspendLayout()
        If Not _curForm Is Nothing Then
            If TypeOf _curForm Is IhaveToolbar Then
                CType(_curForm, IhaveToolbar).ToolBar.Parent = Nothing
            End If
        End If
        _curForm = Me.ActiveMdiChild
        If Not _curForm Is Nothing Then
            If TypeOf _curForm Is IhaveToolbar Then
                CType(_curForm, IhaveToolbar).ToolBar.Parent = Panel3
            End If
        End If
        ResumeLayout()

    End Sub


    Dim _forceClose As Boolean = False
    Private Sub MdiChild_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles formA.Closing, formB.Closing, formC.Closing
        If _forceClose Then Exit Sub

        Dim form As Form = sender
        form.Hide()
        e.Cancel = True
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        _forceClose = True
        For Each child As Form In _MdiChildren
            If TypeOf child Is IhaveToolbar Then
                CType(child, IhaveToolbar).ToolBar.Parent = child
            End If
            child.Hide()
        Next
        e.Cancel = False
    End Sub

    Private Sub ToolBar1_ButtonClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolBarButtonClickEventArgs) Handles ToolBar1.ButtonClick
        Dim form As Form = _MdiChildren(ToolBar1.Buttons.IndexOf(e.Button))
        form.Show()
        form.Activate()

    End Sub



これだと、ちらつきはなんともならんですが、多少はましな気がします。
ジブ
大ベテラン
会議室デビュー日: 2005/09/22
投稿数: 135
投稿日時: 2005-10-28 21:03
あらら C#.NETでしたね。

ごめんなさい。

スキルアップ/キャリアアップ(JOB@IT)