我在Visual Studio 2005中使用.net 2.0,我试图在表单的顶部添加两个不同的工具条,以便它们并排显示。我希望它像Word 2003一样,你可以在同一行中添加多个工具条并让它们相互显示,而不是为每个工具条专用一行。
所以我添加了一个ToolStripPanel并将其停靠在表单的顶部(我没有使用ToolStripContainer,因为我不需要所有额外的面板;我只需要顶部的那个)。我添加了两个工具条并将其Stretch属性设置为False。我可以将它们并排显示在设计器窗口中,但在运行时,ToolStripPanel会分离工具条并为每个工具条提供自己的专用行。好像要侮辱伤害,当我停止调试并返回设计师时,我发现设计师正在将工具条移动到他们自己的行!我在这里做错了吗?
我整天都在谷歌搜索并发现了一些关于ToolStripPanelRow对象的信息,但是我没有看到向它添加工具条的简单方法(即它没有ToolStripPanelRow.Controls.Add方法或类似的东西),它所有的都是一个Controls()属性,它返回一个控件对象Array,我没有太多运气试图向该数组添加项目。我还发现了一些关于ToolStripPanel.Join方法的文档,这听起来应该可以完成这项工作,所以我尝试了所有3次重载,但它们不像宣传的那样工作。无论我做什么或我尝试哪些选项,它总是将新的工具条添加到面板顶部的自己的行上,并将其他所有内容向下推。
为了完全公开,我应该警告你我有ToolStripPanel和一个添加到基类表单的工具条,我试图将其他工具条添加到从基类表单继承的子类表单。基类表单中的ToolStripPanel和ToolStrip都声明为“受保护的朋友”,因此这应该有效。正如我所提到的,子类窗体的设计器窗口将允许我这样做(至少,一段时间)。
如果有人能帮助我解决这个问题,或者至少可以解释为什么不这样做,我将非常感激。
答案 0 :(得分:5)
我创建了一个自定义ToolStripPanel,以便我可以重载LayoutEngine;
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;
}
}
}
需要一段时间的一件事是,更改一个ToolStrip项的位置/大小将导致布局重新触发,并重新排序控件。所以我在布局循环之前获取控件的副本。 并且您无法使用AddRange(...)将项目添加到自定义面板由于某种原因 - 需要一次添加(...)它们。
希望有帮助(它基于MSDN LayoutEngine Example,已针对ToolStripPanels修复)
Wyzfen
答案 1 :(得分:2)
System.Windows.Forms.FlowLayoutPanel可以完成这项工作。
只需按正确的顺序放入ToolStrip控件。
答案 2 :(得分:1)
我认为在你的情况下,只需将ToolStrip上的LayoutStyle设置为ToolStripLayoutStyle.HorizontalStackWithOverflow而不需要自己的自定义LayoutEngine即可。
我问了different question关于如何使用动态项处理布局的类似主题,以便更好地控制溢出。