none
VB2008:TabControlのコード追加について RRS feed

  • 質問

  • 初心者でつまづいております。VB2008+WindowsXP Proでの現象です。

     ソリューションにSub Mainを持つスタートアッププロジェクト「A」と、フォーム「B」を定義したクラスライブラリプロジェクト「C」があります。

     「B」のフォームはデザイナでMenuStripを貼り付けてあり、プロジェクト「A」から「C」を参照設定し、「A」のSub Mainでフォーム「B」を使う際、タブコントロールをコードで追加していますが、希望の動作となりません。

        Sub Main()

            Dim hogeForm As New ClassLibrary1.TmpForm    '「C」で定義したフォーム「B」
            Dim hogeTab As New TabControl    '追加したいタブコントロール

            With hogeTab
                .Visible = True
                .TabPages.Add("1")
                .TabPages.Add("2")
    ~ 中略 ~
                .Dock = DockStyle.Fill    'タブコントロールをフォームいっぱいに表示したい
            End With

            hogeForm.Controls.Add(hogeTab)

            Application.Run(hogeForm)

        End Sub

     タブコントロールは追加されるのですが、メニューストリップの背後にタブの選択部分が入り込み、使用できない状態になっており、途方にくれています。

     フォーム「B」はあちこちで再利用することを前提としており、デザイナでタブコントロールを貼り付けることが出来ない状況です。

     知見のある方おられましたらアドバイスの程宜しくお願い申し上げます。

    2010年8月31日 18:52

回答

  • 試したところ、FormのControls.Add で追加した順番ではなく、逆順に Dock の値が適用されていますね。後から追加されたTabControlがMenuStripより先に全体に貼り付いてしまうから、タブ選択部分がMenuStripの下に隠れてしまっています。

    FormのControlsプロパティはControlCollection型で、このControlCollectionにはコレクション内のコントロールのインデックスを操作するSetChildIndexメソッドがあります。このメソッドを使って、TabControlのインデックスを変更すればいいです。

    コードを載せておきます。C#のコードですが、VBでもやり方は同じです。

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    
    Form1 form = new Form1();
    
    TabControl tab = new TabControl();
    tab.TabPages.Add("foo");
    tab.TabPages.Add("bar");
    tab.Dock = DockStyle.Fill;
    form.Controls.Add(tab);
    form.Controls.SetChildIndex(tab, 0);//MenuStripより前にする
    
    Application.Run(form);
    
    


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答としてマーク 小畑 2010年9月1日 3:14
    2010年8月31日 21:23
  •  すこし時間が取れました故、継承フォームを試してみましたが、デザイナ上でMenuStripのある継承フォームにタブコントロールを貼り付け、DockをFillにした瞬間、やはりタブ選択部分がメニューストリップの背後に隠れてしまいました:P

    なるほど、そうなりますか…。
    では、こうすればどうでしょうか。

    1.継承元フォームに MenuStrip と Panel を配置し、Panel の Dock プロパティを Fill に、Modifiers プロパティを protected に設定する。
    2.1のフォームを継承したフォームを作る。
    3.2で作ったフォームで Panel の上に TabControl を配置し、Dock プロパティを Fill にする。

    ポイント:
    ・Modifiers プロパティを変えないと、2のフォームでうまく配置できません。
    ・継承元フォームで Panel を配置して、継承先フォームで自由に利用できるエリアとして提供することを狙っています。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク 小畑 2010年9月1日 16:37
    2010年9月1日 14:34
    モデレータ

