尝试将ToolStrip与现有ToolStrip并排添加到ToolStripPanel

时间:2008-12-31 18:49:11

标签: user-interface visual-studio-2005 .net-2.0 toolstrip toolstrippanel

我在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都声明为“受保护的朋友”,因此这应该有效。正如我所提到的,子类窗体的设计器窗口将允许我这样做(至少,一段时间)。

如果有人能帮助我解决这个问题,或者至少可以解释为什么不这样做,我将非常感激。

3 个答案:

答案 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.Horizo​​ntalStackWithOverflow而不需要自己的自定义LayoutEngine即可。

我问了different question关于如何使用动态项处理布局的类似主题,以便更好地控制溢出。