┏第66号━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃         .NETプログラミング研究         ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ──<メニュー>─────────────────────── ■.NET Tips ・ToolStrip、ToolStripContainerコントロールとは? ・ToolStripとToolStripContainerコントロールの基本的な使い方 ・ToolStripContainerの代わりにToolStripPanelを使う ・MenuStripやStatusStripを移動できるようにする ・同じ行にToolStripが2つ並ばないようにする ・ToolStripPanelにあるToolStripの位置をプログラムで変更する ・ToolStripとToolStripItemの位置を保存、復元する ・特定のToolStripを指定したToolStripPanelにドッキングできない  ようにする ─────────────────────────────── ─────────────────────────────── 今更ですが、今回から.NET Framework 2.0の新機能を幾つか紹介させ ていただきます。今回は、ToolStripとToolStripContainerコントロー ルについて説明します。 ─────────────────────────────── ─────────────────────────────── ■.NET Tips ─────────────────────────────── ●ToolStrip、ToolStripContainerコントロールとは? ToolStripは、.NET Framework 2.0で新しく追加されたWindowsアプリ ケーションのコントロールです。これは、今までのToolBarコントロー ルの代わりに使用することのできるコントロールで、ToolBarよりも 機能が大幅に増えています。Microsoft Office XPのツールバーのよ うなコントロールといえば分かりやすいでしょう。 ToolStripコントロールは、ToolStripContainerコントロールと共に 使用すると、さらに便利です。Microsoft Office XPのツールバーは、 ドラッグ&ドロップによりユーザーが自由に位置を変更することがで きますが、ToolStripContainerコントロールを使えば、これと同じこ とを実現できます(ただし、現在ツールバーのあるフォームから分離 させて、新しいフォームにすることはできません)。 また、ToolStripから派生したMenuStripとStatusStripコントロール は、今までのMainMenuとStatusBarコントロールの代わりに使うこと ができ、もちろん機能がかなり増えています。しかも ToolStripContainerコントロールを使えば、ToolStrip同様、ユーザー が好きな位置に移動できるようになります。 使ってみればすぐに分かるようなつまらない説明は省略し、とりあえ ず使ってみることにしましょう。本来ならばToolStripコントロール の説明をしてからToolStripContainerコントロールの説明に移るべき ですが、それでは面白くないので、いきなりToolStripと ToolStripContainerコントロールを共に使った例から紹介します。 [URL]ToolStrip コントロール (Windows フォーム) http://msdn2.microsoft.com/ja-jp/library/5daaw6hf.aspx ─────────────────────────────── ●ToolStripとToolStripContainerコントロールの基本的な使い方 Microsoft Visual Studio 2005のフォームデザイナを使って、 ToolStripとToolStripContainerコントロールを使う基本的な方法を 順を追って説明します。 1.Windowsアプリケーションのプロジェクトを作成し、フォームに ToolStripContainerコントロールを配置します(ここでは、名前を「 ToolStripContainer1」とします)。ToolStripContainerコントロー ルは、ツールボックスの「メニューとツールバー」と「すべての Windowsフォーム」にあります。 2.ToolStripContainer1のDockプロパティをFillとします。(または、 ToolStripContainerコントロールを配置した時に表示される「 ToolStripContainerタスク」の「フォームの四辺にドッキング」をク リックしても同じことができます。) 3.デフォルトでは、ToolStripContainer1の四辺のすべてにToolStrip コントロールを配置できるようになっています。ToolStripの配置を 許可しない辺を指定するには、TopToolStripPanelVisible、 BottomToolStripPanelVisible、LeftToolStripPanelVisible、 RightToolStripPanelVisibleの内適当なものをFalseにします。( ToolStripContainerコントロールを配置した時に表示される「 ToolStripContainerタスク」の「パネルの表示状態」でチェックを外 しても同じことができます。) 4.ToolStripコントロールを配置するための場所を空けるために、 ToolStripContainer1の上下左右に表示される内側に向いた矢印(3. で無効にした辺は表示されません)をクリックします。(はじめは、 一番上が空いています。)空いた場所にToolStripコントロール( MenuStripやStatusStripコントロールも含む)を配置します。 ToolStripコントロールを複数配置する場合は、ToolStripコントロー ル配置後、さらに矢印をクリックし、場所を空けます。なお、 ToolStripContainerの上下左右のパネルには、ToolStripとその派生 クラスしか配置できません。それ以外のコントロールを配置しようと すると、ToolStripContainerの中央のContentPanelに配置されてしま います。 5.配置したToolStripコントロールをクリックして、ボタンやコンボ ボックス等を追加します。 このように、VS2005のフォームデザイナを使えば、非常に簡単です。 これと同じことをコードで行う方法を次に示します。ここではこのコー ドがフォームのクラス内に書かれているものとし、OnLoadメソッドで ToolStripContainerとToolStripの作成と配置を行っています。 ToolStripはToolStripContainerの上部に1つだけ追加し、ToolStrip にはボタンを1つだけ追加しています。また、ToolStripContainerの 右側にはToolStripが移動できないようにしています(左と下には移 動できる)。(なお、このコードを実行するには、「Save.bmp」が必 要です。画像がない場合は、「表示する画像の設定」の部分を削除し てください。) ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ Private toolStripContainer1 As ToolStripContainer Private toolStrip1 As ToolStrip Private toolStripButton1 As ToolStripButton Protected Overrides Sub OnLoad(ByVal e As EventArgs) MyBase.OnLoad(e) 'ToolStripContainerの作成 toolStripContainer1 = New ToolStripContainer() 'フォームいっぱいに広げる toolStripContainer1.Dock = DockStyle.Fill '右端だけドッキングできないようにする toolStripContainer1.RightToolStripPanelVisible = False 'ToolStripの作成 toolStrip1 = New ToolStrip() 'ToolStripButtonの作成 toolStripButton1 = New ToolStripButton() '画像と文字列を表示する toolStripButton1.DisplayStyle = _ ToolStripItemDisplayStyle.ImageAndText '表示する画像の設定 toolStripButton1.Image = New Bitmap("Save.bmp") toolStripButton1.ImageTransparentColor = _ System.Drawing.Color.Magenta '表示する文字列の設定 toolStripButton1.Text = "保存" 'クリックされた時のイベントハンドラ AddHandler toolStripButton1.Click, _ AddressOf toolStripButton1_Click 'toolStrip1にアイテムを追加 toolStrip1.Items.Add(toolStripButton1) 'toolStripContainer1の上にtoolStrip1を追加 toolStripContainer1.TopToolStripPanel.Join(toolStrip1) 'または、 'toolStripContainer1.TopToolStripPanel.Controls.Add(toolStrip1) 'フォームにtoolStripContainer1を追加 Me.Controls.Add(toolStripContainer1) End Sub Private Sub toolStripButton1_Click(ByVal sender As Object, _ ByVal e As EventArgs) MessageBox.Show("toolStripButton1が押されたよ") End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ private ToolStripContainer toolStripContainer1; private ToolStrip toolStrip1; private ToolStripButton toolStripButton1; protected override void OnLoad(EventArgs e) { base.OnLoad(e); //ToolStripContainerの作成 toolStripContainer1 = new ToolStripContainer(); //フォームいっぱいに広げる toolStripContainer1.Dock = DockStyle.Fill; //右端だけドッキングできないようにする toolStripContainer1.RightToolStripPanelVisible = false; //ToolStripの作成 toolStrip1 = new ToolStrip(); //ToolStripButtonの作成 toolStripButton1 = new ToolStripButton(); //画像と文字列を表示する toolStripButton1.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText; //表示する画像の設定 toolStripButton1.Image = new Bitmap("Save.bmp"); toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta; //表示する文字列の設定 toolStripButton1.Text = "保存"; //クリックされた時のイベントハンドラ toolStripButton1.Click += new EventHandler(toolStripButton1_Click); //toolStrip1にアイテムを追加 toolStrip1.Items.Add(toolStripButton1); //toolStripContainer1の上にtoolStrip1を追加 toolStripContainer1.TopToolStripPanel.Join(toolStrip1); //または、 //toolStripContainer1.TopToolStripPanel.Controls.Add(toolStrip1); //フォームにtoolStripContainer1を追加 this.Controls.Add(toolStripContainer1); } private void toolStripButton1_Click(object sender, EventArgs e) { MessageBox.Show("toolStripButton1が押されたよ"); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ─────────────────────────────── ●ToolStripContainerの代わりにToolStripPanelを使う ToolStripContainerコントロールは、上下左右に1つずつ計4つの ToolStripPanelコントロールと、中央に1つのToolStripContentPanel コントロールを持ったコントロールです。ToolStripが ToolStripContainerの自由な位置に移動できるのは、実は ToolStripPanelコントロールのおかげです。ですので、例えばフォー ムの上部だけにToolStripを配置したい場合は、わざわざ ToolStripContainerを使わなくても、1つのToolStripPanelをフォー ムの上部に配置するだけで十分です。 さらにMDIの親フォームでは、ToolStripContainerを使用すると真ん 中はToolStripContentPanelとなっているため、子フォームを表示す る場所がなくなってしまいます。よってMDI親フォームでは ToolStripContainerではなく、ToolStripPanelを使用すべきです。 ToolStripPanelコントロールは、デフォルトでは、VS2005のツールボ ックスにありません。ツールボックスにToolStripPanelを表示するに は、ツールボックスで右クリックしてコンテキストメニューを表示し、 「アイテムの選択」を選択し、「ToolStripPanel」にチェックをつけ て、OKをクリックします。 もちろんデザイナを使用せずに、自分でコードを書くことによっても ToolStripPanelをフォームに配置できます。 以下にフォームの上部にToolStripPanelを1つだけ配置した例を示し ます。(このコードを実行するには、「Save.bmp」が必要です。画像 がない場合は、「表示する画像の設定」の部分を削除してください。) ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ Private topToolStripPanel As ToolStripPanel Private toolStrip1 As ToolStrip Private toolStripButton1 As ToolStripButton Protected Overrides Sub OnLoad(ByVal e As EventArgs) MyBase.OnLoad(e) 'ToolStripPanelの作成 topToolStripPanel = New ToolStripPanel() '水平方向にToolStripを並べるようにする topToolStripPanel.Orientation = Orientation.Horizontal '上部に配置する topToolStripPanel.Dock = DockStyle.Top 'ToolStripの作成 toolStrip1 = New ToolStrip() 'ToolStripButtonの作成 toolStripButton1 = New ToolStripButton() '画像と文字列を表示する toolStripButton1.DisplayStyle = _ ToolStripItemDisplayStyle.ImageAndText '表示する画像の設定 toolStripButton1.Image = New Bitmap("Save.bmp") toolStripButton1.ImageTransparentColor = _ System.Drawing.Color.Magenta '表示する文字列の設定 toolStripButton1.Text = "保存" 'クリックされた時のイベントハンドラ AddHandler toolStripButton1.Click, _ AddressOf toolStripButton1_Click 'toolStrip1にアイテムを追加 toolStrip1.Items.Add(toolStripButton1) 'topToolStripPanelの上にtoolStrip1を追加 topToolStripPanel.Join(toolStrip1) 'フォームにtoolStripContainer1を追加 Me.Controls.Add(topToolStripPanel) End Sub Private Sub toolStripButton1_Click(ByVal sender As Object, _ ByVal e As EventArgs) MessageBox.Show("toolStripButton1が押されたよ") End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ private ToolStripPanel topToolStripPanel; private ToolStrip toolStrip1; private ToolStripButton toolStripButton1; protected override void OnLoad(EventArgs e) { base.OnLoad(e); //ToolStripPanelの作成 topToolStripPanel = new ToolStripPanel(); //水平方向にToolStripを並べるようにする topToolStripPanel.Orientation = Orientation.Horizontal; //上部に配置する topToolStripPanel.Dock = DockStyle.Top; //ToolStripの作成 toolStrip1 = new ToolStrip(); //ToolStripButtonの作成 toolStripButton1 = new ToolStripButton(); //画像と文字列を表示する toolStripButton1.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText; //表示する画像の設定 toolStripButton1.Image = new Bitmap("Save.bmp"); toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta; //表示する文字列の設定 toolStripButton1.Text = "保存"; //クリックされた時のイベントハンドラ toolStripButton1.Click += new EventHandler(toolStripButton1_Click); //toolStrip1にアイテムを追加 toolStrip1.Items.Add(toolStripButton1); //topToolStripPanelの上にtoolStrip1を追加 topToolStripPanel.Join(toolStrip1); //フォームにtoolStripContainer1を追加 this.Controls.Add(topToolStripPanel); } private void toolStripButton1_Click(object sender, EventArgs e) { MessageBox.Show("toolStripButton1が押されたよ"); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ [URL]方法 : ToolStripPanel を MDI で使用する http://msdn2.microsoft.com/ja-jp/library/ms229727.aspx [URL]方法 : ToolStripPanel コントロールを持つ MDI フォームを作 成する http://msdn2.microsoft.com/ja-jp/library/ms229722.aspx ─────────────────────────────── ●MenuStripやStatusStripを移動できるようにする デフォルトでは、MenuStripやStatusStripコントロールにはコントロー ルを移動するためのグリップが表示されませんので、ユーザーがこれ らのコントロールを自由な位置に移動させることができません。 このグリップを表示するには、GripStyleプロパティをVisibleにし、 さらに、LayoutStyleプロパティをStackWithOverflowや HorizontalStackWithOverflowやVerticalStackWithOverflowとします。 ─────────────────────────────── ●同じ行にToolStripが2つ並ばないようにする デフォルトでは、ToolStripPanelの同じ行に複数のToolStripを配置 することができます。一行をまるまる1つのToolStripが占領し、別の ToolStripが同じ行に配置されないようにするには、ToolStripの StretchプロパティをTrueにします。これにより、ToolStripは ToolStripPanelの幅いっぱいに広がります。 逆にMenuStripやStatusStripはデフォルトでは同じ行に別の ToolStripを配置できないようになっていますが、Stretchプロパティ をFalseにすることにより、これを可能にします。 ─────────────────────────────── ●ToolStripPanelにあるToolStripの位置をプログラムで変更する ToolStripPanelにあるToolStripの位置は、Locationプロパティで変 更ができます。しかし、ToolStripPanelはToolStripを勝手に整列さ せるため、ToolStripの位置と大きさはLocationやSizeで指定した値 と全く同じになるとは限りません。 ToolStripPanelがどのようにToolStripを整列れるさせるかは、実際 にマウスでToolStripをつかんで移動させてみると分かります。つま り、ToolStripはToolStripPanel内のどこかの行に属することになる ため、その中間の位置に配置できませんし(上か下のどちらかの行に 配置されます)、ToolStripが一つもない行も許されず、そのような 位置を指定しても行が詰められます(例えば、現在1行しかないのに3 行目に移動させようとしても、2行目にしか移動しせん)。また、 ToolStripPanelの幅以上の位置を指定しても、適当な位置に戻されて しまいます。 ToolStrip.Locationプロパティ以外では、ToolStripPanel.Joinメソ ッドを使ってもToolStripの位置を変更できます。Joinメソッドは ToolStripPanelにToolStripを追加するためのメソッドですが、位置 を変更するためにも使用できます。Joinメソッドでは、座標だけでな く、移動先の行を指定することもできますし、別のToolStripPanelに 移動させるためにも使用できます。 ─────────────────────────────── ●ToolStripとToolStripItemの位置を保存、復元する .NET Framework 2.0では、ToolStripの位置を保存、復元する簡単な 方法が用意されています。 ToolStripManager.SaveSettingsメソッドでToolStripの位置を保存し、 ToolStripManager.LoadSettingsメソッドで復元することができます。 ToolStripManager.SaveSettingsで保存される情報は、ToolStripがあ るToolStripPanel、ToolStripのサイズと位置、表示しているか非表 示か、ToolStrip内のToolStripItemの順番です。つまりLoadSettings メソッドでは、これらが復元されます。 下の例では、フォームのOnLoadメソッドでToolStripの位置を復元し、 OnClosedメソッドで保存しています。なおフォームのサイズを復元し ている場合は、フォームのサイズを復元した後にLoadSettingsを呼び 出した方が良いでしょう。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ Protected Overrides Sub OnLoad(ByVal e As EventArgs) MyBase.OnLoad(e) 'ToolStripの位置を復元 ToolStripManager.LoadSettings(Me) End Sub Protected Overrides Sub OnClosed(ByVal e As EventArgs) MyBase.OnClosed(e) 'ToolStripの位置を保存 ToolStripManager.SaveSettings(Me) End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ protected override void OnLoad(EventArgs e) { base.OnLoad(e); //ToolStripの位置を復元 ToolStripManager.LoadSettings(this); } protected override void OnClosed(EventArgs e) { base.OnClosed(e); //ToolStripの位置を保存 ToolStripManager.SaveSettings(this); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ これらのメソッドを使う際には、幾つか注意しなければならない点が あります。 上記のようなコードを書いているフォームに新たなToolStripを追加 すると、そのToolStripは表示されません。ToolStripManager. LoadSettingsメソッドにより、新しく追加されたToolStripのVisible がFalseにされてしまいます。(MSDNには削除されるとありますが、 削除はされていません。)よってこのような場合は、LoadSettingsの 後で新しく追加されたToolStripのVisibleをTrueとするか、新しい ToolStripを追加してからLoadSettingsを呼び出すまでの間に、 SaveSettingsで保存するようにしてください。 また、VS2005のデザイナを使わずにToolStripを作成し、フォームに 追加した場合、そのToolStripの設定がSaveSettingsで保存されない 可能性があります。正しく保存されるようにするには、ToolStripの Nameプロパティにユニークな名前を設定する必要があるようです。 さらには、一番大きく、しかも厄介な問題として、2つ以上の ToolStripが同じToolStripPanelにあると、ほとんどの場合、 LoadSettingsメソッドはToolStripの位置を正常に復元することがで きません。LoadSettingsメソッドを複数回呼び出すことにより復元で きる場合もありますが、何回呼び出しても復元できないケースもあり ました。よって現時点では、ToolStripの位置を復元する目的では、 ToolStripManager.LoadSettingsメソッドはほとんど使い物になりま せん。 この問題は、LoadSettingsメソッドが正しい順番でToolStripの位置 を復元していないことが原因のようです。そこで試しに正しい順番で ToolStripの位置を復元するコードを書いてみたところ、正しく復元 されるようになりました(私が試した範囲内ですが)。 このコードは、次のような方針に基づいて書かれています。 まず設定の保存では、ToolStripPanelにあるToolStripの位置を、そ のToolStripの順番通りに保存します。つまり横長のToolStripPanel であれば、一番上の行の左端のToolStripから順番に、その順番も保 存されるようにして、その位置を保存します。(保存は、独自に行っ ています。ToolStripManager.SaveSettingsが保存したものを使った 方が良いかもしれませんが、面倒なので。) 設定の復元では、まずはじめに現在ToolStripPanel内にあるすべての コントロールを削除してから、順番通りにToolStripを元の位置に追 加していきます。 このコードはToolStripの位置を保存、復元するだけで、サイズや表 示・非表示等の復元は行っていないため、それ以外の設定を復元する ために、ToolStripManager.SaveSettingsとLoadSettingsメソッドも 呼び出す必要があります。(ここで示すコードには、組み込まれてい ます。このコードをちょっと改良すれば、その必要もなくなりそうで すが。) また、すべてのToolStripPanelのNameプロパティが設定されている必 要があります。つまり、ToolStripContainerコントロールの上下左右 のToolStripPanelのNameプロパティも設定されている必要があります (デフォルトでは設定されていません)。 使い方は、ToolStripManagerクラスと同じように、 ToolStripManager2.SaveSettingsで保存し、ToolStripManager2. LoadSettingsで復元します。ちょっといい加減かもしれませんので、 あまり信用しない方が良いでしょう。(コードは、C#のみです。) もっと良い方法をご存知の方は、ぜひご連絡ください。 ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; public class ToolStripManager2 { internal class ToolStripSettings : System.Configuration.ApplicationSettingsBase { /// /// ToolStripPanelにあるToolStripを列に分けて保存する /// [System.Configuration.UserScopedSetting, System.Configuration.DefaultSettingValue("")] public List> Rows { get { return (List>)this["Rows"]; } set { this["Rows"] = value; } } public ToolStripSettings(string settingsKey) : base(settingsKey) { } } /// /// 保存するToolStripの情報 /// public class ToolStripInfo : IComparable { public string Name = ""; public Point Location = Point.Empty; public ToolStripInfo(ToolStrip ts) { this.Name = ts.Name; this.Location = ts.Location; } public ToolStripInfo() { } public int CompareTo(ToolStripInfo other) { if (this.Location.X == other.Location.X) { return this.Location.Y - other.Location.Y; } return this.Location.X - other.Location.X; } } /// /// sourceFormに配置されたToolStripPanel内のToolStripの位置を保存する /// /// public static void SaveSettings(Form sourceForm) { ToolStripManager.SaveSettings(sourceForm); ToolStripManager2.InternalSaveSettings(sourceForm); } /// /// sourceFormに配置されたToolStripPanel内のToolStripの位置を復元する /// /// public static void LoadSettings(Form sourceForm) { ToolStripManager.LoadSettings(sourceForm); ToolStripManager2.InternalLoadSettings(sourceForm); } internal static void InternalSaveSettings(Control owner) { //owner内のToolStripPanelを探す List toolStripPanels = new List(); FindControls(typeof(ToolStripPanel), owner.Controls, ref toolStripPanels); foreach (ToolStripPanel tsp in toolStripPanels) { if (string.IsNullOrEmpty(tsp.Name)) continue; List> rowsList = new List>(); foreach (ToolStripPanelRow r in tsp.Rows) { //ToolStripPanelの列内のToolStripの情報を収集 List toolStripNames = new List(); foreach (Control con in r.Controls) { if (con is ToolStrip && !string.IsNullOrEmpty(con.Name)) { toolStripNames.Add( new ToolStripInfo((ToolStrip)con)); } } //列内の順番を並び替え toolStripNames.Sort(); rowsList.Add(toolStripNames); } //ToolStripPanelごとに保存する string skey = owner.GetType().FullName + "." + tsp.Name; ToolStripSettings settings = new ToolStripSettings(skey); settings.Rows = rowsList; settings.Save(); } } internal static void InternalLoadSettings(Control owner) { //owner内のToolStripPanelを探す List toolStripPanels = new List(); FindControls(typeof(ToolStripPanel), owner.Controls, ref toolStripPanels); foreach (ToolStripPanel tsp in toolStripPanels) { if (string.IsNullOrEmpty(tsp.Name)) continue; //ToolStripPanelの情報を読み込む string skey = owner.GetType().FullName + "." + tsp.Name; ToolStripSettings settings = new ToolStripSettings(skey); List> rowsList = settings.Rows; //ToolStripPanel内のToolStripを一時的にすべて削除する Dictionary toolstrips = new Dictionary(); foreach (Control c in tsp.Controls) { toolstrips.Add(c.Name, (ToolStrip)c); } tsp.Controls.Clear(); for (int i = 0; i < rowsList.Count; i++) { foreach (ToolStripInfo info in rowsList[i]) { //位置を設定するToolStripを探す ToolStrip ts = null; if (toolstrips.ContainsKey(info.Name)) { ts = toolstrips[info.Name]; } else { Control[] tss = owner.Controls.Find(info.Name, true); if ((tss != null) && (tss.Length == 1) && (tss[0] is ToolStrip)) { ts = (ToolStrip)tss[0]; } } //ToolStripの位置を変更する if (ts != null) { tsp.Join(ts, info.Location); } } } } } internal static void FindControls(Type findType, Control.ControlCollection conts, ref List foundList) { foreach (Control c in conts) { if (findType.IsAssignableFrom(c.GetType())) { foundList.Add(c); } if (c.Controls.Count > 0) { FindControls(findType, c.Controls, ref foundList); } } } } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ─────────────────────────────── ●特定のToolStripを指定したToolStripPanelにドッキングできない ようにする ToolStripは、同じフォーム内であれば、どこのToolStripPanelにも 移動できてしまいます。例えば、上下のToolStripPanelには移動でき るが、左右のToolStripPanelには移動できないようにできないもので しょうか? 基本的には、ToolStripPanelのControlAddedイベントで受け入れ可能 なToolStripかを調べ、受け入れられなければToolStripPanelの Controlsから削除し、元のToolStripPanelに戻すという方法になりそ うです。しかし、ToolStripが元のToolStripPanelから削除される直 前に発生するイベントがなく、削除されて始めて分かるため、元に戻 すToolStripの位置をあらかじめ記憶しておかなければなりません。 しかも、たとえそのようなコードを書いたとしても、正常に動作しま せん。ControlAddedイベントが発生しても、この時ToolStripはドラ ッグ中なので、この時点でToolStripを戻してもうまくいかないよう です。つまり、ToolStripがドロップされ、ToolStripの移動が完全に 終了してから、ToolStripを元に戻さなければなりません。 ToolStripの移動が終了したことを知るための方法はないかと探した ところ、.NET Framework 2.0から追加されたControl. MouseCaptureChangedイベントあたりが使えそうです。 以上のような方針で、ToolStripがToolStripContainer( toolStripContainer1)のBottomToolStripPanelに移動できないよう にするコードを書いてみました。ここでは、ToolStripの LocationChangedイベントでToolStripの位置を記憶するようにしてい ます。何回か試した範囲では、どうにかうまくいっているようです。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 'ToolStripの位置 Private toolStripParent As ToolStripPanel = Nothing Private toolStripLocation As Point = Point.Empty 'LocationChangedイベントハンドラ Private Sub toolStrip1_LocationChanged(ByVal sender As Object, _ ByVal e As EventArgs) Handles ToolStrip1.LocationChanged Dim ts As ToolStrip = CType(sender, ToolStrip) If ToolStripContainer1.BottomToolStripPanel.Equals(ts.Parent) _ AndAlso Not (toolStripParent Is Nothing) Then 'BottomToolStripPanelに移動させた時 'ここでToolStripをもとに戻すことができればよいのだが... ElseIf Not (ts.Parent Is Nothing) _ AndAlso TypeOf ts.Parent Is ToolStripPanel Then 'ToolStripの位置を記憶する toolStripParent = CType(ts.Parent, ToolStripPanel) toolStripLocation = ts.Location End If End Sub 'MouseCaptureChangedイベントハンドラ Private Sub toolStrip1_MouseCaptureChanged(ByVal sender As Object, _ ByVal e As EventArgs) Handles ToolStrip1.MouseCaptureChanged Dim ts As ToolStrip = CType(sender, ToolStrip) If ToolStripContainer1.BottomToolStripPanel.Equals(ts.Parent) _ AndAlso Not (toolStripParent Is Nothing) Then 'BottomToolStripPanelに移動させた時 'ToolStripを元の位置に戻す toolStripParent.Join(ts, toolStripLocation) End If End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //ToolStripの位置 private ToolStripPanel toolStripParent = null; private Point toolStripLocation = Point.Empty; //LocationChangedイベントハンドラ private void toolStrip1_LocationChanged(object sender, EventArgs e) { ToolStrip ts = (ToolStrip)sender; if (toolStripContainer1.BottomToolStripPanel.Equals(ts.Parent) && toolStripParent != null) { //BottomToolStripPanelに移動させた時 //ここでToolStripをもとに戻すことができればよいのだが... } else if (ts.Parent != null && ts.Parent is ToolStripPanel) { //ToolStripの位置を記憶する toolStripParent = (ToolStripPanel)ts.Parent; toolStripLocation = ts.Location; } } //MouseCaptureChangedイベントハンドラ private void toolStrip1_MouseCaptureChanged(object sender, EventArgs e) { ToolStrip ts = (ToolStrip)sender; if (toolStripContainer1.BottomToolStripPanel.Equals(ts.Parent) && toolStripParent != null) { //BottomToolStripPanelに移動させた時 //ToolStripを元の位置に戻す toolStripParent.Join(ts, toolStripLocation); } } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ もっと良い方法をご存知の方がいらっしゃれば、ぜひ教えてください。 ─────────────────────────────── 残念ながら、今回は紹介したいことの3分の1も紹介できませんでした。 ToolStripとToolStripContainerコントロールのTipsは、次回も続き ます。 =============================== ■ここで示したコードの多くはまずC#で書き、それを「C# to VB.NET Translator」でVB.NETのコードに変換し、修正を加えたものです。 [URL][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. ===============================