注意:ここで紹介している方法は、.NET Framework 2.0以降でのみ使用できます。
ToolStripは、同じフォーム内であれば、どこのToolStripPanel(ToolStripContainerの上下左右の部分)にも移動できてしまいます。例えば、上下の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の位置を記憶するようにしています。何回か試した範囲では、どうにかうまくいっているようです。
'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
//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); } }
もっと良い方法をご存知の方がいらっしゃれば、ぜひ教えてください。
(この記事は、「.NETプログラミング研究」で紹介したものを基にしています。)