ToolStrip を既存の ToolStrip と並べて ToolStripPanel に追加しようとしています
-
03-07-2019 - |
質問
Visual Studio 2005 で .net 2.0 を使用しており、2 つの異なるツールストリップをフォームの上部に追加して並べて表示しようとしています。Word 2003 のように、各ツールストリップに 1 行を割り当てるのではなく、同じ行に複数のツールストリップを追加して、それらを並べて表示できるようにしたいと考えています。
そこで、ToolStripPanel を追加し、フォームの上部にドッキングしました (追加のパネルはすべて必要ないため、ToolStripContainer は使用しませんでした)。一番上にあるものだけが必要です)。両方のツールストリップを追加し、ストレッチ プロパティを False に設定しました。これらをデザイナー ウィンドウに並べて表示することはできますが、実行時に ToolStripPanel がツールストリップを分離し、各ツールストリップに独自の専用の行を与えます。さらに追い討ちをかけるかのように、デバッグを中止してデザイナーに戻ると、デザイナーがツールストリップを自分の行にも移動していることがわかりました。ここで私は何か間違ったことをしていますか?
一日中グーグル検索をしていて、ToolStripPanelRow オブジェクトに関する情報を見つけましたが、それにツールストリップを追加する簡単な方法が見つかりません。ToolStripPanelRow.Controls.Add メソッドなどはありません)、コントロール オブジェクトの配列を返す Controls() プロパティだけがあり、その配列に項目を追加しようとしてもあまりうまくいきませんでした。 。また、ToolStripPanel.Join メソッドに関するドキュメントも見つかりました。これで十分に機能するはずなので、3 つのオーバーロードすべてを試しましたが、宣伝どおりに機能しませんでした。何をしても、どのオプションを試しても、常に新しいツールストリップがパネルの上部の独自の行に追加され、他のすべては下に押し込まれます。
完全な開示のために、ToolStripPanel とツールストリップの 1 つを基本クラス フォームに追加しており、もう 1 つのツールストリップを基本クラス フォームから継承するサブクラス フォームに追加しようとしていることに注意してください。基本クラス フォームの ToolStripPanel と ToolStrip は両方とも「保護されたフレンド」として宣言されているため、これは機能するはずです。前述したように、サブクラス フォームのデザイナー ウィンドウを使用すると、(少なくとも一時的には) それを行うことができます。
誰かがこれを機能させるのを手伝ってくれたり、少なくとも機能しない理由を明らかにしたりできれば、私は非常に感謝します。
解決
LayoutEngineをオーバーロードできるように、カスタムToolStripPanelを作成しました。
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
namespace CustomGUI
{
class CustomToolStripPanel : ToolStripPanel
{
private LayoutEngine _layoutEngine;
public override LayoutEngine LayoutEngine
{
get
{
if (_layoutEngine == null) _layoutEngine = new CustomLayoutEngine();
return _layoutEngine;
}
}
public override Size GetPreferredSize(Size proposedSize)
{
Size size = base.GetPreferredSize(proposedSize);
foreach(Control control in Controls)
{
int newHeight = control.Height + control.Margin.Vertical + Padding.Vertical;
if (newHeight > size.Height) size.Height = newHeight;
}
return size;
}
}
}
次に、カスタムLayoutEngineがToolStripsをレイアウトします。
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
namespace CustomGUI
{
class CustomLayoutEngine : LayoutEngine
{
public override bool Layout(object container, LayoutEventArgs layoutEventArgs)
{
Control parent = container as Control;
Rectangle parentDisplayRectangle = parent.DisplayRectangle;
Control [] source = new Control[parent.Controls.Count];
parent.Controls.CopyTo(source, 0);
Point nextControlLocation = parentDisplayRectangle.Location;
foreach (Control c in source)
{
if (!c.Visible) continue;
nextControlLocation.Offset(c.Margin.Left, c.Margin.Top);
c.Location = nextControlLocation;
if (c.AutoSize)
{
c.Size = c.GetPreferredSize(parentDisplayRectangle.Size);
}
nextControlLocation.Y = parentDisplayRectangle.Y;
nextControlLocation.X += c.Width + c.Margin.Right + parent.Padding.Horizontal;
}
return false;
}
}
}
少し時間がかかったのは、1つのToolStripアイテムの場所/サイズを変更すると、コントロールが並べ替えられた状態でレイアウトが再起動されることです。そこで、レイアウトループの前にコントロールのコピーを取ります。 また、何らかの理由でAddRange(...)を使用してカスタムパネルにアイテムを追加することはできません。一度に1つずつ追加する必要があります。
役立つ希望( MSDN LayoutEngine Example 、ToolStripPanels用に修正)
Wyzfen
他のヒント
System.Windows.Forms.FlowLayoutPanelがジョブを実行できます。
ToolStripコントロールを正しい順序で配置します。
あなたの場合、独自のカスタム LayoutEngine を必要とするのではなく、ToolStrip の LayoutStyle を ToolStripLayoutStyle.horizontalStackWithOverflow に設定するだけで済むと思います。
私は尋ねました 違う質問 オーバーフローをより適切に制御するために動的アイテムを含むレイアウトを処理する方法に関する同様のトピックについて説明します。