.NETプログラミング研究 第69号
┏第69号━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ .NETプログラミング研究 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
──<メニュー>───────────────────────
■.NET Tips
・FlowLayoutPanelコントロール
-AnchorとDockプロパティ
-FlowBreakプロパティ
-コントロールの順番を変更する
・TableLayoutPanelコントロール
-TableLayoutPanelコントロールにコントロールを追加する
-子コントロールの位置の取得(GetCellPositionと
GetPositionFromControlの違い)
-Controls.Addで指定した位置に配置できない?!
-ColumnCountとRowCountは実際のTableLayoutPanelの列数と行数を
表すものではない
───────────────────────────────
───────────────────────────────
■.NET Tips
───────────────────────────────
今回は、.NET Framework 2.0から追加されたWindowsアプリケーショ
ンのコントロール、FlowLayoutPanelとTableLayoutPanelコントロー
ルについて説明します。これらのコントロールはコンテナとして働き、
複数のコントロールを整列させたい時に使用します。
───────────────────────────────
●FlowLayoutPanelコントロール
FlowLayoutPanelコントロールについて、MSDNでは次のように説明さ
れています。
「FlowLayoutPanel コントロールは、その内容を水平または垂直のフ
ロー方向に整列させます。内容は次の行または次の列に折り返すこと
ができます。また、折り返さずにクリップすることもできます。」
[URL]FlowLayoutPanel コントロール (Windows フォーム)
http://msdn2.microsoft.com/ja-jp/library/zah8ywcc.aspx
言葉で説明するより、実際に使ってみるのが一番早いというわけで、
次のURLにFlowLayoutPanelを使ったサンプル(FlowLayoutPanel1.exe)
を置いておきます。(ソースコードも置いておきます。)実行するに
は、.NET Framework 2.0がインストールされている必要があります。
(VB.NETのコードはありません。また、これらのファイルは、1ヶ月
ほどで削除します。)
[URL]サンプル「FlowLayoutPanel1.exe」
http://dobon.net/vb/dotnet/control/files/FlowLayoutPanel1.exe
[URL]ソース
http://dobon.net/vb/dotnet/control/files/FlowLayoutPanel1.zip
このサンプルは、フォームにFlowLayoutPanelコントロールを配置し、
DockプロパティをFillとし、Buttonコントロールを15個配置したもの
です。フォームの大きさを変更させると、Buttonコントロールが右端
で折り返されて整列することが確認できるでしょう。
FlowLayoutPanelコントロールには、重要なプロパティとして、
FlowDirectionとWrapContentsがあります。FlowDirectionプロパティ
は、整列の方向を指定するために使用します。また、WrapContentsプ
ロパティは、FlowLayoutPanelに配置したコントロールを折り返して
整列させるかを指定するために使用します。
サンプル「FlowLayoutPanel1.exe」では、FlowDirectionと
WrapContentsプロパティを試すため、メニューを使って
FlowLayoutPanelコントロールのFlowDirectionとWrapContentsプロパ
ティの値を簡単に変更できるようになっています。実際にこれらの値
を変更させるとどのように変化するのかを試してみてください。
★AnchorとDockプロパティ
FlowLayoutPanelコントロールに配置された子コントロールは、
AnchorとDockプロパティに、通常とは少し異なる特別な役割が与えら
れています。これに関しては、MSDNで説明されています。
[URL]方法 : FlowLayoutPanel コントロールで子コントロールを固定
およびドッキングする
http://msdn2.microsoft.com/ja-jp/library/ms171633.aspx
これを実際に確認するためのサンプルが次に紹介する「
FlowLayoutPanel2.exe」です。
[URL]サンプル「FlowLayoutPanel2.exe」
http://dobon.net/vb/dotnet/control/files/FlowLayoutPanel2.exe
[URL]ソース
http://dobon.net/vb/dotnet/control/files/FlowLayoutPanel2.zip
このサンプルでは、様々な大きさのButtonコントロールが
FlowLayoutPanelコントロールに配置されています。さらに、Button
コントロールを右クリックすることにより、コンテキストメニューが
表示され、ButtonのAnchorとDockプロパティを簡単に変更できるよう
になっています。
例えば、FlowLayoutPanelのFlowDirectionプロパティがLeftToRight
の時、ButtonのAnchorをTopにすると、Buttonはその列の一番上に配
置されるようになります。AnchorをBottomにすると、逆に一番下に配
置されます。TopとBottom両方を指定すると、列の幅いっぱいに広が
ります。Noneでは中央に配置されます。LeftとRightは、この場合は、
関係ありません。
Dockプロパティも同様に、Topで一番上、Bottomで一番下、Fillで幅
いっぱいに配置されるようになります。
★FlowBreakプロパティ
さらにこのサンプルでは、FlowLayoutPanelコントロールに配置され
たコントロールのFlowBreakプロパティを変更することもできます。
FlowBreakプロパティをTrueとすることにより、そのコントロールの
次で強制的に折り返して整列されるようになります。
FlowBreakプロパティはVS 2005のデザイナのプロパティウィンドウで
変更することができますが、実際のコントロールのクラスに
FlowBreakというプロパティが存在するわけではありません。実際に
はFlowLayoutPanelコントロールのSetFlowBreakメソッドを使って指
定します。例えば、FlowLayoutPanelコントロール「
FlowLayoutPanel1」に配置されたButtonコントロール「Button1」の
FlowBreakプロパティをTrueにするには、次のようにします。
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
FlowLayoutPanel1.SetFlowBreak(Button1, True)
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
FlowLayoutPanel1.SetFlowBreak(Button1, true);
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
また、Button1のFlowBreakの状態を調べるには、FlowLayoutPanel.
GetFlowBreakメソッドを使います。
★コントロールの順番を変更する
FlowLayoutPanelに配置されるコントロールの順番は、
FlowLayoutPanel.Controlsコレクションの順番で決まるようです。よ
って、コントロールの順番を変更するには、変更するコントロール以
降のコントロールをすべて削除してから、追加しなおさなければなら
ないようです。
サンプル「FlowLayoutPanel2.exe」で、コントロールを先頭に移動す
る例を紹介しています。以下にその抜粋を示します。currentButton
というコントロールを移動させています。
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
'移動先の位置
Dim newIndex As Integer = 0
Dim conts As New List(Of Control)
FlowLayoutPanel1.SuspendLayout()
'flowLayoutPanel1内のコントロールを記憶&削除
Dim i As Integer
For i = FlowLayoutPanel1.Controls.Count - 1 To newIndex Step -1
If Not FlowLayoutPanel1.Controls(i).Equals(currentButton) Then
conts.Insert(0, FlowLayoutPanel1.Controls(i))
End If
FlowLayoutPanel1.Controls.RemoveAt(i)
Next i
'移動するコントロールがまだあるときは、削除
If FlowLayoutPanel1.Controls.IndexOf(currentButton) > -1 Then
FlowLayoutPanel1.Controls.Remove(currentButton)
End If
'移動するコントロールを追加
FlowLayoutPanel1.Controls.Add(currentButton)
'残りのコントロールを追加
FlowLayoutPanel1.Controls.AddRange(conts.ToArray())
FlowLayoutPanel1.ResumeLayout()
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
//移動先の位置
int newIndex = 0;
List<Control> conts = new List<Control>();
flowLayoutPanel1.SuspendLayout();
//flowLayoutPanel1内のコントロールを記憶&削除
for (int i = flowLayoutPanel1.Controls.Count - 1; i >= newIndex; i--)
{
if (!flowLayoutPanel1.Controls[i].Equals(currentButton))
conts.Insert(0, flowLayoutPanel1.Controls[i]);
flowLayoutPanel1.Controls.RemoveAt(i);
}
//移動するコントロールがまだあるときは、削除
if (flowLayoutPanel1.Controls.IndexOf(currentButton) > -1)
flowLayoutPanel1.Controls.Remove(currentButton);
//移動するコントロールを追加
flowLayoutPanel1.Controls.Add(currentButton);
//残りのコントロールを追加
flowLayoutPanel1.Controls.AddRange(conts.ToArray());
flowLayoutPanel1.ResumeLayout();
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
───────────────────────────────
●TableLayoutPanelコントロール
TableLayoutPanelコントロールは、まるでHTMLのTABLEタグのような
コントロールと言えば分かりやすいでしょうか。MSDNでは、次のよう
に説明されています。
TableLayoutPanel コントロールは、実行時に比例的なサイズ変更機
能を提供するため、フォームのサイズ変更に合わせてレイアウトを滑
らかに変更できます。このため、TableLayoutPanel コントロールは、
データ入力フォームやアプリケーションのローカライズなどに適して
います。
[URL]TableLayoutPanel コントロール (Windows フォーム)
http://msdn2.microsoft.com/ja-jp/library/3a1tbfwd.aspx
MSDNの「TableLayoutPanel コントロールの推奨される手順」では、
TableLayoutPanelコントロールをどのようなケースで使用し、どのよ
うなケースでは使用すべきではないかが説明されています。
[URL]TableLayoutPanel コントロールの推奨される手順
http://msdn2.microsoft.com/ja-jp/library/ms171689.aspx
これによると、親フォームのサイズ変更や、ローカリゼーションに伴
いコントロールに表示するテキストの長さが変更されるようなケース
でTableLayoutPanelコントロールを使うのが有効であるということで
す。逆にTableLayoutPanelコントロールのDockプロパティをFillにす
る、TableLayoutPanelに別のTableLayoutPanelを配置して入れ子にす
る、TableLayoutPanelを配置したフォームを継承したフォームでさら
にコントロールを追加する、列がレベルとテキストの2つしかない単
純なフォームで使用するなどといったことは推奨されていません。こ
のような推奨事項を守る限り、TableLayoutPanelコントロールの使い
道はごく限られそうです。(巷に出回っているTableLayoutPanelコン
トロールのサンプルは、これらの推奨事項を無視しているものがほと
んどですので、注意が必要です。)
TableLayoutPanelコントロールの使い方は、MSDNの「
TableLayoutPanel コントロール (Windows フォーム)」などに詳しい
です。しかしほとんどがVisual Studioのフォームデザイナを使った
場合の説明であり、コードによる説明はほとんどありません。そこで
ここでは、実行時に行うにはどうするかを中心に説明します。
なお、TableLayoutPanelコントロールの実際の挙動を確かめるための
サンプル(TableLayoutPanel1.exe)も用意しました。
[URL]サンプル「TableLayoutPanel1.exe」
http://dobon.net/vb/dotnet/control/files/TableLayoutPanel1.exe
[URL]ソース
http://dobon.net/vb/dotnet/control/files/TableLayoutPanel1.zip
★TableLayoutPanelコントロールにコントロールを追加する
MSDNでは、フォームデザイナを使った方法が次のページなどで説明さ
れています。
[URL]チュートリアル : TableLayoutPanel を使用した Windows フォー
ム上のコントロールの配置
http://msdn2.microsoft.com/ja-jp/library/w4yc3e8c.aspx
[URL]チュートリアル : データ入力用のサイズ変更可能な Windows
フォームの作成
http://msdn2.microsoft.com/ja-jp/library/991eahec.aspx
TableLayoutPanelコントロール内にコントロールを配置するには、
Controls.Addメソッドを使います。このメソッドではコントロールを
挿入するセルの位置を指定することができます。
[URL]TableLayoutControlCollection.Add メソッド
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.tablelayoutcontrolcollection.add.aspx
TableLayoutPanelコントロールは一つのセルに一つのコントロールし
か入れることができません(セルにPanelを配置し、そこに複数のコ
ントロールを配置することはできます)。よって指定した挿入位置に
すでにコントロールがあるときは、それ以降のコントロールが押し出
されるように次のセルに移動します。
Controls.Addでは挿入位置を指定しなくても大丈夫です。挿入位置を
指定しなかった場合は、右上の空いているセルから順番に配置されま
す。((-1, -1)を指定したことになります。)
すべてのセルがすでに埋まっている時に新しいコントロールを追加し
た時の動作は、TableLayoutPanel.GrowStyleプロパティにより異なり
ます。GrowStyleプロパティがAddRowsのとき(デフォルト)は行を拡
張し、AddColumnsのときは列を拡張します。FixedSizeのときは、例
外ArgumentExceptionがスローされます。
次の例では、insertRowとinsertColumnで指定された位置にButtonコ
ントロールを追加しています。挿入位置にコントロールがあるか調べ、
無いときのみ挿入しています。
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
'挿入位置
Dim insertRow As Integer = 0
Dim insertColumn As Integer = 0
If TableLayoutPanel1.GetControlFromPosition( _
insertColumn, insertRow) Is Nothing Then
Dim newButton As New Button()
newButton.Text = "button"
TableLayoutPanel1.Controls.Add( _
newButton, insertColumn, insertRow)
End If
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
//挿入位置
int insertRow = 0;
int insertColumn = 0;
if (tableLayoutPanel1.GetControlFromPosition(
insertColumn, insertRow) == null)
{
Button newButton = new Button();
newButton.Text = "button";
tableLayoutPanel1.Controls.Add(newButton, insertColumn, insertRow);
}
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
サンプル「TableLayoutPanel1.exe」でも、メニューから簡単に
Buttonコントロールの追加や、TableLayoutPanel.GrowStyleプロパテ
ィの変更を行うことができますので、お試しください。
★子コントロールの位置の取得(GetCellPositionと
GetPositionFromControlの違い)
TableLayoutPanelに配置されたコントロールが占有しているセルの位
置を取得する方法としてTableLayoutPanelクラスには、GetColumn、
GetRow、GetCellPosition、GetPositionFromControlといったメソッ
ドが用意されています。この内、GetColumn、GetRowと
GetCellPositionは同じですが、これらとGetPositionFromControlは
似ているようで全く異なります。
例えば、列数が十分にあるTableLayoutPanel「tableLayoutPanel1」
に次のように2つのボタンを配置したとします。
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
tableLayoutPanel1.Controls.Add(button1, 0, 0)
tableLayoutPanel1.Controls.Add(button2, 1, 0)
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
tableLayoutPanel1.Controls.Add(button1, 0, 0);
tableLayoutPanel1.Controls.Add(button2, 1, 0);
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
このときは、button1に対してGetCellPositionと
GetPositionFromControlが返す値は同じ(0,0)になります。また、
button2に対しても両者とも(1,0)となります。
さて、さらにbutton3を次のように追加すると、どうなるでしょうか?
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
tableLayoutPanel1.Controls.Add(button3, 0, 0)
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
tableLayoutPanel1.Controls.Add(button3, 0, 0);
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
button3が(0,0)に入ることにより、button1は(1,0)に、button2は(2,
0)に追い出されます。このとき、button1とbutton2に対して
GetPositionFromControlが返す値は(1,0)と(2,0)になりますが、
GetCellPositionが返す値は(0,0)と(1,0)のままです。button3に対し
てGetCellPositionとGetPositionFromControlが返す値は(0,0)ですの
で、GetCellPositionが(0,0)を返すコントロールが2つ存在すること
になります。
つまり、GetPositionFromControlは現在実際にコントロールが占有し
ているセルの位置を返し、GetCellPositionはControls.Add(あるい
はTableLayoutPanel.SetCellPositionメソッド)で指定された値を返
すということになります。位置を指定しないでControls.Addを呼び出
したコントロールに対しては、GetCellPositionは(-1,-1)を返します。
VS2005のフォームデザイナのみでコントロールを配置した場合は
GetCellPositionとGetPositionFromControlは一致すると考えてよさ
そうですが、実行時に配置したコントロールがある場合は、そうなら
ない可能性があることを知っておくべきでしょう。
MSDNには、
「GetPositionFromControl メソッドは、位置が LayoutEngine によ
って決定される場合でも、control の実際の現在位置を返します。」
とありますが、これはこういう意味だったのです。
[URL]TableLayoutPanel.GetPositionFromControl メソッド
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.tablelayoutpanel.getpositionfromcontrol.aspx
★Controls.Addで指定した位置に配置できない?!
上で紹介した例に、次のようにしてもう一つbuttonを追加してみまし
ょう。一体どこに追加されるでしょうか?
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
tableLayoutPanel1.Controls.Add(button4, 1, 0)
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
tableLayoutPanel1.Controls.Add(button4, 1, 0);
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
ちょっと意外ですが、button4は(2,0)の位置、つまりbutton1と
button2の間に挿入されます。つまり、GetCellPositionが(0,0)であ
るbutton1が優先されるようなのです。
それでは、間違いなく指定した位置のセルにコントロールを配置する
にはどうすればいいのかということになると、あまりいい方法が思い
つきません。一つの方法として、次のように実際に配置されている位
置をGetCellPositionが返す位置に強制的に設定してしまってから、
コントロールを追加するやり方が考えられます。
‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
Dim c As Control
For Each c In TableLayoutPanel1.Controls
TableLayoutPanel1.SetCellPosition( _
c, TableLayoutPanel1.GetPositionFromControl(c))
Next c
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
foreach (Control c in tableLayoutPanel1.Controls)
{
tableLayoutPanel1.SetCellPosition(
c,
tableLayoutPanel1.GetPositionFromControl(c));
}
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
★ColumnCountとRowCountは実際のTableLayoutPanelの列数と行数を
表すものではない
これもまた分かりにくい話ですが、TableLayoutPanelのColumnCount
やRowCountプロパティは、実際の列数や行数と一致するとは限りませ
ん。実行時にコントロールをTableLayoutPanelに追加して実際の列数
や行数が拡張された場合でも、ColumnCountやRowCountの値は変更さ
れませんので、実際の列数、行数と違いが出てしまいます。つまり、
これらのプロパティはTableLayoutPanelのGrowStyleプロパティが
FixedSizeの場合のみ実際の列数や行数と必ず一致し、GrowStyleが
AddColumnsまたはAddRowsの場合は、RowCountまたはColumnCountだけ
が実際の列数や行数と必ず一致するということになります。
[URL]TableLayoutPanel.ColumnCount プロパティ
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.tablelayoutpanel.columncount.aspx
それでは実際の列数と行数を取得するにはどのようにすればよいかと
いうと、...これがよく分かりません。TableLayoutPanelに配置され
ているすべてのコントロールの実際の位置をGetPositionFromControl
で取得して、その最大値とColumnCountまたはRowCountの大きい方が
実際の列数または行数であるとする以外の良い方法が今のところ見つ
かりません。
───────────────────────────────
今回、予想外に記事が長くなってしまいましたので、きりが良くない
のですが、続きは次回とさせていただきます。
===============================
■ここで示したコードの多くはまずC#で書き、それを「C# to VB.NET
Translator」でVB.NETのコードに変換し、修正を加えたものです。
[URL]C# to VB.NET Translator
http://authors.aspalliance.com/aldotnet/examples/translate.aspx
■このマガジンの購読、購読中止、バックナンバー、説明に関しては
次のページをご覧ください。
http://www.mag2.com/m/0000104516.htm
■発行人・編集人:どぼん!
(Microsoft MVP for Visual Basic, Oct 2005-Oct 2006)
http://dobon.net
dobon_info@yahoo.co.jp
■ご質問等はメールではなく、掲示板へお願いいたします。
http://dobon.net/vb/bbs.html
■上記メールアドレスへのメールは確実に読まれる保障はありません
(スパム、ウィルス対策です)。メールは下記URLのフォームメール
から送信してください。
http://dobon.net/mail.html
Copyright (c) 2003 - 2006 DOBON! All rights reserved.
===============================



![転職なら[en]社会人の転職情報!転職成功者続出 転職なら[en]社会人の転職情報!転職成功者続出](http://kamogawa.mag2.com/bn/recommend/sya.gif)
![派遣のお仕事探しなら[en]派遣のお仕事情報 派遣のお仕事探しなら[en]派遣のお仕事情報](http://kamogawa.mag2.com/bn/recommend/haken.gif)
![アルバイト探しは[en]本気のアルバイト アルバイト探しは[en]本気のアルバイト](http://kamogawa.mag2.com/bn/recommend/baito.gif)
![就職サイトは[en]学生の就職情報 就職サイトは[en]学生の就職情報](http://kamogawa.mag2.com/bn/recommend/gakusei.gif)
![転職なら[en]転職コンサルタントキャリアを活かした転職に! 転職なら[en]転職コンサルタントキャリアを活かした転職に!](http://kamogawa.mag2.com/bn/recommend/consul.gif)

