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

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

我正在将 .net 2.0 与 Visual Studio 2005 一起使用,并且我正在尝试将两个不同的工具条添加到表单顶部,以便它们并排显示。我希望它像 Word 2003 一样,您可以在其中将多个工具条添加到同一行并使它们彼此对齐显示,而不是为每个工具条指定一行。

所以我添加了一个 ToolStripPanel 并将它停靠在表单的顶部(我没有使用 ToolStripContainer 因为我不需要所有额外的面板;我只需要顶部的一个)。我添加了两个工具条并将它们的 Stretch 属性设置为 False。我可以让它们并排显示在设计器窗口中,但在运行时 ToolStripPanel 将工具条分开并为每个工具条提供自己的专用行。好像雪上加霜,当我停止调试并返回设计器时,我发现设计器也在将工具条移动到他们自己的行中!我在这里做错了吗?

我一整天都在谷歌上搜索并找到了一些关于 ToolStripPanelRow 对象的信息,但我没有看到向它添加工具条的简单方法(即它没有 ToolStripPanelRow.Controls.Add 方法或类似的方法),所有它有一个 Controls() 属性,它返回一个控制对象数组,我在尝试向该数组添加项目时运气不佳。我还找到了一些关于 ToolStripPanel.Join 方法的文档,听起来它应该可以完成这项工作,所以我尝试了所有 3 个重载,但它们并没有像宣传的那样工作。无论我做什么或尝试哪些选项,它总是将新的工具条添加到面板顶部的一行,并将其他所有内容向下推。

为了全面公开,我应该警告您,我已将 ToolStripPanel 和其中一个工具条添加到基类表单中,并且我正在尝试将另一个工具条添加到从基类表单继承的子类表单中。基类形式的 ToolStripPanel 和 ToolStrip 都被声明为“ protected friend ”,所以这应该可以工作。正如我所提到的,子类表单的设计器窗口将允许我这样做(至少在一段时间内)。

如果有人可以帮助我完成这项工作,或者至少阐明为什么不能这样做,我将不胜感激。

最佳答案

我创建了一个自定义 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 修复)

维兹芬

关于user-interface - 尝试将 ToolStrip 与现有 ToolStrip 并排添加到 ToolStripPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/403769/

相关文章:

.net-2.0 - .net 中的 MSMQ 作为服务

c# - 数据表转 JSON

Python tkinter spinbox 和 optionmenu 之间的区别

C# IFilter 在解决方案中安装不正确?

c++ - 在 C++ 中使用多重继承时 ESP 无效 (VS2005)

用于 VS2005 的 C++ std::tr2

visual-studio-2008 - 将 .NET 2.0 (VS2005) C# 解决方案迁移到 .NET 3.5 (VS2008) - 会出现什么问题?

javascript - 如何使用 NightwatchJS 从下拉列表中选择一个有效的随机值?

java - 如何将 JLabels 定位到 Java GUI 上的绝对位置

Python gui - 将输入传递给脚本