すべての返信

  • 試したところ、FormのControls.Add で追加した順番ではなく、逆順に Dock の値が適用されていますね。後から追加されたTabControlがMenuStripより先に全体に貼り付いてしまうから、タブ選択部分がMenuStripの下に隠れてしまっています。

    FormのControlsプロパティはControlCollection型で、このControlCollectionにはコレクション内のコントロールのインデックスを操作するSetChildIndexメソッドがあります。このメソッドを使って、TabControlのインデックスを変更すればいいです。

    コードを載せておきます。C#のコードですが、VBでもやり方は同じです。

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    
    Form1 form = new Form1();
    
    TabControl tab = new TabControl();
    tab.TabPages.Add("foo");
    tab.TabPages.Add("bar");
    tab.Dock = DockStyle.Fill;
    form.Controls.Add(tab);
    form.Controls.SetChildIndex(tab, 0);//MenuStripより前にする
    
    Application.Run(form);
    
    


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答としてマーク 小畑 2010年9月1日 3:14
    2010年8月31日 21:23
  • ほかには、TabControl に対して SendToBack メソッドを呼び出すことです。
    ただし、最背面で問題がある場合は、SetChildIndex メソッドで細かく指定するしかないと思われます。

    あとは、B というフォームから派生したフォームを作るとかも良いでしょう。
    この場合、デザイナを利用できます。
    (新規追加の際に、継承した Windows フォームといったようなアイテムを選ぶ)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年8月31日 21:30
    モデレータ
  • 各位 ご回答ありがとうございました。大変参考になりました。

    SetChildIndexと、Azulean様の継承フォームの方法、双方試してみて、影響のないものでいこうと思います。

     

    2010年9月1日 3:18
  • あとは、B というフォームから派生したフォームを作るとかも良いでしょう。
    この場合、デザイナを利用できます。
    (新規追加の際に、継承した Windows フォームといったようなアイテムを選ぶ)

     Azulean 様 アドバイス頂きありがとうございました。

     すこし時間が取れました故、継承フォームを試してみましたが、デザイナ上でMenuStripのある継承フォームにタブコントロールを貼り付け、DockをFillにした瞬間、やはりタブ選択部分がメニューストリップの背後に隠れてしまいました:P

     SendToBackとSetChildIndexでどうにかしたいと思います。ありがとうございました。

    2010年9月1日 10:43
  •  すこし時間が取れました故、継承フォームを試してみましたが、デザイナ上でMenuStripのある継承フォームにタブコントロールを貼り付け、DockをFillにした瞬間、やはりタブ選択部分がメニューストリップの背後に隠れてしまいました:P

    なるほど、そうなりますか…。
    では、こうすればどうでしょうか。

    1.継承元フォームに MenuStrip と Panel を配置し、Panel の Dock プロパティを Fill に、Modifiers プロパティを protected に設定する。
    2.1のフォームを継承したフォームを作る。
    3.2で作ったフォームで Panel の上に TabControl を配置し、Dock プロパティを Fill にする。

    ポイント:
    ・Modifiers プロパティを変えないと、2のフォームでうまく配置できません。
    ・継承元フォームで Panel を配置して、継承先フォームで自由に利用できるエリアとして提供することを狙っています。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク 小畑 2010年9月1日 16:37
    2010年9月1日 14:34
    モデレータ
  • なるほど、そうなりますか…。
    では、こうすればどうでしょうか。

     試してみました。きちんときれいにDockされました。こんな方法もあるんですね :-)

     汎用画面はコードで画面生成しますが、特殊画面をコード生成するかデザイナ中心にするかも含めてよく検討します。

     情報頂きありがとうございました。

    2010年9月1日 16:37
  • tabcontrolを「切り取り」して、再貼り付けしたら、いけますよ。
    2013年11月2日 11:00
  • tabcontrolを「切り取り」して、再貼り付けしたら、いけますよ。

    念のために指摘しておきますと、この事例は”フォーム「B」はあちこちで再利用することを前提としており、デザイナでタブコントロールを貼り付けることが出来ない状況”という前提条件が質問文に記載されていますので、今後回答・助言される際は質問者が設定した前提も気にしてみてください。
    (3 年前の投稿なのでこれ以上は広がらないと思いますが…)

    ところで、切り取りして貼り付けると、イベントハンドラが外れることはご存知でしょうか?
    たとえば、Selected イベントにデザイナからイベントハンドラを設定している状態で TabControl を切り取り、貼り付けするとイベントハンドラの登録が消えることになります。
    コントロールの前後関係を操作するためであれば、コントロールを選択して右クリックして最前面に移動、最背面に移動を選択するか、ドキュメントアウトラインというウィンドウを使うことを検討していただいた方がよさそうです。

    2013年11月2日 11:28
    モデレータ